Fix math, improve physics performance

This commit is contained in:
TheMode 2021-04-11 03:21:38 +02:00
parent 5adbc287b3
commit 6e0202c33b
2 changed files with 29 additions and 19 deletions

View File

@ -32,21 +32,22 @@ public class CollisionUtils {
@NotNull Vector velocityOut) {
// TODO handle collisions with nearby entities (should it be done here?)
final Instance instance = entity.getInstance();
final Chunk originChunk = entity.getChunk();
final Position currentPosition = entity.getPosition();
final BoundingBox boundingBox = entity.getBoundingBox();
Vector intermediaryPosition = new Vector();
final boolean yCollision = stepAxis(instance, currentPosition.toVector(), Y_AXIS, deltaPosition.getY(),
final boolean yCollision = stepAxis(instance, originChunk, currentPosition.toVector(), Y_AXIS, deltaPosition.getY(),
intermediaryPosition,
deltaPosition.getY() > 0 ? boundingBox.getTopFace() : boundingBox.getBottomFace()
);
final boolean xCollision = stepAxis(instance, intermediaryPosition, X_AXIS, deltaPosition.getX(),
final boolean xCollision = stepAxis(instance, originChunk, intermediaryPosition, X_AXIS, deltaPosition.getX(),
intermediaryPosition,
deltaPosition.getX() < 0 ? boundingBox.getLeftFace() : boundingBox.getRightFace()
);
final boolean zCollision = stepAxis(instance, intermediaryPosition, Z_AXIS, deltaPosition.getZ(),
final boolean zCollision = stepAxis(instance, originChunk, intermediaryPosition, Z_AXIS, deltaPosition.getZ(),
intermediaryPosition,
deltaPosition.getZ() > 0 ? boundingBox.getBackFace() : boundingBox.getFrontFace()
);
@ -80,7 +81,11 @@ public class CollisionUtils {
* @param corners the corners to check against
* @return true if a collision has been found
*/
private static boolean stepAxis(Instance instance, Vector startPosition, Vector axis, double stepAmount, Vector positionOut, Vector... corners) {
private static boolean stepAxis(Instance instance,
Chunk originChunk,
Vector startPosition, Vector axis,
double stepAmount, Vector positionOut,
Vector... corners) {
positionOut.copy(startPosition);
if (corners.length == 0)
return false; // avoid degeneracy in following computations
@ -99,7 +104,7 @@ public class CollisionUtils {
// used to determine if 'remainingLength' should be used
boolean collisionFound = false;
for (int i = 0; i < Math.abs(blockLength); i++) {
if (!stepOnce(instance, axis, sign, cornersCopy, cornerPositions)) {
if (!stepOnce(instance, originChunk, axis, sign, cornersCopy, cornerPositions)) {
collisionFound = true;
}
if (collisionFound) {
@ -111,7 +116,7 @@ public class CollisionUtils {
if (!collisionFound) {
Vector direction = new Vector();
direction.copy(axis);
collisionFound = !stepOnce(instance, direction, remainingLength, cornersCopy, cornerPositions);
collisionFound = !stepOnce(instance, originChunk, direction, remainingLength, cornersCopy, cornerPositions);
}
// find the corner which moved the least
@ -138,7 +143,9 @@ public class CollisionUtils {
* @param cornerPositions the corners, converted to BlockPosition (mutable)
* @return false if this method encountered a collision
*/
private static boolean stepOnce(Instance instance, Vector axis, double amount, Vector[] cornersCopy, BlockPosition[] cornerPositions) {
private static boolean stepOnce(Instance instance,
Chunk originChunk,
Vector axis, double amount, Vector[] cornersCopy, BlockPosition[] cornerPositions) {
final double sign = Math.signum(amount);
for (int cornerIndex = 0; cornerIndex < cornersCopy.length; cornerIndex++) {
Vector corner = cornersCopy[cornerIndex];
@ -148,10 +155,13 @@ public class CollisionUtils {
blockPos.setY((int) Math.floor(corner.getY()));
blockPos.setZ((int) Math.floor(corner.getZ()));
final Chunk chunk = instance.getChunkAt(blockPos);
if (!ChunkUtils.isLoaded(chunk)) {
// Collision at chunk border
return false;
Chunk chunk = originChunk;
if (!ChunkUtils.same(originChunk, blockPos.getX(), blockPos.getZ())) {
chunk = instance.getChunkAt(blockPos);
if (!ChunkUtils.isLoaded(chunk)) {
// Collision at chunk border
return false;
}
}
final short blockStateId = chunk.getBlockStateId(blockPos.getX(), blockPos.getY(), blockPos.getZ());

View File

@ -85,17 +85,17 @@ public final class ChunkUtils {
}
public static boolean same(@NotNull Chunk chunk, double x, double z) {
final int chunkX = ChunkUtils.getChunkCoordinate(x);
final int chunkZ = ChunkUtils.getChunkCoordinate(z);
return chunk.getChunkX() != chunkX || chunk.getChunkZ() != chunkZ;
final int chunkX = getChunkCoordinate(x);
final int chunkZ = getChunkCoordinate(z);
return chunk.getChunkX() == chunkX && chunk.getChunkZ() == chunkZ;
}
public static boolean same(@NotNull Position pos1, @NotNull Position pos2) {
final int x1 = ChunkUtils.getChunkCoordinate(pos1.getX());
final int z1 = ChunkUtils.getChunkCoordinate(pos1.getZ());
final int x2 = ChunkUtils.getChunkCoordinate(pos2.getX());
final int z2 = ChunkUtils.getChunkCoordinate(pos2.getZ());
return x1 != x2 || z1 != z2;
final int x1 = getChunkCoordinate(pos1.getX());
final int z1 = getChunkCoordinate(pos1.getZ());
final int x2 = getChunkCoordinate(pos2.getX());
final int z2 = getChunkCoordinate(pos2.getZ());
return x1 == x2 && z1 == z2;
}
/**