mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 18:23:06 +00:00
Move editing stuff to writer
This commit is contained in:
parent
3142717154
commit
9b93a5cd04
@ -18,19 +18,31 @@
|
|||||||
|
|
||||||
package com.volmit.iris.engine.mantle;
|
package com.volmit.iris.engine.mantle;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.object.basic.IrisPosition;
|
||||||
import com.volmit.iris.engine.object.common.IObjectPlacer;
|
import com.volmit.iris.engine.object.common.IObjectPlacer;
|
||||||
import com.volmit.iris.engine.object.feature.IrisFeaturePositional;
|
import com.volmit.iris.engine.object.feature.IrisFeaturePositional;
|
||||||
import com.volmit.iris.engine.object.tile.TileData;
|
import com.volmit.iris.engine.object.tile.TileData;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
import com.volmit.iris.util.mantle.MantleChunk;
|
import com.volmit.iris.util.mantle.MantleChunk;
|
||||||
|
import com.volmit.iris.util.math.INode;
|
||||||
|
import com.volmit.iris.util.math.KochanekBartelsInterpolation;
|
||||||
|
import com.volmit.iris.util.math.PathInterpolation;
|
||||||
import com.volmit.iris.util.matter.Matter;
|
import com.volmit.iris.util.matter.Matter;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.block.TileState;
|
import org.bukkit.block.TileState;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class MantleWriter implements IObjectPlacer {
|
public class MantleWriter implements IObjectPlacer {
|
||||||
@ -133,4 +145,436 @@ public class MantleWriter implements IObjectPlacer {
|
|||||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||||
getEngineMantle().setTile(xx, yy, zz, tile);
|
getEngineMantle().setTile(xx, yy, zz, tile);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Set a sphere into the mantle
|
||||||
|
*
|
||||||
|
* @param cx the center x
|
||||||
|
* @param cy the center y
|
||||||
|
* @param cz the center z
|
||||||
|
* @param radius the radius of this sphere
|
||||||
|
* @param fill should it be filled? or just the outer shell?
|
||||||
|
* @param data the data to set
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
public <T> void setSphere(int cx, int cy, int cz, double radius, boolean fill, T data) {
|
||||||
|
setElipsoid(cx, cy, cz, radius, radius, radius, fill, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an elipsoid into the mantle
|
||||||
|
*
|
||||||
|
* @param cx the center x
|
||||||
|
* @param cy the center y
|
||||||
|
* @param cz the center z
|
||||||
|
* @param rx the x radius
|
||||||
|
* @param ry the y radius
|
||||||
|
* @param rz the z radius
|
||||||
|
* @param fill should it be filled or just the outer shell?
|
||||||
|
* @param data the data to set
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
public <T> void setElipsoid(int cx, int cy, int cz, double rx, double ry, double rz, boolean fill, T data) {
|
||||||
|
rx += 0.5;
|
||||||
|
ry += 0.5;
|
||||||
|
rz += 0.5;
|
||||||
|
final double invRadiusX = 1 / rx;
|
||||||
|
final double invRadiusY = 1 / ry;
|
||||||
|
final double invRadiusZ = 1 / rz;
|
||||||
|
final int ceilRadiusX = (int) Math.ceil(rx);
|
||||||
|
final int ceilRadiusY = (int) Math.ceil(ry);
|
||||||
|
final int ceilRadiusZ = (int) Math.ceil(rz);
|
||||||
|
double nextXn = 0;
|
||||||
|
|
||||||
|
forX:
|
||||||
|
for (int x = 0; x <= ceilRadiusX; ++x) {
|
||||||
|
final double xn = nextXn;
|
||||||
|
nextXn = (x + 1) * invRadiusX;
|
||||||
|
double nextYn = 0;
|
||||||
|
forY:
|
||||||
|
for (int y = 0; y <= ceilRadiusY; ++y) {
|
||||||
|
final double yn = nextYn;
|
||||||
|
nextYn = (y + 1) * invRadiusY;
|
||||||
|
double nextZn = 0;
|
||||||
|
for (int z = 0; z <= ceilRadiusZ; ++z) {
|
||||||
|
final double zn = nextZn;
|
||||||
|
nextZn = (z + 1) * invRadiusZ;
|
||||||
|
|
||||||
|
double distanceSq = lengthSq(xn, yn, zn);
|
||||||
|
if (distanceSq > 1) {
|
||||||
|
if (z == 0) {
|
||||||
|
if (y == 0) {
|
||||||
|
break forX;
|
||||||
|
}
|
||||||
|
break forY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fill) {
|
||||||
|
if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(x + cx, y + cy, z + cz, data);
|
||||||
|
setData(-x + cx, y + cy, z + cz, data);
|
||||||
|
setData(x + cx, -y + cy, z + cz, data);
|
||||||
|
setData(x + cx, y + cy, -z + cz, data);
|
||||||
|
setData(-x + cx, y + cy, -z + cz, data);
|
||||||
|
setData(-x + cx, -y + cy, z + cz, data);
|
||||||
|
setData(x + cx, -y + cy, -z + cz, data);
|
||||||
|
setData(-x + cx, y + cy, -z + cz, data);
|
||||||
|
setData(-x + cx, -y + cy, -z + cz, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a cuboid of data in the mantle
|
||||||
|
*
|
||||||
|
* @param x1 the min x
|
||||||
|
* @param y1 the min y
|
||||||
|
* @param z1 the min z
|
||||||
|
* @param x2 the max x
|
||||||
|
* @param y2 the max y
|
||||||
|
* @param z2 the max z
|
||||||
|
* @param data the data to set
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
public <T> void setCuboid(int x1, int y1, int z1, int x2, int y2, int z2, T data) {
|
||||||
|
int j, k;
|
||||||
|
|
||||||
|
for (int i = x1; i <= x2; i++) {
|
||||||
|
for (j = x1; j <= x2; j++) {
|
||||||
|
for (k = x1; k <= x2; k++) {
|
||||||
|
setData(i, j, k, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a pyramid of data in the mantle
|
||||||
|
*
|
||||||
|
* @param cx the center x
|
||||||
|
* @param cy the base y
|
||||||
|
* @param cz the center z
|
||||||
|
* @param data the data to set
|
||||||
|
* @param size the size of the pyramid (width of base & height)
|
||||||
|
* @param filled should it be filled or hollow
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
public <T> void setPyramid(int cx, int cy, int cz, T data, int size, boolean filled) {
|
||||||
|
int height = size;
|
||||||
|
|
||||||
|
for (int y = 0; y <= height; ++y) {
|
||||||
|
size--;
|
||||||
|
for (int x = 0; x <= size; ++x) {
|
||||||
|
for (int z = 0; z <= size; ++z) {
|
||||||
|
if ((filled && z <= size && x <= size) || z == size || x == size) {
|
||||||
|
setData(x + cx, y + cy, z + cz, data);
|
||||||
|
setData(-x + cx, y + cy, z + cz, data);
|
||||||
|
setData(x + cx, y + cy, -z + cz, data);
|
||||||
|
setData(-x + cx, y + cy, -z + cz, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a 3d tube spline interpolated with Kochanek Bartels
|
||||||
|
*
|
||||||
|
* @param nodevectors the vector points
|
||||||
|
* @param radius the radius
|
||||||
|
* @param filled if it should be filled or hollow
|
||||||
|
* @param data the data to set
|
||||||
|
*/
|
||||||
|
public <T> void setSpline(List<Vector> nodevectors, double radius, boolean filled, T data) {
|
||||||
|
setSpline(nodevectors, 0, 0, 0, 10, radius, filled, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a 3d tube spline interpolated with Kochanek Bartels
|
||||||
|
*
|
||||||
|
* @param nodevectors the spline points
|
||||||
|
* @param tension the tension 0
|
||||||
|
* @param bias the bias 0
|
||||||
|
* @param continuity the continuity 0
|
||||||
|
* @param quality the quality 10
|
||||||
|
* @param radius the radius
|
||||||
|
* @param filled filled or hollow
|
||||||
|
* @param data the data to set
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
public <T> void setSpline(List<Vector> nodevectors, double tension, double bias, double continuity, double quality, double radius, boolean filled, T data) {
|
||||||
|
Set<IrisPosition> vset = new KSet<>();
|
||||||
|
List<INode> nodes = new ArrayList<>(nodevectors.size());
|
||||||
|
PathInterpolation interpol = new KochanekBartelsInterpolation();
|
||||||
|
|
||||||
|
for (Vector nodevector : nodevectors) {
|
||||||
|
INode n = new INode(nodevector);
|
||||||
|
n.setTension(tension);
|
||||||
|
n.setBias(bias);
|
||||||
|
n.setContinuity(continuity);
|
||||||
|
nodes.add(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
interpol.setNodes(nodes);
|
||||||
|
double splinelength = interpol.arcLength(0, 1);
|
||||||
|
for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
|
||||||
|
Vector tipv = interpol.getPosition(loop);
|
||||||
|
vset.add(new IrisPosition(tipv.toBlockVector()));
|
||||||
|
}
|
||||||
|
|
||||||
|
vset = getBallooned(vset, radius);
|
||||||
|
if (!filled) {
|
||||||
|
vset = getHollowed(vset);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(vset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a 3d line
|
||||||
|
*
|
||||||
|
* @param a the first point
|
||||||
|
* @param b the second point
|
||||||
|
* @param radius the radius
|
||||||
|
* @param filled hollow or filled?
|
||||||
|
* @param data the data
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
public <T> void setLine(IrisPosition a, IrisPosition b, double radius, boolean filled, T data) {
|
||||||
|
setLine(ImmutableList.of(a, b), radius, filled, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set lines for points
|
||||||
|
*
|
||||||
|
* @param vectors the points
|
||||||
|
* @param radius the radius
|
||||||
|
* @param filled hollow or filled?
|
||||||
|
* @param data the data to set
|
||||||
|
* @param <T> the type of data to apply to the mantle
|
||||||
|
*/
|
||||||
|
public <T> void setLine(List<IrisPosition> vectors, double radius, boolean filled, T data) {
|
||||||
|
Set<IrisPosition> vset = new KSet<>();
|
||||||
|
|
||||||
|
for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) {
|
||||||
|
IrisPosition pos1 = vectors.get(i);
|
||||||
|
IrisPosition pos2 = vectors.get(i + 1);
|
||||||
|
int x1 = pos1.getX();
|
||||||
|
int y1 = pos1.getY();
|
||||||
|
int z1 = pos1.getZ();
|
||||||
|
int x2 = pos2.getX();
|
||||||
|
int y2 = pos2.getY();
|
||||||
|
int z2 = pos2.getZ();
|
||||||
|
int tipx = x1;
|
||||||
|
int tipy = y1;
|
||||||
|
int tipz = z1;
|
||||||
|
int dx = Math.abs(x2 - x1);
|
||||||
|
int dy = Math.abs(y2 - y1);
|
||||||
|
int dz = Math.abs(z2 - z1);
|
||||||
|
|
||||||
|
if (dx + dy + dz == 0) {
|
||||||
|
vset.add(new IrisPosition(tipx, tipy, tipz));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dMax = Math.max(Math.max(dx, dy), dz);
|
||||||
|
if (dMax == dx) {
|
||||||
|
for (int domstep = 0; domstep <= dx; domstep++) {
|
||||||
|
tipx = x1 + domstep * (x2 - x1 > 0 ? 1 : -1);
|
||||||
|
tipy = (int) Math.round(y1 + domstep * ((double) dy) / ((double) dx) * (y2 - y1 > 0 ? 1 : -1));
|
||||||
|
tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dx) * (z2 - z1 > 0 ? 1 : -1));
|
||||||
|
|
||||||
|
vset.add(new IrisPosition(tipx, tipy, tipz));
|
||||||
|
}
|
||||||
|
} else if (dMax == dy) {
|
||||||
|
for (int domstep = 0; domstep <= dy; domstep++) {
|
||||||
|
tipy = y1 + domstep * (y2 - y1 > 0 ? 1 : -1);
|
||||||
|
tipx = (int) Math.round(x1 + domstep * ((double) dx) / ((double) dy) * (x2 - x1 > 0 ? 1 : -1));
|
||||||
|
tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dy) * (z2 - z1 > 0 ? 1 : -1));
|
||||||
|
|
||||||
|
vset.add(new IrisPosition(tipx, tipy, tipz));
|
||||||
|
}
|
||||||
|
} else /* if (dMax == dz) */ {
|
||||||
|
for (int domstep = 0; domstep <= dz; domstep++) {
|
||||||
|
tipz = z1 + domstep * (z2 - z1 > 0 ? 1 : -1);
|
||||||
|
tipy = (int) Math.round(y1 + domstep * ((double) dy) / ((double) dz) * (y2 - y1 > 0 ? 1 : -1));
|
||||||
|
tipx = (int) Math.round(x1 + domstep * ((double) dx) / ((double) dz) * (x2 - x1 > 0 ? 1 : -1));
|
||||||
|
|
||||||
|
vset.add(new IrisPosition(tipx, tipy, tipz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vset = getBallooned(vset, radius);
|
||||||
|
|
||||||
|
if (!filled) {
|
||||||
|
vset = getHollowed(vset);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(vset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a cylinder in the mantle
|
||||||
|
*
|
||||||
|
* @param cx the center x
|
||||||
|
* @param cy the base y
|
||||||
|
* @param cz the center z
|
||||||
|
* @param data the data to set
|
||||||
|
* @param radius the radius
|
||||||
|
* @param height the height of the cyl
|
||||||
|
* @param filled filled or not
|
||||||
|
*/
|
||||||
|
public <T> void setCylinder(int cx, int cy, int cz, T data, double radius, int height, boolean filled) {
|
||||||
|
setCylinder(cx, cy, cz, data, radius, radius, height, filled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a cylinder in the mantle
|
||||||
|
*
|
||||||
|
* @param cx the center x
|
||||||
|
* @param cy the base y
|
||||||
|
* @param cz the center z
|
||||||
|
* @param data the data to set
|
||||||
|
* @param radiusX the x radius
|
||||||
|
* @param radiusZ the z radius
|
||||||
|
* @param height the height of this cyl
|
||||||
|
* @param filled filled or hollow?
|
||||||
|
*/
|
||||||
|
public <T> void setCylinder(int cx, int cy, int cz, T data, double radiusX, double radiusZ, int height, boolean filled) {
|
||||||
|
int affected = 0;
|
||||||
|
radiusX += 0.5;
|
||||||
|
radiusZ += 0.5;
|
||||||
|
|
||||||
|
if (height == 0) {
|
||||||
|
return;
|
||||||
|
} else if (height < 0) {
|
||||||
|
height = -height;
|
||||||
|
cy = cy - height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cy < 0) {
|
||||||
|
cy = 0;
|
||||||
|
} else if (cy + height - 1 > getMantle().getWorldHeight()) {
|
||||||
|
height = getMantle().getWorldHeight() - cy + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double invRadiusX = 1 / radiusX;
|
||||||
|
final double invRadiusZ = 1 / radiusZ;
|
||||||
|
final int ceilRadiusX = (int) Math.ceil(radiusX);
|
||||||
|
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
|
||||||
|
double nextXn = 0;
|
||||||
|
|
||||||
|
forX:
|
||||||
|
for (int x = 0; x <= ceilRadiusX; ++x) {
|
||||||
|
final double xn = nextXn;
|
||||||
|
nextXn = (x + 1) * invRadiusX;
|
||||||
|
double nextZn = 0;
|
||||||
|
for (int z = 0; z <= ceilRadiusZ; ++z) {
|
||||||
|
final double zn = nextZn;
|
||||||
|
nextZn = (z + 1) * invRadiusZ;
|
||||||
|
double distanceSq = lengthSq(xn, zn);
|
||||||
|
|
||||||
|
if (distanceSq > 1) {
|
||||||
|
if (z == 0) {
|
||||||
|
break forX;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filled) {
|
||||||
|
if (lengthSq(nextXn, zn) <= 1 && lengthSq(xn, nextZn) <= 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < height; ++y) {
|
||||||
|
setData(cx + x, cy + y, cz + z, data);
|
||||||
|
setData(cx + -x, cy + y, cz + z, data);
|
||||||
|
setData(cx + x, cy + y, cz + -z, data);
|
||||||
|
setData(cx + -x, cy + y, cz + -z, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void set(IrisPosition pos, T data) {
|
||||||
|
setData(pos.getX(), pos.getY(), pos.getZ(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void set(List<IrisPosition> positions, T data) {
|
||||||
|
for (IrisPosition i : positions) {
|
||||||
|
set(i, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void set(Set<IrisPosition> positions, T data) {
|
||||||
|
for (IrisPosition i : positions) {
|
||||||
|
set(i, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
||||||
|
Set<IrisPosition> returnset = new HashSet<>();
|
||||||
|
int ceilrad = (int) Math.ceil(radius);
|
||||||
|
|
||||||
|
for (IrisPosition v : vset) {
|
||||||
|
int tipx = v.getX();
|
||||||
|
int tipy = v.getY();
|
||||||
|
int tipz = v.getZ();
|
||||||
|
|
||||||
|
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
|
||||||
|
for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) {
|
||||||
|
for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) {
|
||||||
|
if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= radius) {
|
||||||
|
returnset.add(new IrisPosition(loopx, loopy, loopz));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<IrisPosition> getHollowed(Set<IrisPosition> vset) {
|
||||||
|
Set<IrisPosition> returnset = new KSet<>();
|
||||||
|
for (IrisPosition v : vset) {
|
||||||
|
double x = v.getX();
|
||||||
|
double y = v.getY();
|
||||||
|
double z = v.getZ();
|
||||||
|
if (!(vset.contains(new IrisPosition(x + 1, y, z))
|
||||||
|
&& vset.contains(new IrisPosition(x - 1, y, z))
|
||||||
|
&& vset.contains(new IrisPosition(x, y + 1, z))
|
||||||
|
&& vset.contains(new IrisPosition(x, y - 1, z))
|
||||||
|
&& vset.contains(new IrisPosition(x, y, z + 1))
|
||||||
|
&& vset.contains(new IrisPosition(x, y, z - 1)))) {
|
||||||
|
returnset.add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double hypot(double... pars) {
|
||||||
|
double sum = 0;
|
||||||
|
for (double d : pars) {
|
||||||
|
sum += Math.pow(d, 2);
|
||||||
|
}
|
||||||
|
return Math.sqrt(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double lengthSq(double x, double y, double z) {
|
||||||
|
return (x * x) + (y * y) + (z * z);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double lengthSq(double x, double z) {
|
||||||
|
return (x * x) + (z * z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,439 +499,6 @@ public class Mantle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a sphere into the mantle
|
|
||||||
*
|
|
||||||
* @param cx the center x
|
|
||||||
* @param cy the center y
|
|
||||||
* @param cz the center z
|
|
||||||
* @param radius the radius of this sphere
|
|
||||||
* @param fill should it be filled? or just the outer shell?
|
|
||||||
* @param data the data to set
|
|
||||||
* @param <T> the type of data to apply to the mantle
|
|
||||||
*/
|
|
||||||
public <T> void setSphere(int cx, int cy, int cz, double radius, boolean fill, T data) {
|
|
||||||
setElipsoid(cx, cy, cz, radius, radius, radius, fill, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an elipsoid into the mantle
|
|
||||||
*
|
|
||||||
* @param cx the center x
|
|
||||||
* @param cy the center y
|
|
||||||
* @param cz the center z
|
|
||||||
* @param rx the x radius
|
|
||||||
* @param ry the y radius
|
|
||||||
* @param rz the z radius
|
|
||||||
* @param fill should it be filled or just the outer shell?
|
|
||||||
* @param data the data to set
|
|
||||||
* @param <T> the type of data to apply to the mantle
|
|
||||||
*/
|
|
||||||
public <T> void setElipsoid(int cx, int cy, int cz, double rx, double ry, double rz, boolean fill, T data) {
|
|
||||||
rx += 0.5;
|
|
||||||
ry += 0.5;
|
|
||||||
rz += 0.5;
|
|
||||||
final double invRadiusX = 1 / rx;
|
|
||||||
final double invRadiusY = 1 / ry;
|
|
||||||
final double invRadiusZ = 1 / rz;
|
|
||||||
final int ceilRadiusX = (int) Math.ceil(rx);
|
|
||||||
final int ceilRadiusY = (int) Math.ceil(ry);
|
|
||||||
final int ceilRadiusZ = (int) Math.ceil(rz);
|
|
||||||
double nextXn = 0;
|
|
||||||
|
|
||||||
forX:
|
|
||||||
for (int x = 0; x <= ceilRadiusX; ++x) {
|
|
||||||
final double xn = nextXn;
|
|
||||||
nextXn = (x + 1) * invRadiusX;
|
|
||||||
double nextYn = 0;
|
|
||||||
forY:
|
|
||||||
for (int y = 0; y <= ceilRadiusY; ++y) {
|
|
||||||
final double yn = nextYn;
|
|
||||||
nextYn = (y + 1) * invRadiusY;
|
|
||||||
double nextZn = 0;
|
|
||||||
for (int z = 0; z <= ceilRadiusZ; ++z) {
|
|
||||||
final double zn = nextZn;
|
|
||||||
nextZn = (z + 1) * invRadiusZ;
|
|
||||||
|
|
||||||
double distanceSq = lengthSq(xn, yn, zn);
|
|
||||||
if (distanceSq > 1) {
|
|
||||||
if (z == 0) {
|
|
||||||
if (y == 0) {
|
|
||||||
break forX;
|
|
||||||
}
|
|
||||||
break forY;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fill) {
|
|
||||||
if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set(x + cx, y + cy, z + cz, data);
|
|
||||||
set(-x + cx, y + cy, z + cz, data);
|
|
||||||
set(x + cx, -y + cy, z + cz, data);
|
|
||||||
set(x + cx, y + cy, -z + cz, data);
|
|
||||||
set(-x + cx, y + cy, -z + cz, data);
|
|
||||||
set(-x + cx, -y + cy, z + cz, data);
|
|
||||||
set(x + cx, -y + cy, -z + cz, data);
|
|
||||||
set(-x + cx, y + cy, -z + cz, data);
|
|
||||||
set(-x + cx, -y + cy, -z + cz, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a cuboid of data in the mantle
|
|
||||||
*
|
|
||||||
* @param x1 the min x
|
|
||||||
* @param y1 the min y
|
|
||||||
* @param z1 the min z
|
|
||||||
* @param x2 the max x
|
|
||||||
* @param y2 the max y
|
|
||||||
* @param z2 the max z
|
|
||||||
* @param data the data to set
|
|
||||||
* @param <T> the type of data to apply to the mantle
|
|
||||||
*/
|
|
||||||
public <T> void setCuboid(int x1, int y1, int z1, int x2, int y2, int z2, T data) {
|
|
||||||
int j, k;
|
|
||||||
|
|
||||||
for (int i = x1; i <= x2; i++) {
|
|
||||||
for (j = x1; j <= x2; j++) {
|
|
||||||
for (k = x1; k <= x2; k++) {
|
|
||||||
set(i, j, k, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a pyramid of data in the mantle
|
|
||||||
*
|
|
||||||
* @param cx the center x
|
|
||||||
* @param cy the base y
|
|
||||||
* @param cz the center z
|
|
||||||
* @param data the data to set
|
|
||||||
* @param size the size of the pyramid (width of base & height)
|
|
||||||
* @param filled should it be filled or hollow
|
|
||||||
* @param <T> the type of data to apply to the mantle
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
public <T> void setPyramid(int cx, int cy, int cz, T data, int size, boolean filled) {
|
|
||||||
int height = size;
|
|
||||||
|
|
||||||
for (int y = 0; y <= height; ++y) {
|
|
||||||
size--;
|
|
||||||
for (int x = 0; x <= size; ++x) {
|
|
||||||
for (int z = 0; z <= size; ++z) {
|
|
||||||
if ((filled && z <= size && x <= size) || z == size || x == size) {
|
|
||||||
set(x + cx, y + cy, z + cz, data);
|
|
||||||
set(-x + cx, y + cy, z + cz, data);
|
|
||||||
set(x + cx, y + cy, -z + cz, data);
|
|
||||||
set(-x + cx, y + cy, -z + cz, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a 3d tube spline interpolated with Kochanek Bartels
|
|
||||||
*
|
|
||||||
* @param nodevectors the vector points
|
|
||||||
* @param radius the radius
|
|
||||||
* @param filled if it should be filled or hollow
|
|
||||||
* @param data the data to set
|
|
||||||
*/
|
|
||||||
public <T> void setSpline(List<Vector> nodevectors, double radius, boolean filled, T data) {
|
|
||||||
setSpline(nodevectors, 0, 0, 0, 10, radius, filled, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a 3d tube spline interpolated with Kochanek Bartels
|
|
||||||
*
|
|
||||||
* @param nodevectors the spline points
|
|
||||||
* @param tension the tension 0
|
|
||||||
* @param bias the bias 0
|
|
||||||
* @param continuity the continuity 0
|
|
||||||
* @param quality the quality 10
|
|
||||||
* @param radius the radius
|
|
||||||
* @param filled filled or hollow
|
|
||||||
* @param data the data to set
|
|
||||||
* @param <T> the type of data to apply to the mantle
|
|
||||||
*/
|
|
||||||
public <T> void setSpline(List<Vector> nodevectors, double tension, double bias, double continuity, double quality, double radius, boolean filled, T data) {
|
|
||||||
Set<IrisPosition> vset = new KSet<>();
|
|
||||||
List<INode> nodes = new ArrayList<>(nodevectors.size());
|
|
||||||
PathInterpolation interpol = new KochanekBartelsInterpolation();
|
|
||||||
|
|
||||||
for (Vector nodevector : nodevectors) {
|
|
||||||
INode n = new INode(nodevector);
|
|
||||||
n.setTension(tension);
|
|
||||||
n.setBias(bias);
|
|
||||||
n.setContinuity(continuity);
|
|
||||||
nodes.add(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
interpol.setNodes(nodes);
|
|
||||||
double splinelength = interpol.arcLength(0, 1);
|
|
||||||
for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
|
|
||||||
Vector tipv = interpol.getPosition(loop);
|
|
||||||
vset.add(new IrisPosition(tipv.toBlockVector()));
|
|
||||||
}
|
|
||||||
|
|
||||||
vset = getBallooned(vset, radius);
|
|
||||||
if (!filled) {
|
|
||||||
vset = getHollowed(vset);
|
|
||||||
}
|
|
||||||
|
|
||||||
set(vset, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a 3d line
|
|
||||||
*
|
|
||||||
* @param a the first point
|
|
||||||
* @param b the second point
|
|
||||||
* @param radius the radius
|
|
||||||
* @param filled hollow or filled?
|
|
||||||
* @param data the data
|
|
||||||
* @param <T> the type of data to apply to the mantle
|
|
||||||
*/
|
|
||||||
public <T> void setLine(IrisPosition a, IrisPosition b, double radius, boolean filled, T data) {
|
|
||||||
setLine(ImmutableList.of(a, b), radius, filled, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set lines for points
|
|
||||||
*
|
|
||||||
* @param vectors the points
|
|
||||||
* @param radius the radius
|
|
||||||
* @param filled hollow or filled?
|
|
||||||
* @param data the data to set
|
|
||||||
* @param <T> the type of data to apply to the mantle
|
|
||||||
*/
|
|
||||||
public <T> void setLine(List<IrisPosition> vectors, double radius, boolean filled, T data) {
|
|
||||||
Set<IrisPosition> vset = new KSet<>();
|
|
||||||
|
|
||||||
for (int i = 0; vectors.size() != 0 && i < vectors.size() - 1; i++) {
|
|
||||||
IrisPosition pos1 = vectors.get(i);
|
|
||||||
IrisPosition pos2 = vectors.get(i + 1);
|
|
||||||
int x1 = pos1.getX();
|
|
||||||
int y1 = pos1.getY();
|
|
||||||
int z1 = pos1.getZ();
|
|
||||||
int x2 = pos2.getX();
|
|
||||||
int y2 = pos2.getY();
|
|
||||||
int z2 = pos2.getZ();
|
|
||||||
int tipx = x1;
|
|
||||||
int tipy = y1;
|
|
||||||
int tipz = z1;
|
|
||||||
int dx = Math.abs(x2 - x1);
|
|
||||||
int dy = Math.abs(y2 - y1);
|
|
||||||
int dz = Math.abs(z2 - z1);
|
|
||||||
|
|
||||||
if (dx + dy + dz == 0) {
|
|
||||||
vset.add(new IrisPosition(tipx, tipy, tipz));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dMax = Math.max(Math.max(dx, dy), dz);
|
|
||||||
if (dMax == dx) {
|
|
||||||
for (int domstep = 0; domstep <= dx; domstep++) {
|
|
||||||
tipx = x1 + domstep * (x2 - x1 > 0 ? 1 : -1);
|
|
||||||
tipy = (int) Math.round(y1 + domstep * ((double) dy) / ((double) dx) * (y2 - y1 > 0 ? 1 : -1));
|
|
||||||
tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dx) * (z2 - z1 > 0 ? 1 : -1));
|
|
||||||
|
|
||||||
vset.add(new IrisPosition(tipx, tipy, tipz));
|
|
||||||
}
|
|
||||||
} else if (dMax == dy) {
|
|
||||||
for (int domstep = 0; domstep <= dy; domstep++) {
|
|
||||||
tipy = y1 + domstep * (y2 - y1 > 0 ? 1 : -1);
|
|
||||||
tipx = (int) Math.round(x1 + domstep * ((double) dx) / ((double) dy) * (x2 - x1 > 0 ? 1 : -1));
|
|
||||||
tipz = (int) Math.round(z1 + domstep * ((double) dz) / ((double) dy) * (z2 - z1 > 0 ? 1 : -1));
|
|
||||||
|
|
||||||
vset.add(new IrisPosition(tipx, tipy, tipz));
|
|
||||||
}
|
|
||||||
} else /* if (dMax == dz) */ {
|
|
||||||
for (int domstep = 0; domstep <= dz; domstep++) {
|
|
||||||
tipz = z1 + domstep * (z2 - z1 > 0 ? 1 : -1);
|
|
||||||
tipy = (int) Math.round(y1 + domstep * ((double) dy) / ((double) dz) * (y2 - y1 > 0 ? 1 : -1));
|
|
||||||
tipx = (int) Math.round(x1 + domstep * ((double) dx) / ((double) dz) * (x2 - x1 > 0 ? 1 : -1));
|
|
||||||
|
|
||||||
vset.add(new IrisPosition(tipx, tipy, tipz));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vset = getBallooned(vset, radius);
|
|
||||||
|
|
||||||
if (!filled) {
|
|
||||||
vset = getHollowed(vset);
|
|
||||||
}
|
|
||||||
|
|
||||||
set(vset, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a cylinder in the mantle
|
|
||||||
*
|
|
||||||
* @param cx the center x
|
|
||||||
* @param cy the base y
|
|
||||||
* @param cz the center z
|
|
||||||
* @param data the data to set
|
|
||||||
* @param radius the radius
|
|
||||||
* @param height the height of the cyl
|
|
||||||
* @param filled filled or not
|
|
||||||
*/
|
|
||||||
public <T> void setCylinder(int cx, int cy, int cz, T data, double radius, int height, boolean filled) {
|
|
||||||
setCylinder(cx, cy, cz, data, radius, radius, height, filled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a cylinder in the mantle
|
|
||||||
*
|
|
||||||
* @param cx the center x
|
|
||||||
* @param cy the base y
|
|
||||||
* @param cz the center z
|
|
||||||
* @param data the data to set
|
|
||||||
* @param radiusX the x radius
|
|
||||||
* @param radiusZ the z radius
|
|
||||||
* @param height the height of this cyl
|
|
||||||
* @param filled filled or hollow?
|
|
||||||
*/
|
|
||||||
public <T> void setCylinder(int cx, int cy, int cz, T data, double radiusX, double radiusZ, int height, boolean filled) {
|
|
||||||
int affected = 0;
|
|
||||||
radiusX += 0.5;
|
|
||||||
radiusZ += 0.5;
|
|
||||||
|
|
||||||
if (height == 0) {
|
|
||||||
return;
|
|
||||||
} else if (height < 0) {
|
|
||||||
height = -height;
|
|
||||||
cy = cy - height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cy < 0) {
|
|
||||||
cy = 0;
|
|
||||||
} else if (cy + height - 1 > worldHeight) {
|
|
||||||
height = worldHeight - cy + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
final double invRadiusX = 1 / radiusX;
|
|
||||||
final double invRadiusZ = 1 / radiusZ;
|
|
||||||
final int ceilRadiusX = (int) Math.ceil(radiusX);
|
|
||||||
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
|
|
||||||
double nextXn = 0;
|
|
||||||
|
|
||||||
forX:
|
|
||||||
for (int x = 0; x <= ceilRadiusX; ++x) {
|
|
||||||
final double xn = nextXn;
|
|
||||||
nextXn = (x + 1) * invRadiusX;
|
|
||||||
double nextZn = 0;
|
|
||||||
for (int z = 0; z <= ceilRadiusZ; ++z) {
|
|
||||||
final double zn = nextZn;
|
|
||||||
nextZn = (z + 1) * invRadiusZ;
|
|
||||||
double distanceSq = lengthSq(xn, zn);
|
|
||||||
|
|
||||||
if (distanceSq > 1) {
|
|
||||||
if (z == 0) {
|
|
||||||
break forX;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!filled) {
|
|
||||||
if (lengthSq(nextXn, zn) <= 1 && lengthSq(xn, nextZn) <= 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int y = 0; y < height; ++y) {
|
|
||||||
set(cx + x, cy + y, cz + z, data);
|
|
||||||
set(cx + -x, cy + y, cz + z, data);
|
|
||||||
set(cx + x, cy + y, cz + -z, data);
|
|
||||||
set(cx + -x, cy + y, cz + -z, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> void set(IrisPosition pos, T data) {
|
|
||||||
set(pos.getX(), pos.getY(), pos.getZ(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> void set(List<IrisPosition> positions, T data) {
|
|
||||||
for (IrisPosition i : positions) {
|
|
||||||
set(i, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> void set(Set<IrisPosition> positions, T data) {
|
|
||||||
for (IrisPosition i : positions) {
|
|
||||||
set(i, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
|
||||||
Set<IrisPosition> returnset = new HashSet<>();
|
|
||||||
int ceilrad = (int) Math.ceil(radius);
|
|
||||||
|
|
||||||
for (IrisPosition v : vset) {
|
|
||||||
int tipx = v.getX();
|
|
||||||
int tipy = v.getY();
|
|
||||||
int tipz = v.getZ();
|
|
||||||
|
|
||||||
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
|
|
||||||
for (int loopy = tipy - ceilrad; loopy <= tipy + ceilrad; loopy++) {
|
|
||||||
for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) {
|
|
||||||
if (hypot(loopx - tipx, loopy - tipy, loopz - tipz) <= radius) {
|
|
||||||
returnset.add(new IrisPosition(loopx, loopy, loopz));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Set<IrisPosition> getHollowed(Set<IrisPosition> vset) {
|
|
||||||
Set<IrisPosition> returnset = new KSet<>();
|
|
||||||
for (IrisPosition v : vset) {
|
|
||||||
double x = v.getX();
|
|
||||||
double y = v.getY();
|
|
||||||
double z = v.getZ();
|
|
||||||
if (!(vset.contains(new IrisPosition(x + 1, y, z))
|
|
||||||
&& vset.contains(new IrisPosition(x - 1, y, z))
|
|
||||||
&& vset.contains(new IrisPosition(x, y + 1, z))
|
|
||||||
&& vset.contains(new IrisPosition(x, y - 1, z))
|
|
||||||
&& vset.contains(new IrisPosition(x, y, z + 1))
|
|
||||||
&& vset.contains(new IrisPosition(x, y, z - 1)))) {
|
|
||||||
returnset.add(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double hypot(double... pars) {
|
|
||||||
double sum = 0;
|
|
||||||
for (double d : pars) {
|
|
||||||
sum += Math.pow(d, 2);
|
|
||||||
}
|
|
||||||
return Math.sqrt(sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double lengthSq(double x, double y, double z) {
|
|
||||||
return (x * x) + (y * y) + (z * z);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double lengthSq(double x, double z) {
|
|
||||||
return (x * x) + (z * z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWorldHeight() {
|
public int getWorldHeight() {
|
||||||
return worldHeight;
|
return worldHeight;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user