Physics Test + revert (#742)

This commit is contained in:
iam 2022-03-13 13:53:20 -04:00 committed by GitHub
parent c890a1ae9a
commit 37a18eced5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 237 additions and 15 deletions

View File

@ -144,24 +144,55 @@ final class BlockCollision {
double remainingZ = deltaPosition.z(); double remainingZ = deltaPosition.z();
// If the movement is small we don't need to run the expensive ray casting. // If the movement is small we don't need to run the expensive ray casting.
// Positions of move less than one can have hardcoded blocks to check for every direction
if (deltaPosition.length() < 1) { if (deltaPosition.length() < 1) {
// Go through all points to check. See if the point after the move will be in a new block
// If the point after is in a new block that new block needs to be checked, otherwise only check the current block
for (Vec point : allFaces) { for (Vec point : allFaces) {
final Vec pointBefore = point.add(entityPosition); Vec pointBefore = point.add(entityPosition);
final Vec pointAfter = pointBefore.add(deltaPosition); Vec pointAfter = point.add(entityPosition).add(deltaPosition);
if (!pointAfter.sameBlock(pointBefore)) {
// Entity can pass through up to 4 blocks. Starting block, Two intermediate blocks, and a final block.
// This means we must check every combination of block movements when an entity moves over an axis.
// 000, 001, 010, 011, etc.
// There are 8 of these combinations
// Checks can be limited by checking if we moved across an axis line
// Pass through (0, 0, 0)
checkBoundingBox(pointBefore.blockX(), pointBefore.blockY(), pointBefore.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
if (pointBefore.blockX() != pointAfter.blockX()) { if (pointBefore.blockX() != pointAfter.blockX()) {
// Pass through (+1, 0, 0)
checkBoundingBox(pointAfter.blockX(), pointBefore.blockY(), pointBefore.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult); checkBoundingBox(pointAfter.blockX(), pointBefore.blockY(), pointBefore.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
// Checks for moving through 4 blocks
if (pointBefore.blockY() != pointAfter.blockY())
// Pass through (+1, +1, 0)
checkBoundingBox(pointAfter.blockX(), pointAfter.blockY(), pointBefore.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
if (pointBefore.blockZ() != pointAfter.blockZ())
// Pass through (+1, 0, +1)
checkBoundingBox(pointAfter.blockX(), pointBefore.blockY(), pointAfter.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
} }
if (pointBefore.blockY() != pointAfter.blockY()) { if (pointBefore.blockY() != pointAfter.blockY()) {
// Pass through (0, +1, 0)
checkBoundingBox(pointBefore.blockX(), pointAfter.blockY(), pointBefore.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult); checkBoundingBox(pointBefore.blockX(), pointAfter.blockY(), pointBefore.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
// Checks for moving through 4 blocks
if (pointBefore.blockZ() != pointAfter.blockZ())
// Pass through (0, +1, +1)
checkBoundingBox(pointBefore.blockX(), pointAfter.blockY(), pointAfter.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
} }
if (pointBefore.blockZ() != pointAfter.blockZ()) { if (pointBefore.blockZ() != pointAfter.blockZ()) {
// Pass through (0, 0, +1)
checkBoundingBox(pointBefore.blockX(), pointBefore.blockY(), pointAfter.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult); checkBoundingBox(pointBefore.blockX(), pointBefore.blockY(), pointAfter.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
} }
}
checkBoundingBox(pointBefore.blockX(), pointBefore.blockY(), pointBefore.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult); // Pass through (+1, +1, +1)
if (pointBefore.blockX() != pointAfter.blockX()
&& pointBefore.blockY() != pointAfter.blockY()
&& pointBefore.blockZ() != pointAfter.blockZ())
checkBoundingBox(pointAfter.blockX(), pointAfter.blockY(), pointAfter.blockZ(), deltaPosition, entityPosition, boundingBox, instance, originChunk, finalResult);
} }
} else { } else {
// When large moves are done we need to ray-cast to find all blocks that could intersect with the movement // When large moves are done we need to ray-cast to find all blocks that could intersect with the movement

View File

@ -210,6 +210,25 @@ public class EntityBlockPhysicsIntegrationTest {
assertEqualsPoint(new Pos(0.7, 42, 0.7), res.newPosition()); assertEqualsPoint(new Pos(0.7, 42, 0.7), res.newPosition());
} }
@Test
public void entityPhysicsCheckEdgeClipSmall(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(1, 42, 1, Block.STONE);
var entity = new Entity(EntityType.ZOMBIE);
entity.setInstance(instance, new Pos(0.6999, 42, 0.6999)).join();
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.702, 0, 0.702));
boolean isFirst = checkPoints(new Pos(1.402, 42, 0.7), res.newPosition());
boolean isSecond = checkPoints(new Pos(0.7, 42, 1.402), res.newPosition());
// First and second are both valid, it depends on the implementation
// If x collision is checked first then isFirst will be true
// If z collision is checked first then isSecond will be true
assertTrue(isFirst || isSecond);
}
@Test @Test
public void entityPhysicsCheckDoorSubBlockNorth(Env env) { public void entityPhysicsCheckDoorSubBlockNorth(Env env) {
var instance = env.createFlatInstance(); var instance = env.createFlatInstance();
@ -430,6 +449,178 @@ public class EntityBlockPhysicsIntegrationTest {
assertEqualsPoint(new Pos(0.7, 42, 0), res.newPosition()); assertEqualsPoint(new Pos(0.7, 42, 0), res.newPosition());
} }
// Checks C include all checks for crossing one intermediate block (3 block checks)
@Test
public void entityPhysicsSmallMoveC0(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(1, 42, 0, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(0.7, 42, 0.5)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.6, 0, 0.6));
assertEqualsPoint(new Pos(1, 42, 1.1), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC1(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(0, 42, 1, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(0.5, 42, 0.7)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.6, 0, 0.6));
assertEqualsPoint(new Pos(1.1, 42, 1), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC2(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(1, 42, 1, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(0.8, 42, 1.3)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.6, 0, -0.6));
assertEqualsPoint(new Pos(1, 42, 0.7), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC3(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(0, 42, 0, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(0.7, 42, 1.1)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.6, 0, -0.6));
assertEqualsPoint(new Pos(1.3, 42, 1), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC4(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(0, 42, 1, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(1.1, 42, 1.3)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(-0.6, 0, -0.6));
assertEqualsPoint(new Pos(1, 42, 0.7), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC5(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(1, 42, 0, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(1.3, 42, 1.1)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(-0.6, 0, -0.6));
assertEqualsPoint(new Pos(0.7, 42, 1), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC6(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(0, 42, 0, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(1.1, 42, 0.7)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(-0.6, 0, 0.6));
assertEqualsPoint(new Pos(1, 42, 1.3), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC7(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(1, 42, 1, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(1.3, 42, 0.8)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(-0.6, 0, 0.6));
assertEqualsPoint(new Pos(0.7, 42, 1), res.newPosition());
}
// Checks CE include checks for crossing two intermediate block (4 block checks)
@Test
public void entityPhysicsSmallMoveC0E(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(1, 43, 0, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(0.51, 42.51, 0.5)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.57, 0.57, 0.57));
assertEqualsPoint(new Pos(1.08, 43, 1.07), res.newPosition());
}
@Test
public void entityPhysicsSmallMoveC1E(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(0, 43, 1, Block.STONE);
BoundingBox bb = new BoundingBox(0, 0, 0);
var entity = new Entity(EntityType.ZOMBIE);
entity.setBoundingBox(bb);
entity.setInstance(instance, new Pos(0.50, 42.51, 0.51)).join();
assertEquals(instance, entity.getInstance());
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.57, 0.57, 0.57));
assertEqualsPoint(new Pos(1.07, 43, 1.08), res.newPosition());
}
@Test @Test
public void entityPhysicsCheckNoCollision(Env env) { public void entityPhysicsCheckNoCollision(Env env) {
var instance = env.createFlatInstance(); var instance = env.createFlatInstance();