mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-29 08:27:03 +01:00
Contact points and Friction
- Entities are now moved with the relative motion of their contact point
This commit is contained in:
parent
ebc2944788
commit
53a58def49
2 changed files with 76 additions and 49 deletions
|
@ -130,28 +130,40 @@ public class ContraptionCollider {
|
||||||
if (bounds == null)
|
if (bounds == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO);
|
||||||
double conRotX = contraptionRotation.z;
|
double conRotX = contraptionRotation.z;
|
||||||
double conRotY = contraptionRotation.y;
|
double conRotY = contraptionRotation.y;
|
||||||
double conRotZ = contraptionRotation.x;
|
double conRotZ = contraptionRotation.x;
|
||||||
|
Vec3d conMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec());
|
||||||
|
Vec3d conAngularMotion = contraptionRotation.subtract(contraptionEntity.getPrevRotationVec());
|
||||||
|
Vec3d contraptionCentreOffset = contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0);
|
||||||
|
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
||||||
|
Matrix3d rotation = null;
|
||||||
|
|
||||||
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(2)
|
for (Entity entity : world.getEntitiesWithinAABB((EntityType<?>) null, bounds.grow(2)
|
||||||
.expand(0, 32, 0), contraptionEntity::canCollideWith)) {
|
.expand(0, 32, 0), contraptionEntity::canCollideWith)) {
|
||||||
boolean serverPlayer = entity instanceof PlayerEntity && !world.isRemote;
|
boolean serverPlayer = entity instanceof PlayerEntity && !world.isRemote;
|
||||||
|
|
||||||
|
// Init matrix
|
||||||
|
if (rotation == null) {
|
||||||
|
rotation = new Matrix3d().asIdentity();
|
||||||
|
if (!axisAlignedCollision) {
|
||||||
|
rotation.multiply(new Matrix3d().asXRotation(AngleHelper.rad(-conRotX)));
|
||||||
|
rotation.multiply(new Matrix3d().asYRotation(AngleHelper.rad(conRotY)));
|
||||||
|
rotation.multiply(new Matrix3d().asZRotation(AngleHelper.rad(-conRotZ)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Transform entity position and motion to local space
|
// Transform entity position and motion to local space
|
||||||
Vec3d centerOfBlock = VecHelper.getCenterOf(BlockPos.ZERO);
|
|
||||||
Vec3d entityPosition = entity.getPositionVec();
|
Vec3d entityPosition = entity.getPositionVec();
|
||||||
AxisAlignedBB entityBounds = entity.getBoundingBox();
|
AxisAlignedBB entityBounds = entity.getBoundingBox();
|
||||||
Vec3d centerY = new Vec3d(0, entityBounds.getYSize() / 2, 0);
|
Vec3d centerY = new Vec3d(0, entityBounds.getYSize() / 2, 0);
|
||||||
Vec3d motion = entity.getMotion();
|
Vec3d motion = entity.getMotion();
|
||||||
boolean axisAlignedCollision = contraptionRotation.equals(Vec3d.ZERO);
|
|
||||||
|
|
||||||
Vec3d position =
|
|
||||||
entityPosition.subtract(contraptionEntity.stationary ? centerOfBlock : Vec3d.ZERO.add(0, 0.5, 0))
|
|
||||||
.add(centerY);
|
|
||||||
|
|
||||||
|
Vec3d position = entityPosition.subtract(contraptionCentreOffset)
|
||||||
|
.add(centerY);
|
||||||
position = position.subtract(contraptionPosition);
|
position = position.subtract(contraptionPosition);
|
||||||
position = VecHelper.rotate(position, -conRotX, -conRotY, -conRotZ);
|
position = rotation.transform(position);
|
||||||
position = position.add(centerOfBlock)
|
position = position.add(centerOfBlock)
|
||||||
.subtract(centerY)
|
.subtract(centerY)
|
||||||
.subtract(entityPosition);
|
.subtract(entityPosition);
|
||||||
|
@ -165,18 +177,10 @@ public class ContraptionCollider {
|
||||||
.count() == 0)
|
.count() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!axisAlignedCollision)
|
|
||||||
motion = VecHelper.rotate(motion, -conRotX, -conRotY, -conRotZ);
|
|
||||||
|
|
||||||
// Prepare entity bounds
|
// Prepare entity bounds
|
||||||
OrientedBB obb = new OrientedBB(localBB);
|
OrientedBB obb = new OrientedBB(localBB);
|
||||||
if (!axisAlignedCollision) {
|
obb.setRotation(rotation);
|
||||||
Matrix3d rotation = new Matrix3d().asIdentity();
|
motion = rotation.transform(motion);
|
||||||
rotation.multiply(new Matrix3d().asXRotation(AngleHelper.rad(-conRotX)));
|
|
||||||
rotation.multiply(new Matrix3d().asYRotation(AngleHelper.rad(conRotY)));
|
|
||||||
rotation.multiply(new Matrix3d().asZRotation(AngleHelper.rad(-conRotZ)));
|
|
||||||
obb.setRotation(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
|
// Vec3d visualizerOrigin = new Vec3d(10, 64, 0);
|
||||||
// CollisionDebugger.OBB = obb.copy();
|
// CollisionDebugger.OBB = obb.copy();
|
||||||
|
@ -233,10 +237,14 @@ public class ContraptionCollider {
|
||||||
Vec3d entityMotion = entity.getMotion();
|
Vec3d entityMotion = entity.getMotion();
|
||||||
Vec3d totalResponse = collisionResponse.getValue();
|
Vec3d totalResponse = collisionResponse.getValue();
|
||||||
Vec3d motionResponse = allowedMotion.getValue();
|
Vec3d motionResponse = allowedMotion.getValue();
|
||||||
|
boolean hardCollision = !totalResponse.equals(Vec3d.ZERO);
|
||||||
|
|
||||||
|
rotation.transpose();
|
||||||
|
motionResponse = rotation.transform(motionResponse);
|
||||||
|
totalResponse = rotation.transform(totalResponse);
|
||||||
|
rotation.transpose();
|
||||||
|
|
||||||
if (futureCollision.isTrue() && !serverPlayer) {
|
if (futureCollision.isTrue() && !serverPlayer) {
|
||||||
if (!axisAlignedCollision)
|
|
||||||
motionResponse = VecHelper.rotate(motionResponse, conRotX, conRotY, conRotZ);
|
|
||||||
if (motionResponse.y != entityMotion.y) {
|
if (motionResponse.y != entityMotion.y) {
|
||||||
entity.setMotion(entityMotion.mul(1, 0, 1)
|
entity.setMotion(entityMotion.mul(1, 0, 1)
|
||||||
.add(0, motionResponse.y, 0));
|
.add(0, motionResponse.y, 0));
|
||||||
|
@ -244,47 +252,58 @@ public class ContraptionCollider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!axisAlignedCollision)
|
Vec3d contactPointMotion = Vec3d.ZERO;
|
||||||
totalResponse = VecHelper.rotate(totalResponse, conRotX, conRotY, conRotZ);
|
|
||||||
|
|
||||||
if (surfaceCollision.isTrue()) {
|
if (surfaceCollision.isTrue()) {
|
||||||
// entity.handleFallDamage(entity.fallDistance, 1); tunnelling issue
|
// entity.handleFallDamage(entity.fallDistance, 1); tunnelling issue
|
||||||
entity.fallDistance = 0;
|
entity.fallDistance = 0;
|
||||||
entity.onGround = true;
|
entity.onGround = true;
|
||||||
if (!serverPlayer) {
|
if (!serverPlayer) {
|
||||||
|
|
||||||
|
Vec3d contactPoint = entityPosition.subtract(contraptionCentreOffset)
|
||||||
|
.subtract(contraptionPosition);
|
||||||
|
contactPoint =
|
||||||
|
VecHelper.rotate(contactPoint, conAngularMotion.z, conAngularMotion.y, conAngularMotion.x);
|
||||||
|
contactPoint = contactPoint.add(contraptionPosition)
|
||||||
|
.add(contraptionCentreOffset)
|
||||||
|
.add(conMotion);
|
||||||
|
contactPointMotion = contactPoint.subtract(entityPosition);
|
||||||
|
|
||||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> checkForClientPlayerCollision(entity));
|
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> checkForClientPlayerCollision(entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalResponse.equals(Vec3d.ZERO))
|
if (hardCollision) {
|
||||||
|
double motionX = entityMotion.getX();
|
||||||
|
double motionY = entityMotion.getY();
|
||||||
|
double motionZ = entityMotion.getZ();
|
||||||
|
double intersectX = totalResponse.getX();
|
||||||
|
double intersectY = totalResponse.getY();
|
||||||
|
double intersectZ = totalResponse.getZ();
|
||||||
|
|
||||||
|
double horizonalEpsilon = 1 / 128f;
|
||||||
|
if (motionX != 0 && Math.abs(intersectX) > horizonalEpsilon && motionX > 0 == intersectX < 0)
|
||||||
|
entityMotion = entityMotion.mul(0, 1, 1);
|
||||||
|
if (motionY != 0 && intersectY != 0 && motionY > 0 == intersectY < 0)
|
||||||
|
entityMotion = entityMotion.mul(1, 0, 1);
|
||||||
|
if (motionZ != 0 && Math.abs(intersectZ) > horizonalEpsilon && motionZ > 0 == intersectZ < 0)
|
||||||
|
entityMotion = entityMotion.mul(1, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hardCollision && surfaceCollision.isFalse())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
double motionX = entityMotion.getX();
|
if (serverPlayer && entity instanceof ServerPlayerEntity) {
|
||||||
double motionY = entityMotion.getY();
|
|
||||||
double motionZ = entityMotion.getZ();
|
|
||||||
double intersectX = totalResponse.getX();
|
|
||||||
double intersectY = totalResponse.getY();
|
|
||||||
double intersectZ = totalResponse.getZ();
|
|
||||||
|
|
||||||
double horizonalEpsilon = 1 / 128f;
|
|
||||||
if (motionX != 0 && Math.abs(intersectX) > horizonalEpsilon && motionX > 0 == intersectX < 0)
|
|
||||||
entityMotion = entityMotion.mul(0, 1, 1);
|
|
||||||
if (motionY != 0 && intersectY != 0 && motionY > 0 == intersectY < 0)
|
|
||||||
entityMotion = entityMotion.mul(1, 0, 1);
|
|
||||||
if (motionZ != 0 && Math.abs(intersectZ) > horizonalEpsilon && motionZ > 0 == intersectZ < 0)
|
|
||||||
entityMotion = entityMotion.mul(1, 1, 0);
|
|
||||||
|
|
||||||
if (entity instanceof ServerPlayerEntity)
|
|
||||||
((ServerPlayerEntity) entity).connection.floatingTickCount = 0;
|
((ServerPlayerEntity) entity).connection.floatingTickCount = 0;
|
||||||
|
continue;
|
||||||
if (!serverPlayer) {
|
|
||||||
Vec3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
|
||||||
contraptionEntity.collidingEntities.add(entity);
|
|
||||||
entity.velocityChanged = true;
|
|
||||||
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
|
||||||
entityPosition.z + allowedMovement.z);
|
|
||||||
entity.setMotion(entityMotion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
totalResponse = totalResponse.add(contactPointMotion);
|
||||||
|
Vec3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
||||||
|
contraptionEntity.collidingEntities.add(entity);
|
||||||
|
entity.velocityChanged = true;
|
||||||
|
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
||||||
|
entityPosition.z + allowedMovement.z);
|
||||||
|
entity.setMotion(entityMotion);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -636,6 +636,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
return new Vec3d(getPitch(1), getYaw(1), getRoll(1));
|
return new Vec3d(getPitch(1), getYaw(1), getRoll(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vec3d getPrevRotationVec() {
|
||||||
|
return new Vec3d(getPitch(0), getYaw(0), getRoll(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3d getPrevPositionVec() {
|
||||||
|
return new Vec3d(prevPosX, prevPosY, prevPosZ);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canCollideWith(Entity e) {
|
public boolean canCollideWith(Entity e) {
|
||||||
if (e instanceof PlayerEntity && e.isSpectator())
|
if (e instanceof PlayerEntity && e.isSpectator())
|
||||||
return false;
|
return false;
|
||||||
|
@ -647,14 +655,14 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
|
||||||
return false;
|
return false;
|
||||||
if (e instanceof IProjectile)
|
if (e instanceof IProjectile)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Entity riding = this.getRidingEntity();
|
Entity riding = this.getRidingEntity();
|
||||||
while (riding != null) {
|
while (riding != null) {
|
||||||
if (riding == e)
|
if (riding == e)
|
||||||
return false;
|
return false;
|
||||||
riding = riding.getRidingEntity();
|
riding = riding.getRidingEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.getPushReaction() == PushReaction.NORMAL;
|
return e.getPushReaction() == PushReaction.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue