package com.hypixel.hytale.procedurallib.logic;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.procedurallib.NoiseFunction;
import com.hypixel.hytale.procedurallib.condition.IIntCondition;
import com.hypixel.hytale.procedurallib.logic.cell.HexCellDistanceFunction;
import com.hypixel.hytale.procedurallib.logic.cell.jitter.CellJitter;
public class HexMeshNoise implements NoiseFunction {
protected final IIntCondition density;
protected final double thickness;
protected final double thicknessSquared;
protected final CellJitter jitter;
protected final boolean linesX;
protected final boolean linesY;
protected final boolean linesZ;
public HexMeshNoise(IIntCondition density, double thickness, CellJitter jitter, boolean linesX, boolean linesY, boolean linesZ) {
double domainLocalThickness = HexCellDistanceFunction.DISTANCE_FUNCTION.scale(thickness);
this.density = density;
this.thickness = domainLocalThickness;
this.thicknessSquared = domainLocalThickness * domainLocalThickness;
this.jitter = jitter;
this.linesX = linesX;
this.linesY = linesY;
this.linesZ = linesZ;
}
public double get(int seed, int offsetSeed, double x, double y) {
x = HexCellDistanceFunction.DISTANCE_FUNCTION.scale(x);
y = HexCellDistanceFunction.DISTANCE_FUNCTION.scale(y);
int cx = HexCellDistanceFunction.toGridX(x, y);
int cy = HexCellDistanceFunction.toGridY(x, y);
double nearest = this.thicknessSquared;
nearest = this.checkConnections(offsetSeed, x, y, cx - 1, cy - 1, nearest);
nearest = this.checkConnections(offsetSeed, x, y, cx - 1, cy + 0, nearest);
nearest = this.checkConnections(offsetSeed, x, y, cx + 1, cy + 0, nearest);
nearest = this.checkConnections(offsetSeed, x, y, cx + 0, cy - 1, nearest);
nearest = this.checkConnections(offsetSeed, x, y, cx + 0, cy + 1, nearest);
if (this.linesZ) {
nearest = this.checkDiagonalConnections(offsetSeed, x, y, cx + 0, cy + 0, nearest);
nearest = this.checkDiagonalConnections(offsetSeed, x, y, cx + 0, cy - 1, nearest);
nearest = this.checkDiagonalConnections(offsetSeed, x, y, cx + 0, cy + 1, nearest);
nearest = this.checkDiagonalConnections(offsetSeed, x, y, cx - 1, cy + 0, nearest);
nearest = this.checkDiagonalConnections(offsetSeed, x, y, cx - 1, cy - 1, nearest);
}
if (nearest < this.thicknessSquared) {
double distance = Math.sqrt(nearest);
double d = distance / this.thickness;
return d * 2.0 - 1.0;
} else {
return 1.0;
}
}
public double get(int seed, int offsetSeed, double x, double y, double z) {
throw new UnsupportedOperationException("3d not supported");
}
protected double checkConnections(int offsetSeed, double x, double y, int cx, int cy, double nearest) {
int hash = HexCellDistanceFunction.getHash(offsetSeed, cx, cy);
if (!this.density.eval(hash)) {
return nearest;
} else {
DoubleArray.Double2 vec = HexCellDistanceFunction.HEX_CELL_2D[hash & 255];
double px = this.jitter.getPointX(cx, vec);
double py = this.jitter.getPointY(cy, vec);
double ax = HexCellDistanceFunction.toHexX(px, py);
double ay = HexCellDistanceFunction.toHexY(px, py);
double adx = x - ax;
double ady = y - ay;
if (this.linesX) {
nearest = Math.min(nearest, this.dist2Cell(offsetSeed, x, y, adx, ady, ax, ay, cx - 1, cy));
nearest = Math.min(nearest, this.dist2Cell(offsetSeed, x, y, adx, ady, ax, ay, cx + 1, cy));
}
if (this.linesY) {
nearest = Math.min(nearest, this.dist2Cell(offsetSeed, x, y, adx, ady, ax, ay, cx, cy - 1));
nearest = Math.min(nearest, this.dist2Cell(offsetSeed, x, y, adx, ady, ax, ay, cx, cy + 1));
}
return nearest;
}
}
protected double checkDiagonalConnections(int offsetSeed, double x, double y, int cx, int cy, double nearest) {
int hash = HexCellDistanceFunction.getHash(offsetSeed, cx, cy);
if (!this.density.eval(hash)) {
return nearest;
} else {
DoubleArray.Double2 vec = HexCellDistanceFunction.HEX_CELL_2D[hash & 255];
double px = this.jitter.getPointX(cx, vec);
double py = this.jitter.getPointY(cy, vec);
double ax = HexCellDistanceFunction.toHexX(px, py);
double ay = HexCellDistanceFunction.toHexY(px, py);
double adx = x - ax;
double ady = y - ay;
nearest = Math.min(nearest, this.dist2Cell(offsetSeed, x, y, adx, ady, ax, ay, cx - 1, cy + 1));
nearest = Math.min(nearest, this.dist2Cell(offsetSeed, x, y, adx, ady, ax, ay, cx + 1, cy - 1));
return nearest;
}
}
protected double dist2Cell(int offsetSeed, double x, double y, double adx, double ady, double ax, double ay, int cx, int cy) {
int hash = HexCellDistanceFunction.getHash(offsetSeed, cx, cy);
if (!this.density.eval(hash)) {
return 1.7976931348623157E308;
} else {
DoubleArray.Double2 vec = HexCellDistanceFunction.HEX_CELL_2D[hash & 255];
double px = this.jitter.getPointX(cx, vec);
double py = this.jitter.getPointY(cy, vec);
double bx = HexCellDistanceFunction.toHexX(px, py);
double by = HexCellDistanceFunction.toHexY(px, py);
return MathUtil.distanceToLineSq(x, y, ax, ay, bx, by, adx, ady, bx - ax, by - ay);
}
}
}