added cache and docs
This commit is contained in:
1 parent
ee88f153bb
commit
1a873be361
3 files changed
+97
-32
No files matched your search
@@ -2732,6 +2732,30 @@ public class Expression
|
|||||||
* map(range(10), str('%.1f',rand(_))) => [0.0, 0.4, 0.6, 1.9, 2.8, 3.8, 5.3, 2.2, 1.6, 5.6]
|
* map(range(10), str('%.1f',rand(_))) => [0.0, 0.4, 0.6, 1.9, 2.8, 3.8, 5.3, 2.2, 1.6, 5.6]
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
* <h3><code>perlin(x), perlin(x,y), perlin(x,y,z), perlin(x,y,z,seed)</code></h3>
|
||||||
|
* <p>returns a noise value from <code>0.0</code> to <code>1.0</code> (roughly) for 1, 2 or 3 dimensional coordinate. The default seed it samples from is <code>0</code>, but seed can be
|
||||||
|
* specified as a 4th argument as well. In case you need 1D or 2D noise values with custom seed, use <code>null</code>
|
||||||
|
* for <code>z</code>, or <code>y</code> and <code>z</code> arguments respectively.</p>
|
||||||
|
* <p> Perlin noise is based on a square grid and generates rougher maps comparing to Simplex, which is creamier,
|
||||||
|
* but the in-game implementation allows to sample up to 3D noise. Querying for lower-dimensional result, rather than
|
||||||
|
* affixing unused dimensions to constants has a speed benefit,
|
||||||
|
* </p>
|
||||||
|
* <p>Thou shall not sample from noise changing seed frequently. Scarpet will keep track of the last 256 perlin seeds used for sampling
|
||||||
|
* providing similar speed comparing to the default seed of <code>0</code>. In case the app engine uses more than 256 seeds at the same time,
|
||||||
|
* switching between them can get much more expensive.</p>
|
||||||
|
*
|
||||||
|
* <h3><code>simplex(x,y), simplex(x,y,seed)</code></h3>
|
||||||
|
* <p>returns a noise value from <code>0.0</code> to <code>1.0</code> (roughly) for 2 dimensional coordinate.
|
||||||
|
* The default seed it samples from is <code>0</code>, but seed can be
|
||||||
|
* specified as a 3rd argument as well</p>
|
||||||
|
* <p> Simplex noise is based on a triangular grid and generates smoother maps comparing to Perlin,
|
||||||
|
* but the in-game implementation only allows to sample 2D noise. To sample 1D simplex noise, affix other coordinate
|
||||||
|
* to a constant.
|
||||||
|
* </p>
|
||||||
|
* <p>Thou shall not sample from noise changing seed frequently. Scarpet will keep track of the last 256 simplex seeds used for sampling
|
||||||
|
* providing similar speed comparing to the default seed of <code>0</code>. In case the app engine uses more than 256 seeds at the same time,
|
||||||
|
* switching between them can get much more expensive.</p>
|
||||||
|
*
|
||||||
* <h3><code>print(expr)</code></h3>
|
* <h3><code>print(expr)</code></h3>
|
||||||
* <p>prints the value of the expression to chat.
|
* <p>prints the value of the expression to chat.
|
||||||
* Passes the result of the argument to the output unchanged, so <code>print</code>-statements can
|
* Passes the result of the argument to the output unchanged, so <code>print</code>-statements can
|
||||||
@@ -2975,46 +2999,60 @@ public class Expression
|
|||||||
return (cc, tt) -> retval;
|
return (cc, tt) -> retval;
|
||||||
});
|
});
|
||||||
|
|
||||||
addLazyFunction("perlin", 3, (c, t, lv) -> {
|
addLazyFunction("perlin", -1, (c, t, lv) -> {
|
||||||
// add seed cache
|
PerlinNoiseSampler sampler;
|
||||||
Value ret;
|
Value x, y, z;
|
||||||
Value x = lv.get(0).evalValue(c);
|
|
||||||
Value y = lv.get(1).evalValue(c);
|
|
||||||
Value z = lv.get(2).evalValue(c);
|
|
||||||
|
|
||||||
if (z instanceof NullValue)
|
if (lv.size() >= 4)
|
||||||
{
|
{
|
||||||
if (y instanceof NullValue)
|
x = lv.get(0).evalValue(c);
|
||||||
{
|
y = lv.get(1).evalValue(c);
|
||||||
ret = new NumericValue(PerlinNoiseSampler.instance.sample1d(
|
z = lv.get(2).evalValue(c);
|
||||||
NumericValue.asNumber(x).getDouble()
|
sampler = PerlinNoiseSampler.getPerlin(NumericValue.asNumber(lv.get(3).evalValue(c)).getLong());
|
||||||
));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = new NumericValue(PerlinNoiseSampler.instance.sample2d(
|
|
||||||
NumericValue.asNumber(x).getDouble(),
|
|
||||||
NumericValue.asNumber(y).getDouble()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = new NumericValue(PerlinNoiseSampler.instance.sample3d(
|
sampler = PerlinNoiseSampler.instance;
|
||||||
|
y = Value.NULL;
|
||||||
|
z = Value.NULL;
|
||||||
|
if (lv.size() == 0 )
|
||||||
|
throw new InternalExpressionException("'perlin' requires at least one dimension to sample from");
|
||||||
|
x = NumericValue.asNumber(lv.get(0).evalValue(c));
|
||||||
|
if (lv.size() > 1)
|
||||||
|
{
|
||||||
|
y = NumericValue.asNumber(lv.get(1).evalValue(c));
|
||||||
|
if (lv.size() > 2)
|
||||||
|
z = NumericValue.asNumber(lv.get(2).evalValue(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double result;
|
||||||
|
|
||||||
|
if (z instanceof NullValue)
|
||||||
|
if (y instanceof NullValue)
|
||||||
|
result = sampler.sample1d(NumericValue.asNumber(x).getDouble());
|
||||||
|
else
|
||||||
|
result = sampler.sample2d(NumericValue.asNumber(x).getDouble(), NumericValue.asNumber(y).getDouble());
|
||||||
|
else
|
||||||
|
result = sampler.sample3d(
|
||||||
NumericValue.asNumber(x).getDouble(),
|
NumericValue.asNumber(x).getDouble(),
|
||||||
NumericValue.asNumber(y).getDouble(),
|
NumericValue.asNumber(y).getDouble(),
|
||||||
NumericValue.asNumber(z).getDouble()
|
NumericValue.asNumber(z).getDouble());
|
||||||
));
|
Value ret = new NumericValue(result);
|
||||||
}
|
|
||||||
return (cc, tt) -> ret;
|
return (cc, tt) -> ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
addLazyFunction("simplex", 2, (c, t, lv) -> {
|
addLazyFunction("simplex", -1, (c, t, lv) -> {
|
||||||
// add seed cache
|
SimplexNoiseSampler sampler;
|
||||||
|
if (lv.size() == 2)
|
||||||
|
sampler = SimplexNoiseSampler.instance;
|
||||||
|
else if (lv.size() == 3)
|
||||||
|
sampler = SimplexNoiseSampler.getSimplex(NumericValue.asNumber(lv.get(2).evalValue(c)).getLong());
|
||||||
|
else
|
||||||
|
throw new InternalExpressionException("'simplex' requires two or three arguments");
|
||||||
double x = NumericValue.asNumber(lv.get(0).evalValue(c)).getDouble();
|
double x = NumericValue.asNumber(lv.get(0).evalValue(c)).getDouble();
|
||||||
double y = NumericValue.asNumber(lv.get(1).evalValue(c)).getDouble();
|
double y = NumericValue.asNumber(lv.get(1).evalValue(c)).getDouble();
|
||||||
//double z = NumericValue.asNumber(lv.get(2).evalValue(c)).getDouble();
|
Value value = new NumericValue(sampler.sample(x,y));
|
||||||
Value value = new NumericValue(SimplexNoiseSampler.instance.sample(x,y));
|
|
||||||
return (cc, tt) -> value;
|
return (cc, tt) -> value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package carpet.script.utils;
|
package carpet.script.utils;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
// extracted from import net.minecraft.util.math.noise.PerlinNoiseSampler
|
||||||
public class PerlinNoiseSampler {
|
public class PerlinNoiseSampler {
|
||||||
protected static final int[][] gradients3d = new int[][]{
|
protected static final int[][] gradients3d = new int[][]{
|
||||||
{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0},
|
{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0},
|
||||||
@@ -17,6 +21,14 @@ public class PerlinNoiseSampler {
|
|||||||
public final double originY;
|
public final double originY;
|
||||||
public final double originZ;
|
public final double originZ;
|
||||||
public static PerlinNoiseSampler instance = new PerlinNoiseSampler(new Random(0));
|
public static PerlinNoiseSampler instance = new PerlinNoiseSampler(new Random(0));
|
||||||
|
public static Map<Long, PerlinNoiseSampler> samplers = new Long2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
public static PerlinNoiseSampler getPerlin(long aLong)
|
||||||
|
{
|
||||||
|
if (samplers.size() > 256)
|
||||||
|
samplers.clear();
|
||||||
|
return samplers.computeIfAbsent(aLong, seed -> new PerlinNoiseSampler(new Random(seed)));
|
||||||
|
}
|
||||||
|
|
||||||
public PerlinNoiseSampler(Random random) {
|
public PerlinNoiseSampler(Random random) {
|
||||||
this.originX = random.nextDouble() * 256.0D;
|
this.originX = random.nextDouble() * 256.0D;
|
||||||
@@ -38,6 +50,8 @@ public class PerlinNoiseSampler {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//3D
|
//3D
|
||||||
public double sample3d(double x, double y, double z) {//, double d, double e) {
|
public double sample3d(double x, double y, double z) {//, double d, double e) {
|
||||||
double f = x + this.originX;
|
double f = x + this.originX;
|
||||||
@@ -61,7 +75,7 @@ public class PerlinNoiseSampler {
|
|||||||
t = 0.0D;
|
t = 0.0D;
|
||||||
}*/
|
}*/
|
||||||
//return this.sample(i, j, k, l, m - t, n, o, p, q);
|
//return this.sample(i, j, k, l, m - t, n, o, p, q);
|
||||||
return this.sample3d(i, j, k, l, m, n, o, p, q);
|
return this.sample3d(i, j, k, l, m, n, o, p, q)/2+0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double sample3d(int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX, double fadeLocalY, double fadeLocalZ) {
|
private double sample3d(int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX, double fadeLocalY, double fadeLocalZ) {
|
||||||
@@ -105,7 +119,7 @@ public class PerlinNoiseSampler {
|
|||||||
double m = g - (double)j;
|
double m = g - (double)j;
|
||||||
double o = perlinFade(l);
|
double o = perlinFade(l);
|
||||||
double p = perlinFade(m);
|
double p = perlinFade(m);
|
||||||
return this.sample2d(i, j, l, m, o, p);
|
return this.sample2d(i, j, l, m, o, p)/2+0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double sample2d(int sectionX, int sectionY, double localX, double localY, double fadeLocalX, double fadeLocalY) {
|
private double sample2d(int sectionX, int sectionY, double localX, double localY, double fadeLocalX, double fadeLocalY) {
|
||||||
@@ -138,7 +152,7 @@ public class PerlinNoiseSampler {
|
|||||||
int i = floor(f);
|
int i = floor(f);
|
||||||
double l = f - (double)i;
|
double l = f - (double)i;
|
||||||
double o = perlinFade(l);
|
double o = perlinFade(l);
|
||||||
return this.sample1d(i, l, o);
|
return this.sample1d(i, l, o)+0.5;
|
||||||
}
|
}
|
||||||
private double sample1d(int sectionX, double localX, double fadeLocalX) {
|
private double sample1d(int sectionX, double localX, double fadeLocalX) {
|
||||||
double d = grad1d(this.getGradient(sectionX), localX);
|
double d = grad1d(this.getGradient(sectionX), localX);
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
package carpet.script.utils;
|
package carpet.script.utils;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
// extracted from import net.minecraft.util.math.noise.SimplexNoiseSampler
|
||||||
public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
||||||
private static final double sqrt3 = Math.sqrt(3.0D);
|
private static final double sqrt3 = Math.sqrt(3.0D);
|
||||||
private static final double SKEW_FACTOR_2D;
|
private static final double SKEW_FACTOR_2D;
|
||||||
private static final double UNSKEW_FACTOR_2D;
|
private static final double UNSKEW_FACTOR_2D;
|
||||||
|
|
||||||
public static SimplexNoiseSampler instance = new SimplexNoiseSampler(new Random(0));
|
public static SimplexNoiseSampler instance = new SimplexNoiseSampler(new Random(0));
|
||||||
|
public static Map<Long, SimplexNoiseSampler> samplers = new Long2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
public static SimplexNoiseSampler getSimplex(long aLong)
|
||||||
|
{
|
||||||
|
if (samplers.size() > 256)
|
||||||
|
samplers.clear();
|
||||||
|
return samplers.computeIfAbsent(aLong, seed -> new SimplexNoiseSampler(new Random(seed)));
|
||||||
|
}
|
||||||
|
|
||||||
public SimplexNoiseSampler(Random random) {
|
public SimplexNoiseSampler(Random random) {
|
||||||
super(random);
|
super(random);
|
||||||
@@ -57,7 +69,8 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
|||||||
double aa = this.grad(v, h, k, 0.0D, 0.5D);
|
double aa = this.grad(v, h, k, 0.0D, 0.5D);
|
||||||
double ab = this.grad(w, p, q, 0.0D, 0.5D);
|
double ab = this.grad(w, p, q, 0.0D, 0.5D);
|
||||||
double ac = this.grad(z, r, s, 0.0D, 0.5D);
|
double ac = this.grad(z, r, s, 0.0D, 0.5D);
|
||||||
return 70.0D * (aa + ab + ac);
|
//return 70.0D * (aa + ab + ac);
|
||||||
|
return 35.0D * (aa + ab + ac)+0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|||||||
Reference in new issue
Block a user