diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java
index 0aae7dcb..a69f3c28 100644
--- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java
+++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java
@@ -52,8 +52,8 @@ public HiresModelRenderer(ResourcePack resourcePack, RenderSettings renderSettin
}
public HiresModel render(WorldTile tile, AABB region) {
- Vector3i modelMin = region.getMin().toInt();
- Vector3i modelMax = region.getMax().toInt();
+ Vector3i modelMin = region.getMin();
+ Vector3i modelMax = region.getMax();
Vector3i min = modelMin.max(renderSettings.getMin());
Vector3i max = modelMax.min(renderSettings.getMax());
diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java
index 1c1aa58f..48e66349 100644
--- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java
+++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java
@@ -24,42 +24,28 @@
*/
package de.bluecolored.bluemap.core.util;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
-import java.util.Optional;
-
+import com.flowpowered.math.GenericMath;
import com.flowpowered.math.vector.Vector3d;
import com.flowpowered.math.vector.Vector3i;
/**
* An axis aligned bounding box. That is, an un-rotated cuboid.
* It is represented by its minimum and maximum corners.
- *
- *
The box will never be degenerate: the corners are always not equal and
- * respect the minimum and maximum properties.
+ *
+ * Using integers, the box has a minimum size of 1 in each direction.
*
* This class is immutable, all objects returned are either new instances or
* itself.
*/
public class AABB {
- private final Vector3d min;
- private final Vector3d max;
- private Vector3d size = null;
+ private final Vector3i min;
+ private final Vector3i max;
+ private Vector3i size = null;
private Vector3d center = null;
-
- /**
- * Constructs a new bounding box from two opposite corners.
- * Fails the resulting box would be degenerate (a dimension is 0).
- *
- * @param firstCorner The first corner
- * @param secondCorner The second corner
- */
- public AABB(Vector3i firstCorner, Vector3i secondCorner) {
- this(checkNotNull(firstCorner, "firstCorner").toDouble(), checkNotNull(secondCorner, "secondCorner").toDouble());
- }
-
+
/**
* Constructs a new bounding box from two opposite corners.
* Fails the resulting box would be degenerate (a dimension is 0).
@@ -71,8 +57,8 @@ public AABB(Vector3i firstCorner, Vector3i secondCorner) {
* @param y2 The second corner y coordinate
* @param z2 The second corner z coordinate
*/
- public AABB(double x1, double y1, double z1, double x2, double y2, double z2) {
- this(new Vector3d(x1, y1, z1), new Vector3d(x2, y2, z2));
+ public AABB(int x1, int y1, int z1, int x2, int y2, int z2) {
+ this(new Vector3i(x1, y1, z1), new Vector3i(x2, y2, z2));
}
/**
@@ -82,14 +68,11 @@ public AABB(double x1, double y1, double z1, double x2, double y2, double z2) {
* @param firstCorner The first corner
* @param secondCorner The second corner
*/
- public AABB(Vector3d firstCorner, Vector3d secondCorner) {
+ public AABB(Vector3i firstCorner, Vector3i secondCorner) {
checkNotNull(firstCorner, "firstCorner");
checkNotNull(secondCorner, "secondCorner");
this.min = firstCorner.min(secondCorner);
this.max = firstCorner.max(secondCorner);
- checkArgument(this.min.getX() != this.max.getX(), "The box is degenerate on x");
- checkArgument(this.min.getY() != this.max.getY(), "The box is degenerate on y");
- checkArgument(this.min.getZ() != this.max.getZ(), "The box is degenerate on z");
}
/**
@@ -97,7 +80,7 @@ public AABB(Vector3d firstCorner, Vector3d secondCorner) {
*
* @return The minimum corner
*/
- public Vector3d getMin() {
+ public Vector3i getMin() {
return this.min;
}
@@ -106,7 +89,7 @@ public Vector3d getMin() {
*
* @return The maximum corner
*/
- public Vector3d getMax() {
+ public Vector3i getMax() {
return this.max;
}
@@ -117,7 +100,7 @@ public Vector3d getMax() {
*/
public Vector3d getCenter() {
if (this.center == null) {
- this.center = this.min.add(getSize().div(2));
+ this.center = this.min.toDouble().add(getSize().toDouble().div(2));
}
return this.center;
}
@@ -127,9 +110,9 @@ public Vector3d getCenter() {
*
* @return The size
*/
- public Vector3d getSize() {
+ public Vector3i getSize() {
if (this.size == null) {
- this.size = this.max.sub(this.min);
+ this.size = this.max.sub(this.min).add(Vector3i.ONE);
}
return this.size;
}
@@ -165,6 +148,18 @@ public boolean contains(Vector3d point) {
* @return Whether or not the box contains the point
*/
public boolean contains(double x, double y, double z) {
+ return contains(GenericMath.floor(x), GenericMath.floor(y), GenericMath.floor(z));
+ }
+
+ /**
+ * Checks if the bounding box contains a point.
+ *
+ * @param x The x coordinate of the point
+ * @param y The y coordinate of the point
+ * @param z The z coordinate of the point
+ * @return Whether or not the box contains the point
+ */
+ public boolean contains(int x, int y, int z) {
return this.min.getX() <= x && this.max.getX() >= x
&& this.min.getY() <= y && this.max.getY() >= y
&& this.min.getZ() <= z && this.max.getZ() >= z;
@@ -183,156 +178,6 @@ public boolean intersects(AABB other) {
&& this.max.getZ() >= other.getMin().getZ() && other.getMax().getZ() >= this.min.getZ();
}
- /**
- * Tests for intersection between the box and a ray defined by a starting
- * point and a direction.
- *
- * @param start The starting point of the ray
- * @param direction The direction of the ray
- * @return An intersection point, if any
- */
- public Optional intersects(Vector3d start, Vector3d direction) {
- checkNotNull(start, "start");
- checkNotNull(direction, "direction");
- // Adapted from: https://github.com/flow/react/blob/develop/src/main/java/com/flowpowered/react/collision/RayCaster.java#L156
- // The box is interpreted as 6 infinite perpendicular places, one for each face (being expanded infinitely)
- // "t" variables are multipliers: start + direction * t gives the intersection point
- // Find the intersections on the -x and +x planes, oriented by direction
- final double txMin;
- final double txMax;
- final Vector3d xNormal;
- if (Math.copySign(1, direction.getX()) > 0) {
- txMin = (this.min.getX() - start.getX()) / direction.getX();
- txMax = (this.max.getX() - start.getX()) / direction.getX();
- xNormal = Vector3d.UNIT_X;
- } else {
- txMin = (this.max.getX() - start.getX()) / direction.getX();
- txMax = (this.min.getX() - start.getX()) / direction.getX();
- xNormal = Vector3d.UNIT_X.negate();
- }
- // Find the intersections on the -y and +y planes, oriented by direction
- final double tyMin;
- final double tyMax;
- final Vector3d yNormal;
- if (Math.copySign(1, direction.getY()) > 0) {
- tyMin = (this.min.getY() - start.getY()) / direction.getY();
- tyMax = (this.max.getY() - start.getY()) / direction.getY();
- yNormal = Vector3d.UNIT_Y;
- } else {
- tyMin = (this.max.getY() - start.getY()) / direction.getY();
- tyMax = (this.min.getY() - start.getY()) / direction.getY();
- yNormal = Vector3d.UNIT_Y.negate();
- }
- // The ray should intersect the -x plane before the +y plane and intersect
- // the -y plane before the +x plane, else it is outside the box
- if (txMin > tyMax || txMax < tyMin) {
- return Optional.empty();
- }
- // Keep track of the intersection normal which also helps with floating point errors
- Vector3d normalMax;
- Vector3d normalMin;
- // The ray intersects only the furthest min plane on the box and only the closest
- // max plane on the box
- double tMin;
- if (tyMin == txMin) {
- tMin = tyMin;
- normalMin = xNormal.negate().sub(yNormal);
- } else if (tyMin > txMin) {
- tMin = tyMin;
- normalMin = yNormal.negate();
- } else {
- tMin = txMin;
- normalMin = xNormal.negate();
- }
- double tMax;
- if (tyMax == txMax) {
- tMax = tyMax;
- normalMax = xNormal.add(yNormal);
- } else if (tyMax < txMax) {
- tMax = tyMax;
- normalMax = yNormal;
- } else {
- tMax = txMax;
- normalMax = xNormal;
- }
- // Find the intersections on the -z and +z planes, oriented by direction
- final double tzMin;
- final double tzMax;
- final Vector3d zNormal;
- if (Math.copySign(1, direction.getZ()) > 0) {
- tzMin = (this.min.getZ() - start.getZ()) / direction.getZ();
- tzMax = (this.max.getZ() - start.getZ()) / direction.getZ();
- zNormal = Vector3d.UNIT_Z;
- } else {
- tzMin = (this.max.getZ() - start.getZ()) / direction.getZ();
- tzMax = (this.min.getZ() - start.getZ()) / direction.getZ();
- zNormal = Vector3d.UNIT_Z.negate();
- }
- // The ray intersects only the furthest min plane on the box and only the closest
- // max plane on the box
- if (tMin > tzMax || tMax < tzMin) {
- return Optional.empty();
- }
- // The ray should intersect the closest plane outside first and the furthest
- // plane outside last
- if (tzMin == tMin) {
- normalMin = normalMin.sub(zNormal);
- } else if (tzMin > tMin) {
- tMin = tzMin;
- normalMin = zNormal.negate();
- }
- if (tzMax == tMax) {
- normalMax = normalMax.add(zNormal);
- } else if (tzMax < tMax) {
- tMax = tzMax;
- normalMax = zNormal;
- }
- // Both intersection points are behind the start, there are no intersections
- if (tMax < 0) {
- return Optional.empty();
- }
- // Find the final intersection multiplier and normal
- final double t;
- Vector3d normal;
- if (tMin < 0) {
- // Only the furthest intersection is after the start, so use it
- t = tMax;
- normal = normalMax;
- } else {
- // Both are after the start, use the closest one
- t = tMin;
- normal = normalMin;
- }
- normal = normal.normalize();
- // To avoid rounding point errors leaving the intersection point just off the plane
- // we check the normal to use the actual plane value from the box coordinates
- final double x;
- final double y;
- final double z;
- if (normal.getX() > 0) {
- x = this.max.getX();
- } else if (normal.getX() < 0) {
- x = this.min.getX();
- } else {
- x = direction.getX() * t + start.getX();
- }
- if (normal.getY() > 0) {
- y = this.max.getY();
- } else if (normal.getY() < 0) {
- y = this.min.getY();
- } else {
- y = direction.getY() * t + start.getY();
- }
- if (normal.getZ() > 0) {
- z = this.max.getZ();
- } else if (normal.getZ() < 0) {
- z = this.min.getZ();
- } else {
- z = direction.getZ() * t + start.getZ();
- }
- return Optional.of(new IntersectionPoint(new Vector3d(x, y, z), normal));
- }
-
/**
* Offsets this bounding box by a given amount and returns a new box.
*
@@ -344,17 +189,6 @@ public AABB offset(Vector3i offset) {
return offset(offset.getX(), offset.getY(), offset.getZ());
}
- /**
- * Offsets this bounding box by a given amount and returns a new box.
- *
- * @param offset The offset to apply
- * @return The new offset box
- */
- public AABB offset(Vector3d offset) {
- checkNotNull(offset, "offset");
- return offset(offset.getX(), offset.getY(), offset.getZ());
- }
-
/**
* Offsets this bounding box by a given amount and returns a new box.
*
@@ -363,53 +197,10 @@ public AABB offset(Vector3d offset) {
* @param z The amount of offset for the z coordinate
* @return The new offset box
*/
- public AABB offset(double x, double y, double z) {
+ public AABB offset(int x, int y, int z) {
return new AABB(this.min.add(x, y, z), this.max.add(x, y, z));
}
-
- /**
- * Expands this bounding box by a given amount in both directions and
- * returns a new box. The expansion is applied half and half to the
- * minimum and maximum corners.
- *
- * @param amount The amount of expansion to apply
- * @return The new expanded box
- */
- public AABB expand(Vector3i amount) {
- checkNotNull(amount, "amount");
- return expand(amount.getX(), amount.getY(), amount.getZ());
- }
-
- /**
- * Expands this bounding box by a given amount in both directions and
- * returns a new box. The expansion is applied half and half to the
- * minimum and maximum corners.
- *
- * @param amount The amount of expansion to apply
- * @return The new expanded box
- */
- public AABB expand(Vector3d amount) {
- checkNotNull(amount, "amount");
- return expand(amount.getX(), amount.getY(), amount.getZ());
- }
-
- /**
- * Expands this bounding box by a given amount in both directions and
- * returns a new box. The expansion is applied half and half to the
- * minimum and maximum corners.
- *
- * @param x The amount of expansion for the x coordinate
- * @param y The amount of expansion for the y coordinate
- * @param z The amount of expansion for the z coordinate
- * @return The new expanded box
- */
- public AABB expand(double x, double y, double z) {
- x /= 2;
- y /= 2;
- z /= 2;
- return new AABB(this.min.sub(x, y, z), this.max.add(x, y, z));
- }
-
+
@Override
public boolean equals(Object other) {
if (this == other) {
diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java
index e9ef7a4f..7870b0b6 100644
--- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java
+++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java
@@ -132,7 +132,7 @@ public boolean isChunkGenerated(Vector2i chunkPos) throws IOException {
@Override
public boolean isAreaGenerated(AABB area) throws IOException {
- if (!isInside(blockPosToChunkPos(area.getMin().toInt())) && !isInside(blockPosToChunkPos(area.getMax().toInt()))) return false;
+ if (!isInside(blockPosToChunkPos(area.getMin())) && !isInside(blockPosToChunkPos(area.getMax()))) return false;
return world.isAreaGenerated(area);
}
diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java
index b9993870..d04dc341 100644
--- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java
+++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java
@@ -94,7 +94,7 @@ public default Collection getChunkList(){
* @throws IOException
*/
public default boolean isAreaGenerated(AABB area) throws IOException {
- return isAreaGenerated(area.getMin().toInt(), area.getMax().toInt());
+ return isAreaGenerated(area.getMin(), area.getMax());
}
/**