mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-24 03:25:17 +01:00
Merge branch 'master' into mc/1.12
This commit is contained in:
commit
0425243a28
@ -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());
|
||||
|
@ -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.
|
||||
*
|
||||
* <p>The box will never be degenerate: the corners are always not equal and
|
||||
* respect the minimum and maximum properties.</p>
|
||||
*
|
||||
* Using integers, the box has a minimum size of 1 in each direction.
|
||||
*
|
||||
* <p>This class is immutable, all objects returned are either new instances or
|
||||
* itself.</p>
|
||||
*/
|
||||
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<IntersectionPoint> 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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public default Collection<Vector2i> 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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user