mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-02 14:38:26 +01:00
Reduce bounding box allocation
This commit is contained in:
parent
3917d3cb1d
commit
c89f049dad
@ -1,9 +1,14 @@
|
||||
package net.minestom.server.collision;
|
||||
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* See https://wiki.vg/Entity_metadata#Mobs_2
|
||||
@ -13,6 +18,14 @@ public class BoundingBox {
|
||||
private final Entity entity;
|
||||
private final double x, y, z;
|
||||
|
||||
private volatile Pos lastPosition;
|
||||
private List<Vec> bottomFace;
|
||||
private List<Vec> topFace;
|
||||
private List<Vec> leftFace;
|
||||
private List<Vec> rightFace;
|
||||
private List<Vec> frontFace;
|
||||
private List<Vec> backFace;
|
||||
|
||||
/**
|
||||
* Creates a {@link BoundingBox} linked to an {@link Entity} and with a specific size.
|
||||
*
|
||||
@ -211,14 +224,13 @@ public class BoundingBox {
|
||||
*
|
||||
* @return the points at the bottom of the {@link BoundingBox}
|
||||
*/
|
||||
@NotNull
|
||||
public Vec[] getBottomFace() {
|
||||
return new Vec[]{
|
||||
new Vec(getMinX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMaxZ()),
|
||||
new Vec(getMinX(), getMinY(), getMaxZ()),
|
||||
};
|
||||
public @NotNull List<Vec> getBottomFace() {
|
||||
this.bottomFace = get(bottomFace, () ->
|
||||
List.of(new Vec(getMinX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMaxZ()),
|
||||
new Vec(getMinX(), getMinY(), getMaxZ())));
|
||||
return bottomFace;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,14 +238,13 @@ public class BoundingBox {
|
||||
*
|
||||
* @return the points at the top of the {@link BoundingBox}
|
||||
*/
|
||||
@NotNull
|
||||
public Vec[] getTopFace() {
|
||||
return new Vec[]{
|
||||
new Vec(getMinX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMaxZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMaxZ()),
|
||||
};
|
||||
public @NotNull List<Vec> getTopFace() {
|
||||
this.topFace = get(topFace, () ->
|
||||
List.of(new Vec(getMinX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMaxZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMaxZ())));
|
||||
return topFace;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,14 +252,13 @@ public class BoundingBox {
|
||||
*
|
||||
* @return the points on the left face of the {@link BoundingBox}
|
||||
*/
|
||||
@NotNull
|
||||
public Vec[] getLeftFace() {
|
||||
return new Vec[]{
|
||||
new Vec(getMinX(), getMinY(), getMinZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMaxZ()),
|
||||
new Vec(getMinX(), getMinY(), getMaxZ()),
|
||||
};
|
||||
public @NotNull List<Vec> getLeftFace() {
|
||||
this.leftFace = get(leftFace, () ->
|
||||
List.of(new Vec(getMinX(), getMinY(), getMinZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMaxZ()),
|
||||
new Vec(getMinX(), getMinY(), getMaxZ())));
|
||||
return leftFace;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,14 +266,13 @@ public class BoundingBox {
|
||||
*
|
||||
* @return the points on the right face of the {@link BoundingBox}
|
||||
*/
|
||||
@NotNull
|
||||
public Vec[] getRightFace() {
|
||||
return new Vec[]{
|
||||
new Vec(getMaxX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMaxZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMaxZ()),
|
||||
};
|
||||
public @NotNull List<Vec> getRightFace() {
|
||||
this.rightFace = get(rightFace, () ->
|
||||
List.of(new Vec(getMaxX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMaxZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMaxZ())));
|
||||
return rightFace;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,14 +280,13 @@ public class BoundingBox {
|
||||
*
|
||||
* @return the points at the front of the {@link BoundingBox}
|
||||
*/
|
||||
@NotNull
|
||||
public Vec[] getFrontFace() {
|
||||
return new Vec[]{
|
||||
new Vec(getMinX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMinZ()),
|
||||
};
|
||||
public @NotNull List<Vec> getFrontFace() {
|
||||
this.frontFace = get(frontFace, () ->
|
||||
List.of(new Vec(getMinX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMinZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMinZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMinZ())));
|
||||
return frontFace;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -286,14 +294,13 @@ public class BoundingBox {
|
||||
*
|
||||
* @return the points at the back of the {@link BoundingBox}
|
||||
*/
|
||||
@NotNull
|
||||
public Vec[] getBackFace() {
|
||||
return new Vec[]{
|
||||
public @NotNull List<Vec> getBackFace() {
|
||||
this.backFace = get(backFace, () -> List.of(
|
||||
new Vec(getMinX(), getMinY(), getMaxZ()),
|
||||
new Vec(getMaxX(), getMinY(), getMaxZ()),
|
||||
new Vec(getMaxX(), getMaxY(), getMaxZ()),
|
||||
new Vec(getMinX(), getMaxY(), getMaxZ()),
|
||||
};
|
||||
new Vec(getMinX(), getMaxY(), getMaxZ())));
|
||||
return backFace;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -307,4 +314,14 @@ public class BoundingBox {
|
||||
result += "[" + getMinZ() + " : " + getMaxZ() + "]";
|
||||
return result;
|
||||
}
|
||||
|
||||
private @NotNull List<Vec> get(@Nullable List<Vec> face, Supplier<? extends List<Vec>> vecSupplier) {
|
||||
final var lastPos = this.lastPosition;
|
||||
final var entityPos = entity.getPosition();
|
||||
if (face != null && lastPos != null && lastPos.samePoint(entityPos)) {
|
||||
return face;
|
||||
}
|
||||
this.lastPosition = entityPos;
|
||||
return vecSupplier.get();
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,9 @@ import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CollisionUtils {
|
||||
|
||||
private static final Vec Y_AXIS = new Vec(0, 1, 0);
|
||||
@ -71,30 +74,27 @@ public class CollisionUtils {
|
||||
* @param corners the corners to check against
|
||||
* @return result of the step
|
||||
*/
|
||||
private static StepResult stepAxis(Instance instance, Chunk originChunk, Vec startPosition, Vec axis, double stepAmount, Vec... corners) {
|
||||
if (corners.length == 0)
|
||||
return new StepResult(startPosition, false); // avoid degeneracy in following computations
|
||||
|
||||
final Vec[] originalCorners = corners.clone();
|
||||
private static StepResult stepAxis(Instance instance, Chunk originChunk, Vec startPosition, Vec axis, double stepAmount, List<Vec> corners) {
|
||||
final List<Vec> mutableCorners = new ArrayList<>(corners);
|
||||
final double sign = Math.signum(stepAmount);
|
||||
final int blockLength = (int) stepAmount;
|
||||
final double remainingLength = stepAmount - blockLength;
|
||||
// used to determine if 'remainingLength' should be used
|
||||
boolean collisionFound = false;
|
||||
for (int i = 0; i < Math.abs(blockLength); i++) {
|
||||
collisionFound = stepOnce(instance, originChunk, axis, sign, corners);
|
||||
collisionFound = stepOnce(instance, originChunk, axis, sign, mutableCorners);
|
||||
if (collisionFound) break;
|
||||
}
|
||||
|
||||
// add remainingLength
|
||||
if (!collisionFound) {
|
||||
collisionFound = stepOnce(instance, originChunk, axis, remainingLength, corners);
|
||||
collisionFound = stepOnce(instance, originChunk, axis, remainingLength, mutableCorners);
|
||||
}
|
||||
|
||||
// find the corner which moved the least
|
||||
double smallestDisplacement = Double.POSITIVE_INFINITY;
|
||||
for (int i = 0; i < corners.length; i++) {
|
||||
final double displacement = originalCorners[i].distance(corners[i]);
|
||||
for (int i = 0; i < corners.size(); i++) {
|
||||
final double displacement = corners.get(i).distance(mutableCorners.get(i));
|
||||
if (displacement < smallestDisplacement) {
|
||||
smallestDisplacement = displacement;
|
||||
}
|
||||
@ -111,10 +111,10 @@ public class CollisionUtils {
|
||||
* @param corners the corners of the bounding box to consider
|
||||
* @return true if found collision
|
||||
*/
|
||||
private static boolean stepOnce(Instance instance, Chunk originChunk, Vec axis, double amount, Vec[] corners) {
|
||||
private static boolean stepOnce(Instance instance, Chunk originChunk, Vec axis, double amount, List<Vec> corners) {
|
||||
final double sign = Math.signum(amount);
|
||||
for (int cornerIndex = 0; cornerIndex < corners.length; cornerIndex++) {
|
||||
final Vec originalCorner = corners[cornerIndex];
|
||||
for (int cornerIndex = 0; cornerIndex < corners.size(); cornerIndex++) {
|
||||
final Vec originalCorner = corners.get(cornerIndex);
|
||||
final Vec newCorner = originalCorner.add(axis.mul(amount));
|
||||
final Chunk chunk = ChunkUtils.retrieve(instance, originChunk, newCorner);
|
||||
if (!ChunkUtils.isLoaded(chunk)) {
|
||||
@ -122,17 +122,16 @@ public class CollisionUtils {
|
||||
return true;
|
||||
}
|
||||
final Block block = chunk.getBlock(newCorner);
|
||||
|
||||
// TODO: block collision boxes
|
||||
// TODO: for the moment, always consider a full block
|
||||
if (block.isSolid()) {
|
||||
corners[cornerIndex] = new Vec(
|
||||
corners.set(cornerIndex, new Vec(
|
||||
Math.abs(axis.x()) > 10e-16 ? newCorner.blockX() - axis.x() * sign : originalCorner.x(),
|
||||
Math.abs(axis.y()) > 10e-16 ? newCorner.blockY() - axis.y() * sign : originalCorner.y(),
|
||||
Math.abs(axis.z()) > 10e-16 ? newCorner.blockZ() - axis.z() * sign : originalCorner.z());
|
||||
Math.abs(axis.z()) > 10e-16 ? newCorner.blockZ() - axis.z() * sign : originalCorner.z()));
|
||||
return true;
|
||||
}
|
||||
corners[cornerIndex] = newCorner;
|
||||
corners.set(cornerIndex, newCorner);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user