floating origin for CollisionEngine.java
This commit is contained in:
parent
919298a3de
commit
70bc473277
@ -1301,6 +1301,8 @@ Save assembly on compile
|
|||||||
Delete old server physics cell on terrain edit
|
Delete old server physics cell on terrain edit
|
||||||
Fix server terrain physics entity positioning
|
Fix server terrain physics entity positioning
|
||||||
Disable client fluid draw cell loading gate
|
Disable client fluid draw cell loading gate
|
||||||
|
Properly differentiate local/world bone attach point calculation
|
||||||
|
Floating origin implementation for collision engine
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -212,7 +212,7 @@ public class CollisionBodyCreation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the offset position of the first geometry in a given body
|
* Sets the offset position of the first geometry in a given body (local to the parent)
|
||||||
* @param collisionEngine The collision engine
|
* @param collisionEngine The collision engine
|
||||||
* @param body The body
|
* @param body The body
|
||||||
* @param offsetPosition The position to offset the first geometry by
|
* @param offsetPosition The position to offset the first geometry by
|
||||||
|
|||||||
@ -116,6 +116,13 @@ public class CollisionEngine {
|
|||||||
//The list of all collidables the engine is currently tracking
|
//The list of all collidables the engine is currently tracking
|
||||||
List<Collidable> collidableList = new ArrayList<Collidable>();
|
List<Collidable> collidableList = new ArrayList<Collidable>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamic spatial offset applied to all operations on the space.
|
||||||
|
* This is used for world origin rebasing.
|
||||||
|
* This makes physics behave more consistently by moving far out objects to center around 0,0,0.
|
||||||
|
*/
|
||||||
|
Vector3d floatingOrigin = new Vector3d(0,0,0);
|
||||||
|
|
||||||
//callbacks for collision check
|
//callbacks for collision check
|
||||||
RayCastCallback rayCastCallback = new RayCastCallback();
|
RayCastCallback rayCastCallback = new RayCastCallback();
|
||||||
|
|
||||||
@ -530,7 +537,7 @@ public class CollisionEngine {
|
|||||||
Entity physicsEntity = collidable.getParent();
|
Entity physicsEntity = collidable.getParent();
|
||||||
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
|
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
|
||||||
Matrix4d inverseTransform = new Matrix4d();
|
Matrix4d inverseTransform = new Matrix4d();
|
||||||
Vector4d rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.getRigidBodyPosition(rigidBody),1));
|
Vector4d rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin),1));
|
||||||
Vector3d calculatedPosition = new Vector3d(rawPos.x,rawPos.y,rawPos.z);
|
Vector3d calculatedPosition = new Vector3d(rawPos.x,rawPos.y,rawPos.z);
|
||||||
Vector3d suggestedPosition = this.suggestMovementPosition(collisionWorldData, calculatedPosition);
|
Vector3d suggestedPosition = this.suggestMovementPosition(collisionWorldData, calculatedPosition);
|
||||||
if(calculatedPosition.distance(suggestedPosition) > 0){
|
if(calculatedPosition.distance(suggestedPosition) > 0){
|
||||||
@ -546,6 +553,48 @@ public class CollisionEngine {
|
|||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebases the world origin
|
||||||
|
*/
|
||||||
|
public void rebaseWorldOrigin(){
|
||||||
|
Globals.profiler.beginCpuSample("rebaseWorldOrigin");
|
||||||
|
spaceLock.lock();
|
||||||
|
if(this.collisionWorldData != null && this.floatingOrigin.x == 0 && this.floatingOrigin.z == 0){
|
||||||
|
int collected = 0;
|
||||||
|
Vector3d newOrigin = new Vector3d();
|
||||||
|
//calculate new origin
|
||||||
|
for(Collidable collidable : collidableList){
|
||||||
|
Entity physicsEntity = collidable.getParent();
|
||||||
|
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
|
||||||
|
if(rigidBody != null){
|
||||||
|
Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition());
|
||||||
|
if(collected == 0){
|
||||||
|
newOrigin.set(currentBodyOffset);
|
||||||
|
} else {
|
||||||
|
float percentExisting = collected / (float)(collected + 1);
|
||||||
|
float percentNew = 1.0f - percentExisting;
|
||||||
|
newOrigin = newOrigin.mul(percentExisting).add(currentBodyOffset.mul(percentNew));
|
||||||
|
}
|
||||||
|
collected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Vector3d delta = new Vector3d(this.floatingOrigin).sub(newOrigin);
|
||||||
|
this.floatingOrigin = this.floatingOrigin.set(newOrigin);
|
||||||
|
//apply new origin to all geoms
|
||||||
|
//calculate new origin
|
||||||
|
for(Collidable collidable : collidableList){
|
||||||
|
Entity physicsEntity = collidable.getParent();
|
||||||
|
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
|
||||||
|
if(rigidBody != null){
|
||||||
|
Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition());
|
||||||
|
rigidBody.setPosition(PhysicsUtils.jomlVecToOdeVec(existingPosition.add(delta)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spaceLock.unlock();
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a collision object with the server
|
* Registers a collision object with the server
|
||||||
* @param body The body
|
* @param body The body
|
||||||
@ -573,7 +622,7 @@ public class CollisionEngine {
|
|||||||
public void listBodyPositions(){
|
public void listBodyPositions(){
|
||||||
for(DBody body : bodies){
|
for(DBody body : bodies){
|
||||||
LoggerInterface.loggerEngine.INFO("" + body);
|
LoggerInterface.loggerEngine.INFO("" + body);
|
||||||
LoggerInterface.loggerEngine.INFO("" + PhysicsUtils.getRigidBodyPosition(body));
|
LoggerInterface.loggerEngine.INFO("" + PhysicsUtils.odeVecToJomlVec(body.getPosition()).add(this.floatingOrigin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,7 +963,7 @@ public class CollisionEngine {
|
|||||||
*/
|
*/
|
||||||
protected void setBodyTransform(DBody body, Vector3d position, Quaterniond rotation){
|
protected void setBodyTransform(DBody body, Vector3d position, Quaterniond rotation){
|
||||||
spaceLock.lock();
|
spaceLock.lock();
|
||||||
body.setPosition(position.x, position.y, position.z);
|
body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z);
|
||||||
body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
||||||
spaceLock.unlock();
|
spaceLock.unlock();
|
||||||
}
|
}
|
||||||
@ -932,7 +981,7 @@ public class CollisionEngine {
|
|||||||
protected void synchronizeData(DBody body, Vector3d position, Quaterniond rotation, Vector3d linearVel, Vector3d angularVel, Vector3d linearForce, Vector3d angularForce){
|
protected void synchronizeData(DBody body, Vector3d position, Quaterniond rotation, Vector3d linearVel, Vector3d angularVel, Vector3d linearForce, Vector3d angularForce){
|
||||||
if(body != null){
|
if(body != null){
|
||||||
spaceLock.lock();
|
spaceLock.lock();
|
||||||
body.setPosition(position.x, position.y, position.z);
|
body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z);
|
||||||
body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
||||||
body.setLinearVel(PhysicsUtils.jomlVecToOdeVec(linearVel));
|
body.setLinearVel(PhysicsUtils.jomlVecToOdeVec(linearVel));
|
||||||
body.setAngularVel(PhysicsUtils.jomlVecToOdeVec(angularVel));
|
body.setAngularVel(PhysicsUtils.jomlVecToOdeVec(angularVel));
|
||||||
@ -951,7 +1000,7 @@ public class CollisionEngine {
|
|||||||
*/
|
*/
|
||||||
protected void setBodyTransform(DBody body, CollidableTemplate template, Vector3d position, Quaterniond rotation, Vector3d scale){
|
protected void setBodyTransform(DBody body, CollidableTemplate template, Vector3d position, Quaterniond rotation, Vector3d scale){
|
||||||
spaceLock.lock();
|
spaceLock.lock();
|
||||||
body.setPosition(position.x, position.y, position.z);
|
body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z);
|
||||||
body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
||||||
DGeom firstGeom = body.getFirstGeom();
|
DGeom firstGeom = body.getFirstGeom();
|
||||||
if(firstGeom instanceof DCylinder){
|
if(firstGeom instanceof DCylinder){
|
||||||
@ -965,14 +1014,14 @@ public class CollisionEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the transform of a geometry
|
* Sets the transform of a geometry (local to the parent)
|
||||||
* @param geom The geometry
|
* @param geom The geometry
|
||||||
* @param position The position
|
* @param position The position
|
||||||
* @param rotation The rotation
|
* @param rotation The rotation
|
||||||
*/
|
*/
|
||||||
protected void setGeomTransform(DGeom geom, Vector3d position, Quaterniond rotation){
|
protected void setGeomTransform(DGeom geom, Vector3d position, Quaterniond rotation){
|
||||||
spaceLock.lock();
|
spaceLock.lock();
|
||||||
geom.setOffsetWorldPosition(position.x, position.y, position.z);
|
geom.setOffsetPosition(position.x, position.y, position.z);
|
||||||
geom.setOffsetQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
geom.setOffsetQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
|
||||||
spaceLock.unlock();
|
spaceLock.unlock();
|
||||||
}
|
}
|
||||||
@ -995,7 +1044,7 @@ public class CollisionEngine {
|
|||||||
protected Vector3d getBodyPosition(DBody body){
|
protected Vector3d getBodyPosition(DBody body){
|
||||||
Vector3d rVal = null;
|
Vector3d rVal = null;
|
||||||
spaceLock.lock();
|
spaceLock.lock();
|
||||||
rVal = PhysicsUtils.odeVecToJomlVec(body.getPosition());
|
rVal = PhysicsUtils.odeVecToJomlVec(body.getPosition()).add(this.floatingOrigin);
|
||||||
spaceLock.unlock();
|
spaceLock.unlock();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,15 +15,6 @@ import electrosphere.game.data.collidable.CollidableTemplate;
|
|||||||
*/
|
*/
|
||||||
public class PhysicsUtils {
|
public class PhysicsUtils {
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current position of a rigid body as a joml vector
|
|
||||||
* @param body The dbody
|
|
||||||
* @return The position
|
|
||||||
*/
|
|
||||||
public static Vector3d getRigidBodyPosition(DBody body){
|
|
||||||
return odeVecToJomlVec(body.getPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the rotation of an ode body as a joml quaternion
|
* Gets the rotation of an ode body as a joml quaternion
|
||||||
* @param body
|
* @param body
|
||||||
|
|||||||
@ -294,7 +294,7 @@ public class AttachUtils {
|
|||||||
Vector3d parentScale
|
Vector3d parentScale
|
||||||
){
|
){
|
||||||
//transform bone space
|
//transform bone space
|
||||||
Vector3d position = AttachUtils.calculateBoneAttachmentPosition(
|
Vector3d position = AttachUtils.calculateBoneAttachmentWorldPosition(
|
||||||
offsetVector,
|
offsetVector,
|
||||||
offsetRotation,
|
offsetRotation,
|
||||||
bonePosition,
|
bonePosition,
|
||||||
@ -331,7 +331,7 @@ public class AttachUtils {
|
|||||||
* @param parentScale The parent's scale
|
* @param parentScale The parent's scale
|
||||||
* @return The position of the attached/child entity
|
* @return The position of the attached/child entity
|
||||||
*/
|
*/
|
||||||
public static Vector3d calculateBoneAttachmentPosition(
|
public static Vector3d calculateBoneAttachmentLocalPosition(
|
||||||
//optional offsets
|
//optional offsets
|
||||||
Vector3d offsetVector,
|
Vector3d offsetVector,
|
||||||
Quaterniond offsetRotation,
|
Quaterniond offsetRotation,
|
||||||
@ -352,6 +352,39 @@ public class AttachUtils {
|
|||||||
position = position.mul(parentScale);
|
position = position.mul(parentScale);
|
||||||
position = position.rotate(new Quaterniond(parentRotation));
|
position = position.rotate(new Quaterniond(parentRotation));
|
||||||
//transform worldspace
|
//transform worldspace
|
||||||
|
// position.add(parentPosition);
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the position of an entity attached to a bone
|
||||||
|
* @param offsetVector The offset position
|
||||||
|
* @param offsetRotation The offset rotation
|
||||||
|
* @param bonePosition The bone's position
|
||||||
|
* @param boneRotation The bone's rotation
|
||||||
|
* @param parentPosition The parent's position
|
||||||
|
* @param parentRotation The parent's rotation
|
||||||
|
* @param parentScale The parent's scale
|
||||||
|
* @return The position of the attached/child entity
|
||||||
|
*/
|
||||||
|
public static Vector3d calculateBoneAttachmentWorldPosition(
|
||||||
|
//optional offsets
|
||||||
|
Vector3d offsetVector,
|
||||||
|
Quaterniond offsetRotation,
|
||||||
|
|
||||||
|
//current bone transform
|
||||||
|
Vector3d bonePosition,
|
||||||
|
Quaterniond boneRotation,
|
||||||
|
|
||||||
|
//parent transforms
|
||||||
|
Vector3d parentPosition,
|
||||||
|
Quaterniond parentRotation,
|
||||||
|
Vector3d parentScale
|
||||||
|
){
|
||||||
|
//transform bone space
|
||||||
|
Vector3d position = calculateBoneAttachmentLocalPosition(offsetVector, offsetRotation, bonePosition, boneRotation, parentPosition, parentRotation, parentScale);
|
||||||
|
//transform worldspace
|
||||||
position.add(parentPosition);
|
position.add(parentPosition);
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
|
|||||||
@ -253,7 +253,7 @@ public class HitboxCollectionState {
|
|||||||
if(parent != null && !isServer && EntityUtils.getActor(parent) != null){
|
if(parent != null && !isServer && EntityUtils.getActor(parent) != null){
|
||||||
if(!this.geoms.isEmpty()){
|
if(!this.geoms.isEmpty()){
|
||||||
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
||||||
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
|
PhysicsUtils.setRigidBodyTransform(collisionEngine, entityPosition, new Quaterniond(), body);
|
||||||
for(String boneName : this.boneHitboxMap.keySet()){
|
for(String boneName : this.boneHitboxMap.keySet()){
|
||||||
if(EntityUtils.getActor(parent).containsBone(boneName)){
|
if(EntityUtils.getActor(parent).containsBone(boneName)){
|
||||||
Vector3d bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName);
|
Vector3d bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName);
|
||||||
@ -293,7 +293,7 @@ public class HitboxCollectionState {
|
|||||||
} else if(parent != null && isServer && EntityUtils.getPoseActor(parent) != null){
|
} else if(parent != null && isServer && EntityUtils.getPoseActor(parent) != null){
|
||||||
if(!this.geoms.isEmpty()){
|
if(!this.geoms.isEmpty()){
|
||||||
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
Vector3d entityPosition = EntityUtils.getPosition(parent);
|
||||||
this.body.setPosition(PhysicsUtils.jomlVecToOdeVec(entityPosition));
|
PhysicsUtils.setRigidBodyTransform(collisionEngine, entityPosition, new Quaterniond(), body);
|
||||||
//
|
//
|
||||||
for(String boneName : this.boneHitboxMap.keySet()){
|
for(String boneName : this.boneHitboxMap.keySet()){
|
||||||
if(EntityUtils.getPoseActor(parent).containsBone(boneName)){
|
if(EntityUtils.getPoseActor(parent).containsBone(boneName)){
|
||||||
@ -358,8 +358,7 @@ public class HitboxCollectionState {
|
|||||||
* @param bonePosition The position of the bone
|
* @param bonePosition The position of the bone
|
||||||
*/
|
*/
|
||||||
private void updateStaticCapsulePosition(CollisionEngine collisionEngine, DGeom geom, HitboxState shapeStatus){
|
private void updateStaticCapsulePosition(CollisionEngine collisionEngine, DGeom geom, HitboxState shapeStatus){
|
||||||
Vector3d parentPos = EntityUtils.getPosition(parent);
|
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, new Vector3d(), new Quaterniond(0.707,0,0,0.707));
|
||||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, parentPos, new Quaterniond(0.707,0,0,0.707));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -388,7 +387,7 @@ public class HitboxCollectionState {
|
|||||||
Vector3d parentScale = new Vector3d(EntityUtils.getScale(parent));
|
Vector3d parentScale = new Vector3d(EntityUtils.getScale(parent));
|
||||||
|
|
||||||
//calculate
|
//calculate
|
||||||
Vector3d hitboxPos = AttachUtils.calculateBoneAttachmentPosition(offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
|
Vector3d hitboxPos = AttachUtils.calculateBoneAttachmentLocalPosition(offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
|
||||||
|
|
||||||
|
|
||||||
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, hitboxPos, new Quaterniond());
|
PhysicsEntityUtils.setGeometryPosition(collisionEngine, geom, hitboxPos, new Quaterniond());
|
||||||
@ -425,7 +424,7 @@ public class HitboxCollectionState {
|
|||||||
Vector3d parentScale = new Vector3d(EntityUtils.getScale(parent));
|
Vector3d parentScale = new Vector3d(EntityUtils.getScale(parent));
|
||||||
|
|
||||||
//calculate
|
//calculate
|
||||||
Vector3d worldPosition = AttachUtils.calculateBoneAttachmentPosition(offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
|
Vector3d worldPosition = AttachUtils.calculateBoneAttachmentLocalPosition(offsetPosition, offsetRotation, bonePositionD, boneRotation, parentPosition, parentRotation, parentScale);
|
||||||
Quaterniond worldRotation = new Quaterniond();
|
Quaterniond worldRotation = new Quaterniond();
|
||||||
|
|
||||||
if(previousWorldPos != null){
|
if(previousWorldPos != null){
|
||||||
|
|||||||
@ -537,10 +537,12 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(worldPos)),0);
|
cellPlayerlessFrameMap.put(groundDataCells.get(this.getServerDataCellKey(worldPos)),0);
|
||||||
loadedCellsLock.unlock();
|
loadedCellsLock.unlock();
|
||||||
} else if(groundDataCells.get(this.getServerDataCellKey(worldPos)) == null) {
|
} else if(groundDataCells.get(this.getServerDataCellKey(worldPos)) == null) {
|
||||||
LoggerInterface.loggerEngine.WARNING(
|
LoggerInterface.loggerEngine.ERROR(
|
||||||
|
new Error(
|
||||||
"Trying to create data cell outside world bounds!\n" +
|
"Trying to create data cell outside world bounds!\n" +
|
||||||
worldPos + "\n" +
|
worldPos + "\n" +
|
||||||
this.serverWorldData.getWorldSizeDiscrete()
|
this.serverWorldData.getWorldSizeDiscrete()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return groundDataCells.get(this.getServerDataCellKey(worldPos));
|
return groundDataCells.get(this.getServerDataCellKey(worldPos));
|
||||||
|
|||||||
@ -218,6 +218,10 @@ public class Realm {
|
|||||||
collisionEngine.clearCollidableImpulseLists();
|
collisionEngine.clearCollidableImpulseLists();
|
||||||
chemistryEngine.clearCollidableImpulseLists();
|
chemistryEngine.clearCollidableImpulseLists();
|
||||||
|
|
||||||
|
//
|
||||||
|
//rebase physics origin
|
||||||
|
this.collisionEngine.rebaseWorldOrigin();
|
||||||
|
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user