Skip to content

Commit 3e2fa6d

Browse files
committed
Little improvement and tentative fix for #12
1 parent eb45eb9 commit 3e2fa6d

File tree

4 files changed

+33
-242
lines changed

4 files changed

+33
-242
lines changed

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelRenderer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ public HiresModelRenderer(ResourcePack resourcePack, RenderSettings renderSettin
5252
}
5353

5454
public HiresModel render(WorldTile tile, AABB region) {
55-
Vector3i modelMin = region.getMin().toInt();
56-
Vector3i modelMax = region.getMax().toInt();
55+
Vector3i modelMin = region.getMin();
56+
Vector3i modelMax = region.getMax();
5757

5858
Vector3i min = modelMin.max(renderSettings.getMin());
5959
Vector3i max = modelMax.min(renderSettings.getMax());

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/util/AABB.java

Lines changed: 29 additions & 238 deletions
Original file line numberDiff line numberDiff line change
@@ -24,42 +24,28 @@
2424
*/
2525
package de.bluecolored.bluemap.core.util;
2626

27-
import static com.google.common.base.Preconditions.checkArgument;
2827
import static com.google.common.base.Preconditions.checkNotNull;
2928

30-
import java.util.Optional;
31-
29+
import com.flowpowered.math.GenericMath;
3230
import com.flowpowered.math.vector.Vector3d;
3331
import com.flowpowered.math.vector.Vector3i;
3432

3533
/**
3634
* An axis aligned bounding box. That is, an un-rotated cuboid.
3735
* It is represented by its minimum and maximum corners.
38-
*
39-
* <p>The box will never be degenerate: the corners are always not equal and
40-
* respect the minimum and maximum properties.</p>
36+
*
37+
* Using integers, the box has a minimum size of 1 in each direction.
4138
*
4239
* <p>This class is immutable, all objects returned are either new instances or
4340
* itself.</p>
4441
*/
4542
public class AABB {
4643

47-
private final Vector3d min;
48-
private final Vector3d max;
49-
private Vector3d size = null;
44+
private final Vector3i min;
45+
private final Vector3i max;
46+
private Vector3i size = null;
5047
private Vector3d center = null;
51-
52-
/**
53-
* Constructs a new bounding box from two opposite corners.
54-
* Fails the resulting box would be degenerate (a dimension is 0).
55-
*
56-
* @param firstCorner The first corner
57-
* @param secondCorner The second corner
58-
*/
59-
public AABB(Vector3i firstCorner, Vector3i secondCorner) {
60-
this(checkNotNull(firstCorner, "firstCorner").toDouble(), checkNotNull(secondCorner, "secondCorner").toDouble());
61-
}
62-
48+
6349
/**
6450
* Constructs a new bounding box from two opposite corners.
6551
* Fails the resulting box would be degenerate (a dimension is 0).
@@ -71,8 +57,8 @@ public AABB(Vector3i firstCorner, Vector3i secondCorner) {
7157
* @param y2 The second corner y coordinate
7258
* @param z2 The second corner z coordinate
7359
*/
74-
public AABB(double x1, double y1, double z1, double x2, double y2, double z2) {
75-
this(new Vector3d(x1, y1, z1), new Vector3d(x2, y2, z2));
60+
public AABB(int x1, int y1, int z1, int x2, int y2, int z2) {
61+
this(new Vector3i(x1, y1, z1), new Vector3i(x2, y2, z2));
7662
}
7763

7864
/**
@@ -82,22 +68,19 @@ public AABB(double x1, double y1, double z1, double x2, double y2, double z2) {
8268
* @param firstCorner The first corner
8369
* @param secondCorner The second corner
8470
*/
85-
public AABB(Vector3d firstCorner, Vector3d secondCorner) {
71+
public AABB(Vector3i firstCorner, Vector3i secondCorner) {
8672
checkNotNull(firstCorner, "firstCorner");
8773
checkNotNull(secondCorner, "secondCorner");
8874
this.min = firstCorner.min(secondCorner);
8975
this.max = firstCorner.max(secondCorner);
90-
checkArgument(this.min.getX() != this.max.getX(), "The box is degenerate on x");
91-
checkArgument(this.min.getY() != this.max.getY(), "The box is degenerate on y");
92-
checkArgument(this.min.getZ() != this.max.getZ(), "The box is degenerate on z");
9376
}
9477

9578
/**
9679
* The minimum corner of the box.
9780
*
9881
* @return The minimum corner
9982
*/
100-
public Vector3d getMin() {
83+
public Vector3i getMin() {
10184
return this.min;
10285
}
10386

@@ -106,7 +89,7 @@ public Vector3d getMin() {
10689
*
10790
* @return The maximum corner
10891
*/
109-
public Vector3d getMax() {
92+
public Vector3i getMax() {
11093
return this.max;
11194
}
11295

@@ -117,7 +100,7 @@ public Vector3d getMax() {
117100
*/
118101
public Vector3d getCenter() {
119102
if (this.center == null) {
120-
this.center = this.min.add(getSize().div(2));
103+
this.center = this.min.toDouble().add(getSize().toDouble().div(2));
121104
}
122105
return this.center;
123106
}
@@ -127,9 +110,9 @@ public Vector3d getCenter() {
127110
*
128111
* @return The size
129112
*/
130-
public Vector3d getSize() {
113+
public Vector3i getSize() {
131114
if (this.size == null) {
132-
this.size = this.max.sub(this.min);
115+
this.size = this.max.sub(this.min).add(Vector3i.ONE);
133116
}
134117
return this.size;
135118
}
@@ -165,6 +148,18 @@ public boolean contains(Vector3d point) {
165148
* @return Whether or not the box contains the point
166149
*/
167150
public boolean contains(double x, double y, double z) {
151+
return contains(GenericMath.floor(x), GenericMath.floor(y), GenericMath.floor(z));
152+
}
153+
154+
/**
155+
* Checks if the bounding box contains a point.
156+
*
157+
* @param x The x coordinate of the point
158+
* @param y The y coordinate of the point
159+
* @param z The z coordinate of the point
160+
* @return Whether or not the box contains the point
161+
*/
162+
public boolean contains(int x, int y, int z) {
168163
return this.min.getX() <= x && this.max.getX() >= x
169164
&& this.min.getY() <= y && this.max.getY() >= y
170165
&& this.min.getZ() <= z && this.max.getZ() >= z;
@@ -183,156 +178,6 @@ public boolean intersects(AABB other) {
183178
&& this.max.getZ() >= other.getMin().getZ() && other.getMax().getZ() >= this.min.getZ();
184179
}
185180

186-
/**
187-
* Tests for intersection between the box and a ray defined by a starting
188-
* point and a direction.
189-
*
190-
* @param start The starting point of the ray
191-
* @param direction The direction of the ray
192-
* @return An intersection point, if any
193-
*/
194-
public Optional<IntersectionPoint> intersects(Vector3d start, Vector3d direction) {
195-
checkNotNull(start, "start");
196-
checkNotNull(direction, "direction");
197-
// Adapted from: https://github.com/flow/react/blob/develop/src/main/java/com/flowpowered/react/collision/RayCaster.java#L156
198-
// The box is interpreted as 6 infinite perpendicular places, one for each face (being expanded infinitely)
199-
// "t" variables are multipliers: start + direction * t gives the intersection point
200-
// Find the intersections on the -x and +x planes, oriented by direction
201-
final double txMin;
202-
final double txMax;
203-
final Vector3d xNormal;
204-
if (Math.copySign(1, direction.getX()) > 0) {
205-
txMin = (this.min.getX() - start.getX()) / direction.getX();
206-
txMax = (this.max.getX() - start.getX()) / direction.getX();
207-
xNormal = Vector3d.UNIT_X;
208-
} else {
209-
txMin = (this.max.getX() - start.getX()) / direction.getX();
210-
txMax = (this.min.getX() - start.getX()) / direction.getX();
211-
xNormal = Vector3d.UNIT_X.negate();
212-
}
213-
// Find the intersections on the -y and +y planes, oriented by direction
214-
final double tyMin;
215-
final double tyMax;
216-
final Vector3d yNormal;
217-
if (Math.copySign(1, direction.getY()) > 0) {
218-
tyMin = (this.min.getY() - start.getY()) / direction.getY();
219-
tyMax = (this.max.getY() - start.getY()) / direction.getY();
220-
yNormal = Vector3d.UNIT_Y;
221-
} else {
222-
tyMin = (this.max.getY() - start.getY()) / direction.getY();
223-
tyMax = (this.min.getY() - start.getY()) / direction.getY();
224-
yNormal = Vector3d.UNIT_Y.negate();
225-
}
226-
// The ray should intersect the -x plane before the +y plane and intersect
227-
// the -y plane before the +x plane, else it is outside the box
228-
if (txMin > tyMax || txMax < tyMin) {
229-
return Optional.empty();
230-
}
231-
// Keep track of the intersection normal which also helps with floating point errors
232-
Vector3d normalMax;
233-
Vector3d normalMin;
234-
// The ray intersects only the furthest min plane on the box and only the closest
235-
// max plane on the box
236-
double tMin;
237-
if (tyMin == txMin) {
238-
tMin = tyMin;
239-
normalMin = xNormal.negate().sub(yNormal);
240-
} else if (tyMin > txMin) {
241-
tMin = tyMin;
242-
normalMin = yNormal.negate();
243-
} else {
244-
tMin = txMin;
245-
normalMin = xNormal.negate();
246-
}
247-
double tMax;
248-
if (tyMax == txMax) {
249-
tMax = tyMax;
250-
normalMax = xNormal.add(yNormal);
251-
} else if (tyMax < txMax) {
252-
tMax = tyMax;
253-
normalMax = yNormal;
254-
} else {
255-
tMax = txMax;
256-
normalMax = xNormal;
257-
}
258-
// Find the intersections on the -z and +z planes, oriented by direction
259-
final double tzMin;
260-
final double tzMax;
261-
final Vector3d zNormal;
262-
if (Math.copySign(1, direction.getZ()) > 0) {
263-
tzMin = (this.min.getZ() - start.getZ()) / direction.getZ();
264-
tzMax = (this.max.getZ() - start.getZ()) / direction.getZ();
265-
zNormal = Vector3d.UNIT_Z;
266-
} else {
267-
tzMin = (this.max.getZ() - start.getZ()) / direction.getZ();
268-
tzMax = (this.min.getZ() - start.getZ()) / direction.getZ();
269-
zNormal = Vector3d.UNIT_Z.negate();
270-
}
271-
// The ray intersects only the furthest min plane on the box and only the closest
272-
// max plane on the box
273-
if (tMin > tzMax || tMax < tzMin) {
274-
return Optional.empty();
275-
}
276-
// The ray should intersect the closest plane outside first and the furthest
277-
// plane outside last
278-
if (tzMin == tMin) {
279-
normalMin = normalMin.sub(zNormal);
280-
} else if (tzMin > tMin) {
281-
tMin = tzMin;
282-
normalMin = zNormal.negate();
283-
}
284-
if (tzMax == tMax) {
285-
normalMax = normalMax.add(zNormal);
286-
} else if (tzMax < tMax) {
287-
tMax = tzMax;
288-
normalMax = zNormal;
289-
}
290-
// Both intersection points are behind the start, there are no intersections
291-
if (tMax < 0) {
292-
return Optional.empty();
293-
}
294-
// Find the final intersection multiplier and normal
295-
final double t;
296-
Vector3d normal;
297-
if (tMin < 0) {
298-
// Only the furthest intersection is after the start, so use it
299-
t = tMax;
300-
normal = normalMax;
301-
} else {
302-
// Both are after the start, use the closest one
303-
t = tMin;
304-
normal = normalMin;
305-
}
306-
normal = normal.normalize();
307-
// To avoid rounding point errors leaving the intersection point just off the plane
308-
// we check the normal to use the actual plane value from the box coordinates
309-
final double x;
310-
final double y;
311-
final double z;
312-
if (normal.getX() > 0) {
313-
x = this.max.getX();
314-
} else if (normal.getX() < 0) {
315-
x = this.min.getX();
316-
} else {
317-
x = direction.getX() * t + start.getX();
318-
}
319-
if (normal.getY() > 0) {
320-
y = this.max.getY();
321-
} else if (normal.getY() < 0) {
322-
y = this.min.getY();
323-
} else {
324-
y = direction.getY() * t + start.getY();
325-
}
326-
if (normal.getZ() > 0) {
327-
z = this.max.getZ();
328-
} else if (normal.getZ() < 0) {
329-
z = this.min.getZ();
330-
} else {
331-
z = direction.getZ() * t + start.getZ();
332-
}
333-
return Optional.of(new IntersectionPoint(new Vector3d(x, y, z), normal));
334-
}
335-
336181
/**
337182
* Offsets this bounding box by a given amount and returns a new box.
338183
*
@@ -344,17 +189,6 @@ public AABB offset(Vector3i offset) {
344189
return offset(offset.getX(), offset.getY(), offset.getZ());
345190
}
346191

347-
/**
348-
* Offsets this bounding box by a given amount and returns a new box.
349-
*
350-
* @param offset The offset to apply
351-
* @return The new offset box
352-
*/
353-
public AABB offset(Vector3d offset) {
354-
checkNotNull(offset, "offset");
355-
return offset(offset.getX(), offset.getY(), offset.getZ());
356-
}
357-
358192
/**
359193
* Offsets this bounding box by a given amount and returns a new box.
360194
*
@@ -363,53 +197,10 @@ public AABB offset(Vector3d offset) {
363197
* @param z The amount of offset for the z coordinate
364198
* @return The new offset box
365199
*/
366-
public AABB offset(double x, double y, double z) {
200+
public AABB offset(int x, int y, int z) {
367201
return new AABB(this.min.add(x, y, z), this.max.add(x, y, z));
368202
}
369-
370-
/**
371-
* Expands this bounding box by a given amount in both directions and
372-
* returns a new box. The expansion is applied half and half to the
373-
* minimum and maximum corners.
374-
*
375-
* @param amount The amount of expansion to apply
376-
* @return The new expanded box
377-
*/
378-
public AABB expand(Vector3i amount) {
379-
checkNotNull(amount, "amount");
380-
return expand(amount.getX(), amount.getY(), amount.getZ());
381-
}
382-
383-
/**
384-
* Expands this bounding box by a given amount in both directions and
385-
* returns a new box. The expansion is applied half and half to the
386-
* minimum and maximum corners.
387-
*
388-
* @param amount The amount of expansion to apply
389-
* @return The new expanded box
390-
*/
391-
public AABB expand(Vector3d amount) {
392-
checkNotNull(amount, "amount");
393-
return expand(amount.getX(), amount.getY(), amount.getZ());
394-
}
395-
396-
/**
397-
* Expands this bounding box by a given amount in both directions and
398-
* returns a new box. The expansion is applied half and half to the
399-
* minimum and maximum corners.
400-
*
401-
* @param x The amount of expansion for the x coordinate
402-
* @param y The amount of expansion for the y coordinate
403-
* @param z The amount of expansion for the z coordinate
404-
* @return The new expanded box
405-
*/
406-
public AABB expand(double x, double y, double z) {
407-
x /= 2;
408-
y /= 2;
409-
z /= 2;
410-
return new AABB(this.min.sub(x, y, z), this.max.add(x, y, z));
411-
}
412-
203+
413204
@Override
414205
public boolean equals(Object other) {
415206
if (this == other) {

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/SlicedWorld.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public boolean isChunkGenerated(Vector2i chunkPos) throws IOException {
132132

133133
@Override
134134
public boolean isAreaGenerated(AABB area) throws IOException {
135-
if (!isInside(blockPosToChunkPos(area.getMin().toInt())) && !isInside(blockPosToChunkPos(area.getMax().toInt()))) return false;
135+
if (!isInside(blockPosToChunkPos(area.getMin())) && !isInside(blockPosToChunkPos(area.getMax()))) return false;
136136

137137
return world.isAreaGenerated(area);
138138
}

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/World.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public default Collection<Vector2i> getChunkList(){
9494
* @throws IOException
9595
*/
9696
public default boolean isAreaGenerated(AABB area) throws IOException {
97-
return isAreaGenerated(area.getMin().toInt(), area.getMax().toInt());
97+
return isAreaGenerated(area.getMin(), area.getMax());
9898
}
9999

100100
/**

0 commit comments

Comments
 (0)