Fix floating point precision issue with RayUtils method (#1196)

This commit is contained in:
Steank 2022-07-01 17:00:40 +00:00 committed by GitHub
parent 4a40805ca0
commit 18ab44706b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 2 deletions

View File

@ -114,8 +114,8 @@ final class RayUtils {
Point rayCentre = rayStart.add(bbCentre);
// Translate bounding box
Vec bbOffMin = new Vec(collidableStatic.minX() - rayCentre.x() + staticCollidableOffset.x() - moving.width() / 2, collidableStatic.minY() - rayCentre.y() + staticCollidableOffset.y() - moving.height() / 2, collidableStatic.minZ() - rayCentre.z() + staticCollidableOffset.z() - moving.depth() / 2);
Vec bbOffMax = new Vec(collidableStatic.maxX() - rayCentre.x() + staticCollidableOffset.x() + moving.width() / 2, collidableStatic.maxY() - rayCentre.y() + staticCollidableOffset.y() + moving.height() / 2, collidableStatic.maxZ() - rayCentre.z() + staticCollidableOffset.z() + moving.depth() / 2);
Vec bbOffMin = Vec.Operator.EPSILON.apply(collidableStatic.minX() - rayCentre.x() + staticCollidableOffset.x() - moving.width() / 2, collidableStatic.minY() - rayCentre.y() + staticCollidableOffset.y() - moving.height() / 2, collidableStatic.minZ() - rayCentre.z() + staticCollidableOffset.z() - moving.depth() / 2);
Vec bbOffMax = Vec.Operator.EPSILON.apply(collidableStatic.maxX() - rayCentre.x() + staticCollidableOffset.x() + moving.width() / 2, collidableStatic.maxY() - rayCentre.y() + staticCollidableOffset.y() + moving.height() / 2, collidableStatic.maxZ() - rayCentre.z() + staticCollidableOffset.z() + moving.depth() / 2);
// This check is done in 2d. it can be visualised as a rectangle (the face we are checking), and a point.
// If the point is within the rectangle, we know the vector intersects the face.

View File

@ -59,6 +59,21 @@ public class EntityBlockPhysicsIntegrationTest {
assertEqualsPoint(new Pos(0, 42.5, 0), res.newPosition());
}
@Test
public void entityPhysicsCheckShallowAngle(Env env) {
var instance = env.createFlatInstance();
instance.setBlock(13, 99, 16, Block.STONE);
var entity = new Entity(EntityType.ZOMBIE);
entity.setInstance(instance, new Pos(12.812, 100.0, 16.498)).join();
PhysicsResult res = CollisionUtils.handlePhysics(entity, new Vec(0.273, -0.0784, 0.0));
assertTrue(res.isOnGround());
assertTrue(res.collisionY());
assertEqualsPoint(new Vec(13.09, 100, 16.5), res.newPosition());
assertEqualsPoint(new Vec(0.273, 0, 0), res.newVelocity());
}
@Test
public void entityPhysicsCheckFallFence(Env env) {
var instance = env.createFlatInstance();

View File

@ -0,0 +1,23 @@
package net.minestom.server.collision;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class RayUtilsTest {
@Test
void manyHeightIntersectionChecks() {
final Pos rayStart = new Pos(0.5, 1.0, 0.5);
final Vec rayDirection = new Vec(0.273, -0.0784, 0.0);
final BoundingBox collidableStatic = new BoundingBox(1, 1, 1);
final Vec staticCollidableOffset = new Vec(1, 0.0, 0.0);
for(double y = 1; y < 10; y += 0.001D) {
final BoundingBox moving = new BoundingBox(0.6, y, 0.6);
assertTrue(RayUtils.BoundingBoxIntersectionCheck(moving, rayStart, rayDirection, collidableStatic,
staticCollidableOffset), moving.toString());
}
}
}