mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-01 23:47:50 +00:00
implement NormalNormalizer
This commit is contained in:
parent
2fb30322ff
commit
a8266f99b1
@ -98,4 +98,88 @@ public final class MathUtil {
|
||||
public static long squash(int first, int last) {
|
||||
return (((long) first) << 32) | (last & 0xffffffffL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp value to range of [-1, 1]
|
||||
*
|
||||
* @param in Value to clamp
|
||||
* @return Clamped value
|
||||
*/
|
||||
public static double clamp(double in) {
|
||||
return FastMath.min(FastMath.max(in, -1), 1);
|
||||
}
|
||||
|
||||
public static double compute(double p, double mu, double sigma) {
|
||||
if(p < 0 || p > 1)
|
||||
throw new IllegalArgumentException("Probability must be in range [0, 1]");
|
||||
if(sigma < 0)
|
||||
throw new IllegalArgumentException("Standard deviation must be positive.");
|
||||
if(p == 0)
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
if(p == 1)
|
||||
return Double.POSITIVE_INFINITY;
|
||||
if(sigma == 0)
|
||||
return mu;
|
||||
double q, r, val;
|
||||
|
||||
q = p - 0.5;
|
||||
|
||||
if(FastMath.abs(q) <= .425) {
|
||||
r = .180625 - q * q;
|
||||
val =
|
||||
q * (((((((r * 2509.0809287301226727 +
|
||||
33430.575583588128105) * r + 67265.770927008700853) * r +
|
||||
45921.953931549871457) * r + 13731.693765509461125) * r +
|
||||
1971.5909503065514427) * r + 133.14166789178437745) * r +
|
||||
3.387132872796366608)
|
||||
/ (((((((r * 5226.495278852854561 +
|
||||
28729.085735721942674) * r + 39307.89580009271061) * r +
|
||||
21213.794301586595867) * r + 5394.1960214247511077) * r +
|
||||
687.1870074920579083) * r + 42.313330701600911252) * r + 1);
|
||||
} else {
|
||||
if(q > 0) {
|
||||
r = 1 - p;
|
||||
} else {
|
||||
r = p;
|
||||
}
|
||||
|
||||
r = FastMath.sqrt(-FastMath.log(r));
|
||||
|
||||
if(r <= 5) {
|
||||
r += -1.6;
|
||||
val = (((((((r * 7.7454501427834140764e-4 +
|
||||
.0227238449892691845833) * r + .24178072517745061177) *
|
||||
r + 1.27045825245236838258) * r +
|
||||
3.64784832476320460504) * r + 5.7694972214606914055) *
|
||||
r + 4.6303378461565452959) * r +
|
||||
1.42343711074968357734)
|
||||
/ (((((((r *
|
||||
1.05075007164441684324e-9 + 5.475938084995344946e-4) *
|
||||
r + .0151986665636164571966) * r +
|
||||
.14810397642748007459) * r + .68976733498510000455) *
|
||||
r + 1.6763848301838038494) * r +
|
||||
2.05319162663775882187) * r + 1);
|
||||
} else { /* very close to 0 or 1 */
|
||||
r += -5;
|
||||
val = (((((((r * 2.01033439929228813265e-7 +
|
||||
2.71155556874348757815e-5) * r +
|
||||
.0012426609473880784386) * r + .026532189526576123093) *
|
||||
r + .29656057182850489123) * r +
|
||||
1.7848265399172913358) * r + 5.4637849111641143699) *
|
||||
r + 6.6579046435011037772)
|
||||
/ (((((((r *
|
||||
2.04426310338993978564e-15 + 1.4215117583164458887e-7) *
|
||||
r + 1.8463183175100546818e-5) * r +
|
||||
7.868691311456132591e-4) * r + .0148753612908506148525)
|
||||
* r + .13692988092273580531) * r +
|
||||
.59983220655588793769) * r + 1);
|
||||
}
|
||||
|
||||
if(q < 0.0) {
|
||||
val = -val;
|
||||
}
|
||||
}
|
||||
|
||||
return mu + sigma * val;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
package com.dfsek.terra.api.math.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
|
||||
public class LinearNormalizer extends Normalizer {
|
||||
private final double min;
|
@ -0,0 +1,43 @@
|
||||
package com.dfsek.terra.api.math.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.math.MathUtil;
|
||||
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public class NormalNormalizer extends Normalizer {
|
||||
|
||||
private final double[] lookup;
|
||||
|
||||
public NormalNormalizer(NoiseSampler sampler, int buckets, double mean, double standardDeviation) {
|
||||
super(sampler);
|
||||
this.lookup = new double[buckets];
|
||||
|
||||
for(int i = 0; i < buckets; i++) {
|
||||
lookup[i] = MathUtil.compute((double) i / buckets, mean, standardDeviation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public double normalize(double in) {
|
||||
int start = 0;
|
||||
int end = lookup.length - 1;
|
||||
while(start + 1 < end) {
|
||||
int mid = start + (end - start) / 2;
|
||||
if(lookup[mid] <= in) {
|
||||
start = mid;
|
||||
} else {
|
||||
end = mid;
|
||||
}
|
||||
}
|
||||
double left = FastMath.abs(lookup[start] - in);
|
||||
double right = FastMath.abs(lookup[end] - in);
|
||||
|
||||
double fin;
|
||||
if(left <= right) {
|
||||
fin = (double) start / (lookup.length);
|
||||
} else fin = (double) end / (lookup.length);
|
||||
|
||||
return (fin - 0.5) * 2;
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
package com.dfsek.terra.api.math.noise.normalizer;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
|
||||
public abstract class Normalizer implements NoiseSampler {
|
||||
private final NoiseSampler sampler;
|
||||
@ -30,6 +32,6 @@ public abstract class Normalizer implements NoiseSampler {
|
||||
}
|
||||
|
||||
public enum NormalType {
|
||||
LINEAR, NONE
|
||||
LINEAR, NONE, NORMAL
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import com.dfsek.terra.api.core.TerraPlugin;
|
||||
import com.dfsek.terra.api.math.GridSpawn;
|
||||
import com.dfsek.terra.api.math.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.math.Range;
|
||||
import com.dfsek.terra.api.math.noise.samplers.Normalizer;
|
||||
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
|
||||
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
|
||||
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
|
||||
import com.dfsek.terra.config.loaders.MaterialSetLoader;
|
||||
|
@ -5,8 +5,8 @@ import com.dfsek.tectonic.exception.ConfigException;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.api.math.noise.samplers.Normalizer;
|
||||
import com.dfsek.terra.world.generation.config.NoiseBuilder;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
@ -3,10 +3,11 @@ package com.dfsek.terra.world.generation.config;
|
||||
import com.dfsek.tectonic.annotations.Default;
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer;
|
||||
import com.dfsek.terra.api.math.noise.normalizer.NormalNormalizer;
|
||||
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.api.math.noise.samplers.LinearNormalizer;
|
||||
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
import com.dfsek.terra.api.math.noise.samplers.Normalizer;
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class NoiseBuilder implements ConfigTemplate {
|
||||
@ -94,6 +95,14 @@ public class NoiseBuilder implements ConfigTemplate {
|
||||
@Default
|
||||
private double linearMax = 1D;
|
||||
|
||||
@Value("normalize.normal.mean")
|
||||
@Default
|
||||
private double mean = 0D;
|
||||
|
||||
@Value("normalize.normal.standard-deviation")
|
||||
@Default
|
||||
private double stdDev = 0.75D;
|
||||
|
||||
|
||||
public NoiseSampler build(int seed) {
|
||||
FastNoiseLite noise = new FastNoiseLite(seed + seedOffset);
|
||||
@ -121,7 +130,8 @@ public class NoiseBuilder implements ConfigTemplate {
|
||||
noise.setRotationType3D(rotationType3D);
|
||||
|
||||
noise.setFrequency(frequency);
|
||||
if(!normalType.equals(Normalizer.NormalType.NONE)) return new LinearNormalizer(noise, linearMin, linearMax);
|
||||
if(normalType.equals(Normalizer.NormalType.LINEAR)) return new LinearNormalizer(noise, linearMin, linearMax);
|
||||
else if(normalType.equals(Normalizer.NormalType.NORMAL)) return new NormalNormalizer(noise, 16384, mean, stdDev);
|
||||
return noise;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user