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