diff --git a/src/main/java/com/volmit/iris/object/IrisFeaturePositional.java b/src/main/java/com/volmit/iris/object/IrisFeaturePositional.java new file mode 100644 index 000000000..c2c6f8670 --- /dev/null +++ b/src/main/java/com/volmit/iris/object/IrisFeaturePositional.java @@ -0,0 +1,164 @@ +package com.volmit.iris.object; + +import com.google.gson.Gson; +import com.volmit.iris.scaffold.cache.AtomicCache; +import com.volmit.iris.util.*; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +@Data +@DontObfuscate +@NoArgsConstructor +@Desc("Represents an Iris zone") +public class IrisFeaturePositional { + public IrisFeaturePositional(int x, int z, IrisFeature feature) + { + this.x = x; + this.z = z; + this.feature = feature; + } + + @Required + @DontObfuscate + @Desc("The x coordinate of this zone") + private int x; + + @Required + @DontObfuscate + @Desc("The z coordinate of this zone") + private int z; + + @Required + @DontObfuscate + @Desc("The Terrain Feature to apply") + private IrisFeature feature; + + private transient AtomicCache provider = new AtomicCache<>(); + private transient AtomicCache actualRadius = new AtomicCache<>(); + private static double BLOCK = 1D / 256D; + + public static IrisFeaturePositional read(DataInputStream s) throws IOException + { + return new Gson().fromJson(s.readUTF(), IrisFeaturePositional.class); + } + + public void write(DataOutputStream s) throws IOException { + s.writeUTF(new Gson().toJson(this)); + } + + public boolean shouldFilter(double x, double z) + { + double actualRadius = IrisInterpolation.getRealRadius(getFeature().getInterpolator(), (int)x, (int)z, getFeature().getInterpolationRadius()); + double dist2 = distance2(x, z); + + if(getFeature().isInvertZone()) { + if (dist2 < Math.pow(getFeature().getBlockRadius() - actualRadius, 2)) { + return false; + } + } + + if(dist2 > Math.pow(getFeature().getBlockRadius() + actualRadius, 2)) + { + return false; + } + + return true; + } + + public double getStrength(double x, double z) + { + double actualRadius = IrisInterpolation.getRealRadius(getFeature().getInterpolator(), (int)x, (int)z, getFeature().getInterpolationRadius()); + double dist2 = distance2(x, z); + + if(getFeature().isInvertZone()) + { + if (dist2 < Math.pow(getFeature().getBlockRadius() - actualRadius, 2)) + { + return 0; + } + + NoiseProvider d = provider.aquire(this::getNoiseProvider); + double s = IrisInterpolation.getNoise(getFeature().getInterpolator(), (int)x, (int)z, getFeature().getInterpolationRadius(), d); + + if(s <= 0) + { + return 0; + } + + return getFeature().getStrength() * s; + } + + else + { + if(dist2 > Math.pow(getFeature().getBlockRadius() + actualRadius, 2)) + { + return 0; + } + + NoiseProvider d = provider.aquire(this::getNoiseProvider); + double s = IrisInterpolation.getNoise(getFeature().getInterpolator(), (int)x, (int)z, getFeature().getInterpolationRadius(), d); + + if(s <= 0) + { + return 0; + } + + return getFeature().getStrength() * s; + } + } + + public double getObjectChanceModifier(double x, double z) + { + if(getFeature().getObjectChance()>=1) + { + return getFeature().getObjectChance(); + } + + return M.lerp(1, getFeature().getObjectChance(), getStrength(x, z)); + } + + public double filter(double x, double z, double noise) { + double s = getStrength(x, z); + + if(s <= 0) + { + return noise; + } + + double fx = noise; + + if(getFeature().getConvergeToHeight() >= 0) + { + fx = getFeature().getConvergeToHeight(); + } + + fx *= getFeature().getMultiplyHeight(); + fx += getFeature().getShiftHeight(); + + return M.lerp(noise, fx, s); + } + + public double distance(double x, double z) { + return Math.sqrt(Math.pow(this.x - x, 2) + Math.pow(this.z - z, 2)); + } + + public double distance2(double x, double z) { + return Math.pow(this.x - x, 2) + Math.pow(this.z - z, 2); + } + + private NoiseProvider getNoiseProvider() { + if(getFeature().isInvertZone()) + { + return (x, z) -> distance(x, z) > getFeature().getBlockRadius() ? 1D : 0D; + } + + else + { + return (x, z) -> distance(x, z) < getFeature().getBlockRadius() ? 1D : 0D; + } + } +}