hytale-server/com/hypixel/hytale/procedurallib/logic/CellNoise.java

269 lines
9.1 KiB
Java

package com.hypixel.hytale.procedurallib.logic;
import com.hypixel.hytale.math.util.HashUtil;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.math.util.TrigMathUtil;
import com.hypixel.hytale.procedurallib.NoiseFunction;
import com.hypixel.hytale.procedurallib.logic.cell.CellDistanceFunction;
import com.hypixel.hytale.procedurallib.logic.cell.evaluator.PointEvaluator;
import com.hypixel.hytale.procedurallib.property.NoiseProperty;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class CellNoise implements NoiseFunction {
protected final CellDistanceFunction distanceFunction;
protected final PointEvaluator pointEvaluator;
protected final CellNoise.CellFunction cellFunction;
@Nullable
protected final NoiseProperty noiseLookup;
public CellNoise(
CellDistanceFunction distanceFunction, PointEvaluator pointEvaluator, CellNoise.CellFunction cellFunction, @Nullable NoiseProperty noiseLookup
) {
this.distanceFunction = distanceFunction;
this.pointEvaluator = pointEvaluator;
this.cellFunction = cellFunction;
this.noiseLookup = noiseLookup;
}
public CellDistanceFunction getDistanceFunction() {
return this.distanceFunction;
}
public CellNoise.CellFunction getCellFunction() {
return this.cellFunction;
}
@Nullable
public NoiseProperty getNoiseLookup() {
return this.noiseLookup;
}
@Override
public double get(int seed, int offsetSeed, double x, double y) {
x = this.distanceFunction.scale(x);
y = this.distanceFunction.scale(y);
int xr = this.distanceFunction.getCellX(x, y);
int yr = this.distanceFunction.getCellY(x, y);
ResultBuffer.ResultBuffer2d buffer = this.localBuffer2d();
buffer.distance = Double.POSITIVE_INFINITY;
this.distanceFunction.nearest2D(offsetSeed, x, y, xr, yr, buffer, this.pointEvaluator);
return GeneralNoise.limit(this.cellFunction.eval(seed, offsetSeed, x, y, buffer, this.distanceFunction, this.noiseLookup)) * 2.0 - 1.0;
}
@Override
public double get(int seed, int offsetSeed, double x, double y, double z) {
int xr = this.distanceFunction.getCellX(x, y, z);
int yr = this.distanceFunction.getCellY(x, y, z);
int zr = this.distanceFunction.getCellZ(x, y, z);
ResultBuffer.ResultBuffer3d buffer = this.localBuffer3d();
buffer.distance = Double.POSITIVE_INFINITY;
this.distanceFunction.nearest3D(offsetSeed, x, y, z, xr, yr, zr, buffer, this.pointEvaluator);
return GeneralNoise.limit(this.cellFunction.eval(seed, offsetSeed, x, y, z, buffer, this.distanceFunction, this.noiseLookup)) * 2.0 - 1.0;
}
protected ResultBuffer.ResultBuffer2d localBuffer2d() {
return ResultBuffer.buffer2d;
}
protected ResultBuffer.ResultBuffer3d localBuffer3d() {
return ResultBuffer.buffer3d;
}
@Nonnull
@Override
public String toString() {
return "CellNoise{distanceFunction="
+ this.distanceFunction
+ ", pointEvaluator="
+ this.pointEvaluator
+ ", cellFunction="
+ this.cellFunction
+ ", noiseLookup="
+ this.noiseLookup
+ "}";
}
public interface CellFunction {
double eval(int var1, int var2, double var3, double var5, ResultBuffer.ResultBuffer2d var7, CellDistanceFunction var8, NoiseProperty var9);
double eval(int var1, int var2, double var3, double var5, double var7, ResultBuffer.ResultBuffer3d var9, CellDistanceFunction var10, NoiseProperty var11);
}
public static enum CellMode {
CELL_VALUE(
new CellNoise.CellFunction() {
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
@Nonnull ResultBuffer.ResultBuffer2d buffer,
CellDistanceFunction cellFunction,
NoiseProperty noiseLookup
) {
return HashUtil.random(offsetSeed, buffer.ix, buffer.iy);
}
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
double z,
@Nonnull ResultBuffer.ResultBuffer3d buffer,
CellDistanceFunction cellFunction,
NoiseProperty noiseLookup
) {
return HashUtil.random(offsetSeed, buffer.ix, buffer.iy, buffer.iz);
}
@Nonnull
@Override
public String toString() {
return "CellValueCellFunction{}";
}
}
),
NOISE_LOOKUP(
new CellNoise.CellFunction() {
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
@Nonnull ResultBuffer.ResultBuffer2d buffer,
@Nonnull CellDistanceFunction cellFunction,
@Nonnull NoiseProperty noiseLookup
) {
double px = cellFunction.invScale(buffer.x);
double py = cellFunction.invScale(buffer.y);
return noiseLookup.get(seed, px, py);
}
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
double z,
@Nonnull ResultBuffer.ResultBuffer3d buffer,
@Nonnull CellDistanceFunction cellFunction,
@Nonnull NoiseProperty noiseLookup
) {
double px = cellFunction.invScale(buffer.x);
double py = cellFunction.invScale(buffer.y);
double pz = cellFunction.invScale(buffer.z);
return noiseLookup.get(seed, px, py, pz);
}
@Nonnull
@Override
public String toString() {
return "NoiseLookupCellFunction{}";
}
}
),
DISTANCE(
new CellNoise.CellFunction() {
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
@Nonnull ResultBuffer.ResultBuffer2d buffer,
CellDistanceFunction cellFunction,
NoiseProperty noiseLookup
) {
return Math.sqrt(buffer.distance);
}
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
double z,
@Nonnull ResultBuffer.ResultBuffer3d buffer,
CellDistanceFunction cellFunction,
NoiseProperty noiseLookup
) {
return Math.sqrt(buffer.distance);
}
@Nonnull
@Override
public String toString() {
return "DistanceCellFunction{}";
}
}
),
DIRECTION(
new CellNoise.CellFunction() {
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
@Nonnull ResultBuffer.ResultBuffer2d buffer,
CellDistanceFunction cellFunction,
NoiseProperty noiseLookup
) {
float angle = (float)this.getAngleNoise(seed, offsetSeed, buffer, noiseLookup) * (float) (Math.PI * 2);
float dx = TrigMathUtil.sin(angle);
float dy = TrigMathUtil.cos(angle);
double ax = buffer.x;
double ay = buffer.y;
double bx = ax + dx;
double by = ay + dy;
double distance2 = MathUtil.distanceToInfLineSq(x, y, ax, ay, bx, by);
double distance = MathUtil.clamp(Math.sqrt(distance2), 0.0, 1.0);
int side = MathUtil.sideOfLine(x, y, ax, ay, bx, by);
return 0.5 + side * distance * 0.5;
}
@Override
public double eval(
int seed,
int offsetSeed,
double x,
double y,
double z,
ResultBuffer.ResultBuffer3d buffer,
CellDistanceFunction cellFunction,
NoiseProperty noiseLookup
) {
throw new UnsupportedOperationException();
}
@Nonnull
@Override
public String toString() {
return "DirectionCellFunction{}";
}
private double getAngleNoise(int seed, int offsetSeed, @Nonnull ResultBuffer.ResultBuffer2d buffer, @Nullable NoiseProperty noiseProperty) {
return noiseProperty != null ? noiseProperty.get(seed, buffer.x, buffer.y) : HashUtil.random(offsetSeed, buffer.ix, buffer.iy);
}
}
);
private final CellNoise.CellFunction function;
private CellMode(CellNoise.CellFunction function) {
this.function = function;
}
public CellNoise.CellFunction getFunction() {
return this.function;
}
}
}