work on body position management

This commit is contained in:
austin 2025-06-03 14:15:02 -04:00
parent 0b4c08796e
commit 81337d0eb9
35 changed files with 474 additions and 221 deletions

View File

@ -2100,6 +2100,7 @@ Actually fix pathing spinlock
Support for observing ai entities Support for observing ai entities
ServerGroundMovementTree supports collidable entities ServerGroundMovementTree supports collidable entities
ServerGroundMovementTree geom work ServerGroundMovementTree geom work
ServerLODComponent replaces bodies with geometries instead of just destroying the geometries

View File

@ -189,7 +189,7 @@ public class ClientState {
* Constructor * Constructor
*/ */
public ClientState(){ public ClientState(){
this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, new CollisionEngine(), CollisionEngine.create(new ClientChemistryCollisionCallback()), new CollisionEngine()); this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, new CollisionEngine("clientPhysics"), CollisionEngine.create("clientChem", new ClientChemistryCollisionCallback()), new CollisionEngine("clientInteraction"));
this.clientTemporalService = (ClientTemporalService)Globals.engineState.serviceManager.registerService(new ClientTemporalService()); this.clientTemporalService = (ClientTemporalService)Globals.engineState.serviceManager.registerService(new ClientTemporalService());
} }

View File

@ -7,13 +7,9 @@ import java.util.concurrent.locks.ReentrantLock;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3i;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
import electrosphere.client.block.BlockChunkData;
import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.client.ui.menu.ingame.InteractionTargetMenu; import electrosphere.client.ui.menu.ingame.InteractionTargetMenu;
import electrosphere.collision.CollisionBodyCreation; import electrosphere.collision.CollisionBodyCreation;
import electrosphere.collision.CollisionEngine; import electrosphere.collision.CollisionEngine;
@ -24,9 +20,7 @@ import electrosphere.engine.Globals;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils; import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.EntityTypes.EntityType;
import electrosphere.entity.types.common.CommonEntityUtils; import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
/** /**
* Manages the interaction state * Manages the interaction state
@ -90,7 +84,7 @@ public class ClientInteractionEngine {
rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody); rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody);
Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable); Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal));
} break; } break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
// //
@ -125,7 +119,7 @@ public class ClientInteractionEngine {
rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody); rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody);
Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable); Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal));
} break; } break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
// //
@ -161,7 +155,7 @@ public class ClientInteractionEngine {
rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.INTERACTION_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody); rVal.putData(EntityDataStrings.INTERACTION_BODY, rigidBody);
Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable); Globals.clientState.clientSceneWrapper.getInteractionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal));
} break; } break;
default: { default: {
throw new Error("Unsupported shape type! " + physicsTemplate.getType()); throw new Error("Unsupported shape type! " + physicsTemplate.getType());

View File

@ -1,6 +1,7 @@
package electrosphere.collision; package electrosphere.collision;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -10,7 +11,6 @@ import java.util.concurrent.locks.ReentrantLock;
import org.joml.Matrix4d; import org.joml.Matrix4d;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector4d;
import org.ode4j.math.DVector3; import org.ode4j.math.DVector3;
import org.ode4j.ode.DBhvSpace; import org.ode4j.ode.DBhvSpace;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
@ -100,6 +100,11 @@ public class CollisionEngine {
* Distance from current floating point origin to trigger a rebase * Distance from current floating point origin to trigger a rebase
*/ */
private static final double REBASE_TRIGGER_DISTANCE = 16; private static final double REBASE_TRIGGER_DISTANCE = 16;
/**
* Maximum expected distance from local origin
*/
private static final double MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN = 3000;
/** /**
* world data that the collision engine leverages for position correction and the like * world data that the collision engine leverages for position correction and the like
@ -188,16 +193,27 @@ public class CollisionEngine {
*/ */
private int geomCount = 0; private int geomCount = 0;
/**
* Tracks whether the engine has rebased or not
*/
private boolean hasRebased = false;
/** /**
* buffer for storing potential collisions * buffer for storing potential collisions
*/ */
private DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); private DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS);
/**
* The name of the collision engine
*/
private final String name;
/** /**
* Constructor * Constructor
*/ */
public CollisionEngine(){ public CollisionEngine(String name){
this.name = name;
world = OdeHelper.createWorld(); world = OdeHelper.createWorld();
world.setGravity(0,-GRAVITY_MAGNITUDE,0); world.setGravity(0,-GRAVITY_MAGNITUDE,0);
world.setQuickStepNumIterations(QUICKSTEP_ITERATION_COUNT); world.setQuickStepNumIterations(QUICKSTEP_ITERATION_COUNT);
@ -221,8 +237,8 @@ public class CollisionEngine {
/** /**
* Creates a collision engine with a specified callback * Creates a collision engine with a specified callback
*/ */
public static CollisionEngine create(CollisionResolutionCallback callback){ public static CollisionEngine create(String name, CollisionResolutionCallback callback){
CollisionEngine rVal = new CollisionEngine(); CollisionEngine rVal = new CollisionEngine(name);
rVal.setCollisionResolutionCallback(callback); rVal.setCollisionResolutionCallback(callback);
return rVal; return rVal;
} }
@ -243,13 +259,6 @@ public class CollisionEngine {
case Collidable.TYPE_CREATURE: case Collidable.TYPE_CREATURE:
switch(impactor.getType()){ switch(impactor.getType()){
case Collidable.TYPE_STATIC: case Collidable.TYPE_STATIC:
// System.out.println(EntityUtils.getPosition(impactor.getParent()) + " " + EntityUtils.getPosition(receiver.getParent()));
// System.out.println();
// System.out.println("Terrain-creature collision: " + normal + " mag:" + magnitude);
// if(normal.y > normal.x + normal.z){
// normal.x = 0;
// normal.z = 0;
// }
receiver.addImpulse(new Impulse(normal, localPosition, worldPos, magnitude * 2, Collidable.TYPE_STATIC)); receiver.addImpulse(new Impulse(normal, localPosition, worldPos, magnitude * 2, Collidable.TYPE_STATIC));
break; break;
case Collidable.TYPE_CREATURE: case Collidable.TYPE_CREATURE:
@ -276,8 +285,15 @@ public class CollisionEngine {
spaceLock.unlock(); spaceLock.unlock();
} }
/**
* Gets the list of collidables
* @return The list of collidables
*/
public List<Collidable> getCollidables(){ public List<Collidable> getCollidables(){
return collidableList; spaceLock.lock();
List<Collidable> rVal = Collections.unmodifiableList(this.collidableList);
spaceLock.unlock();
return rVal;
} }
@ -633,16 +649,16 @@ public class CollisionEngine {
Matrix4d inverseTransform = new Matrix4d(); Matrix4d inverseTransform = new Matrix4d();
if(this.collisionWorldData != null){ if(this.collisionWorldData != null){
for(Collidable collidable : collidableList){ for(Collidable collidable : collidableList){
if(collidable.getParentTracksCollidable()){ if(collidable.getParentTracksCollidable() && collidable.getReady()){
Entity physicsEntity = collidable.getParent(); Entity physicsEntity = collidable.getParent();
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity); DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity); DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity);
Vector4d rawPos = null; Vector3d rawPos = null;
inverseTransform.identity(); inverseTransform.identity();
if(rigidBody != null){ if(rigidBody != null){
rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin),1)); rawPos = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin);
} else if(geom != null){ } else if(geom != null){
rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin),1)); rawPos = PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin);
} else { } else {
continue; continue;
} }
@ -664,9 +680,21 @@ public class CollisionEngine {
CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(physicsEntity); CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(physicsEntity);
if(template != null){ if(template != null){
suggestedPosition.sub(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()); suggestedPosition.sub(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ());
suggestedPosition = this.suggestMovementPosition(collisionWorldData, suggestedPosition);
newRotation.mul(new Quaterniond(template.getRotX(),template.getRotY(),template.getRotZ(),template.getRotW()).invert()); newRotation.mul(new Quaterniond(template.getRotX(),template.getRotY(),template.getRotZ(),template.getRotW()).invert());
} }
} }
// if(rigidBody != null && suggestedPosition.distance(0,0,0) < 100){
// String message = "\n" +
// "this.floatingOrigin: " + this.floatingOrigin + "\n" +
// "calculatedPosition: " + calculatedPosition + "\n" +
// "suggestedPosition: " + suggestedPosition + "\n" +
// "rawPos: " + rawPos + "\n" +
// (rigidBody != null ? "body: " + rigidBody.getPosition() + "\n" : "\n") +
// (geom != null ? "geom: " + geom.getPosition() + "\n" : "\n") +
// "";
// throw new Error(message);
// }
EntityUtils.getPosition(physicsEntity).set(suggestedPosition); EntityUtils.getPosition(physicsEntity).set(suggestedPosition);
EntityUtils.getRotation(physicsEntity).set(newRotation); EntityUtils.getRotation(physicsEntity).set(newRotation);
} }
@ -690,49 +718,46 @@ public class CollisionEngine {
Entity physicsEntity = collidable.getParent(); Entity physicsEntity = collidable.getParent();
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity); DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
if(rigidBody != null){ if(rigidBody != null){
Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin); Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition());
// if(this.bodies.size() > 1 && currentBodyOffset.distance(0,0,0) > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN && this.hasRebased){
// String message = "Body far outside expected range! " + currentBodyOffset + "\n";
// message = message + this.getDebugStatus();
// throw new Error(message);
// }
currentBodyOffset.add(this.floatingOrigin);
if(collected == 0){ if(collected == 0){
newOrigin.set(currentBodyOffset); newOrigin.set(currentBodyOffset);
} else { } else {
float percentExisting = collected / (float)(collected + 1); newOrigin.add(currentBodyOffset);
float percentNew = 1.0f - percentExisting;
newOrigin = newOrigin.mul(percentExisting).add(currentBodyOffset.mul(percentNew));
} }
collected++; collected++;
} }
// DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity); }
// if(geom != null){ if(collected > 0){
// if(geom instanceof DSpace space){ newOrigin = newOrigin.mul(1.0/(double)collected);
// for(DGeom child : space.getGeoms()){
// Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(child.getPosition()).add(this.floatingOrigin);
// 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++;
// }
// } else {
// Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin);
// 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++;
// }
// }
} }
newOrigin = newOrigin.round(); newOrigin = newOrigin.round();
Vector3d delta = new Vector3d(this.floatingOrigin); Vector3d delta = new Vector3d(this.floatingOrigin);
delta = delta.sub(newOrigin); delta = delta.sub(newOrigin);
//only perform rebase if sufficiently far away //only perform rebase if sufficiently far away
if(delta.length() > REBASE_TRIGGER_DISTANCE){ if(delta.length() > REBASE_TRIGGER_DISTANCE){
//error checking
if(collected > 1 && delta.length() > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN){
System.out.println("newOrigin: " + newOrigin);
System.out.println("delta: " + delta);
throw new Error(this.getDebugStatus());
}
System.out.println("REbase");
System.out.println(this.getStatus());
System.out.println("newOrigin: " + newOrigin);
System.out.println("delta: " + delta);
if(delta.y > 100 || delta.y < -100){
throw new Error(this.getDebugStatus());
}
this.floatingOrigin = newOrigin; this.floatingOrigin = newOrigin;
//apply new origin to all geoms //apply new origin to all geoms
//calculate new origin //calculate new origin
@ -757,6 +782,7 @@ public class CollisionEngine {
} }
} }
} }
this.hasRebased = true;
} }
spaceLock.unlock(); spaceLock.unlock();
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
@ -766,12 +792,37 @@ public class CollisionEngine {
* Registers a collision object with the server * Registers a collision object with the server
* @param body The body * @param body The body
* @param collidable The corresponding collidable * @param collidable The corresponding collidable
* @param position The position of the body
*/ */
public void registerCollisionObject(DBody body, Collidable collidable){ public void registerCollisionObject(DBody body, Collidable collidable, Vector3d position){
if(collidable == null){ if(collidable == null){
throw new Error("Collidable is null!"); throw new Error("Collidable is null!");
} }
spaceLock.lock(); spaceLock.lock();
// if(this.name.equals("serverPhysics") && position.distance(0,0,0) < 100){
// throw new Error("Invalid position " + position);
// }
// if(this.name.equals("serverPhysics") && this.hasRebased && this.bodies.size() > 1 && position.distance(this.floatingOrigin) > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN){
// String message = "Position invalid!\n" +
// "position: " + position.x + "," + position.y + "," + position.z + "\n" +
// "floating origin: " + this.floatingOrigin.x + "," + this.floatingOrigin.y + "," + this.floatingOrigin.z + "\n" +
// "dist: " + position.distance(this.floatingOrigin) + "\n" +
// "ent pos: " + EntityUtils.getPosition(collidable.getParent()) + "\n" +
// this.getDebugStatus() +
// "";
// throw new Error(message);
// }
// if(this.name.equals("serverPhysics")){
// System.out.println("Register collidable at " + position);
// }
//Body transform needs to be set before the body is added to the collidable list
//this makes sure that dynamic update transforms and floating origin work correctly
this.setBodyTransform(body, new Vector3d(position), new Quaterniond());
// if(this.name.equals("serverPhysics") && (body.getPosition().get0() != position.x || body.getPosition().get1() != position.y || body.getPosition().get2() != position.z)){
// System.out.println("Transform not set properly! " + body.getPosition() + " " + position);
// }
this.registerPhysicsObject(body); this.registerPhysicsObject(body);
bodyPointerMap.put(body,collidable); bodyPointerMap.put(body,collidable);
collidableList.add(collidable); collidableList.add(collidable);
@ -1294,8 +1345,17 @@ 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();
// if(this.name.equals("serverPhysics")){
// if(position.distance(0,0,0) < 100){
// throw new Error("Reposition server body " + position);
// }
// }
body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.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));
// if(this.name.equals("serverPhysics")){
// System.out.println("SetBodyTransform " + body.getPosition());
// }
spaceLock.unlock(); spaceLock.unlock();
} }
@ -1334,8 +1394,26 @@ public class CollisionEngine {
* @param angularForce The angular force * @param angularForce The angular force
*/ */
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(!this.hasRebased){
return;
}
if(body != null){ if(body != null){
spaceLock.lock(); spaceLock.lock();
// if(this.name.equals("clientPhysics") || this.name.equals("serverPhysics")){
// double posX = position.x - this.floatingOrigin.x;
// double posY = position.y - this.floatingOrigin.y;
// double posZ = position.z - this.floatingOrigin.z;
// if((posX > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posX < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN) && this.floatingOrigin.length() == 0 && this.hasRebased){
// System.out.println("Sync body pos: " + posX + "," + posY + "," + posZ);
// spaceLock.unlock();
// return;
// }
// if(this.bodies.size() > 2 && this.floatingOrigin.length() == 0 && this.hasRebased){
// throw new Error(this.getDebugStatus());
// }
// }
body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.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));
@ -1355,6 +1433,19 @@ 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();
// if(this.name.equals("clientPhysics") || this.name.equals("serverPhysics")){
// double posX = position.x - this.floatingOrigin.x;
// double posY = position.y - this.floatingOrigin.y;
// double posZ = position.z - this.floatingOrigin.z;
// if((posX > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ > MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posX < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN || posZ < -MAX_EXPECTED_DIST_FROM_LOCAL_ORIGIN) && this.floatingOrigin.length() == 0 && this.hasRebased){
// System.out.println("Set body pos: " + posX + "," + posY + "," + posZ);
// spaceLock.unlock();
// return;
// }
// if(this.bodies.size() > 2 && this.floatingOrigin.length() == 0 && this.hasRebased){
// throw new Error(this.getDebugStatus());
// }
// }
body.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.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();
@ -1537,6 +1628,7 @@ public class CollisionEngine {
*/ */
public String getStatus(){ public String getStatus(){
String message = "" + String message = "" +
"Name: " + this.name + "\n" +
"Bodies: " + this.bodies.size() + "\n" + "Bodies: " + this.bodies.size() + "\n" +
"Body Ptrs: " + this.bodyPointerMap.size() + "\n" + "Body Ptrs: " + this.bodyPointerMap.size() + "\n" +
"Geom Ptrs: " + this.geomPointerMap.size() + "\n" + "Geom Ptrs: " + this.geomPointerMap.size() + "\n" +
@ -1549,6 +1641,22 @@ public class CollisionEngine {
return message; return message;
} }
/**
* Gets the status of the collision engine
* @return The status of the collision engine
*/
public String getDebugStatus(){
String message = this.getStatus();
for(Collidable collidable : collidableList){
DBody rigidBody = PhysicsEntityUtils.getDBody(collidable.getParent());
if(rigidBody != null){
Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition());
message = message + existingPosition.x + "," + existingPosition.y + "," + existingPosition.z + "\n";
}
}
return message;
}
/** /**
* Gets the floating origin of the collision engine * Gets the floating origin of the collision engine
* @return The floating origin * @return The floating origin

View File

@ -234,7 +234,7 @@ public class PhysicsEntityUtils {
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal));
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE); Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
} break; } break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
@ -298,7 +298,7 @@ public class PhysicsEntityUtils {
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal));
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE); Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
} break; } break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
@ -364,7 +364,7 @@ public class PhysicsEntityUtils {
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(rVal));
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE); Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
} break; } break;
} }
@ -385,8 +385,9 @@ public class PhysicsEntityUtils {
* @param realm The realm the entity is inside of * @param realm The realm the entity is inside of
* @param rVal The entity * @param rVal The entity
* @param physicsTemplate The collidable template * @param physicsTemplate The collidable template
* @param position the position of the body
*/ */
public static void serverAttachCollidableTemplate(Realm realm, Entity rVal, CollidableTemplate physicsTemplate){ public static void serverAttachCollidableTemplate(Realm realm, Entity rVal, CollidableTemplate physicsTemplate, Vector3d position){
Collidable collidable; Collidable collidable;
double mass = 1.0f; double mass = 1.0f;
if(physicsTemplate.getMass() != null){ if(physicsTemplate.getMass() != null){
@ -398,102 +399,7 @@ public class PhysicsEntityUtils {
} }
CollisionEngine.lockOde(); CollisionEngine.lockOde();
if(physicsTemplate.getKinematic()){ if(physicsTemplate.getKinematic()){
DGeom geom = null; PhysicsEntityUtils.serverAttachGeom(realm,rVal,physicsTemplate);
switch(physicsTemplate.getType()){
case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
//
//create dbody
geom = CollisionBodyCreation.createCylinderShape(
realm.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
//
//create dbody
geom = CollisionBodyCreation.createCubeShape(
realm.getCollisionEngine(),
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
categoryBit
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
//
//create dbody
geom = CollisionBodyCreation.createCapsuleShape(
realm.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
} break;
}
} else { } else {
DBody rigidBody = null; DBody rigidBody = null;
switch(physicsTemplate.getType()){ switch(physicsTemplate.getType()){
@ -551,17 +457,17 @@ public class PhysicsEntityUtils {
realm.getCollisionEngine().setAngularlyStatic(rigidBody, true); realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
} }
if(physicsTemplate.getKinematic()){ if(physicsTemplate.getKinematic()){
Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody); realm.getCollisionEngine().setKinematic(rigidBody);
rigidBody.disable(); rigidBody.disable();
} }
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree); rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, position);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
} break; } break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: { case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
@ -615,17 +521,17 @@ public class PhysicsEntityUtils {
realm.getCollisionEngine().setAngularlyStatic(rigidBody, true); realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
} }
if(physicsTemplate.getKinematic()){ if(physicsTemplate.getKinematic()){
Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody); realm.getCollisionEngine().setKinematic(rigidBody);
rigidBody.disable(); rigidBody.disable();
} }
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree); rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, position);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
} break; } break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: { case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
@ -681,17 +587,17 @@ public class PhysicsEntityUtils {
realm.getCollisionEngine().setAngularlyStatic(rigidBody, true); realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
} }
if(physicsTemplate.getKinematic()){ if(physicsTemplate.getKinematic()){
Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody); realm.getCollisionEngine().setKinematic(rigidBody);
rigidBody.disable(); rigidBody.disable();
} }
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree); rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, position);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE); ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
} break; } break;
} }
@ -706,6 +612,124 @@ public class PhysicsEntityUtils {
CollisionEngine.unlockOde(); CollisionEngine.unlockOde();
} }
/**
* [SERVER ONLY] Attaches a collidable template to a given entity
* @param realm The realm the entity is inside of
* @param rVal The entity
* @param physicsTemplate The collidable template
* @return The geometry object
*/
public static DGeom serverAttachGeom(Realm realm, Entity rVal, CollidableTemplate physicsTemplate){
if(physicsTemplate == null){
throw new Error("Physics template is null!");
}
Collidable collidable;
double mass = 1.0f;
long categoryBit = Collidable.TYPE_CREATURE_BIT;
if(physicsTemplate.getKinematic()){
categoryBit = Collidable.TYPE_STATIC_BIT;
}
CollisionEngine.lockOde();
DGeom geom = null;
switch(physicsTemplate.getType()){
case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
//
//create dbody
geom = CollisionBodyCreation.createCylinderShape(
realm.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
//
//create dbody
geom = CollisionBodyCreation.createCubeShape(
realm.getCollisionEngine(),
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
categoryBit
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
//
//create dbody
geom = CollisionBodyCreation.createCapsuleShape(
realm.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
} break;
}
CollisionEngine.unlockOde();
return geom;
}
/** /**
* [CLIENT ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity * [CLIENT ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity
@ -718,7 +742,7 @@ public class PhysicsEntityUtils {
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT); DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
CollisionBodyCreation.setAutoDisable(Globals.clientState.clientSceneWrapper.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); CollisionBodyCreation.setAutoDisable(Globals.clientState.clientSceneWrapper.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false); Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable); Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable, EntityUtils.getPosition(terrain));
PhysicsEntityUtils.setDBody(terrain,terrainBody); PhysicsEntityUtils.setDBody(terrain,terrainBody);
CollisionEngine.unlockOde(); CollisionEngine.unlockOde();
terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
@ -750,7 +774,7 @@ public class PhysicsEntityUtils {
DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT); DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
CollisionBodyCreation.setAutoDisable(Globals.clientState.clientSceneWrapper.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); CollisionBodyCreation.setAutoDisable(Globals.clientState.clientSceneWrapper.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false); Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable); Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable, EntityUtils.getPosition(terrain));
PhysicsEntityUtils.setDBody(terrain,terrainBody); PhysicsEntityUtils.setDBody(terrain,terrainBody);
terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
} }
@ -781,7 +805,7 @@ public class PhysicsEntityUtils {
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT); DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT);
CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false)); realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false), EntityUtils.getPosition(terrain));
PhysicsEntityUtils.setDBody(terrain,terrainBody); PhysicsEntityUtils.setDBody(terrain,terrainBody);
return terrainBody; return terrainBody;
@ -816,7 +840,7 @@ public class PhysicsEntityUtils {
DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT); DBody terrainBody = CollisionBodyCreation.generateBodyFromMultiShapeMeshData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT);
CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD); CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), terrainBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false)); realm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_STATIC, false), EntityUtils.getPosition(terrain));
PhysicsEntityUtils.setDBody(terrain,terrainBody); PhysicsEntityUtils.setDBody(terrain,terrainBody);
return terrainBody; return terrainBody;
@ -889,6 +913,7 @@ public class PhysicsEntityUtils {
); );
} }
PhysicsEntityUtils.setCollidable(entity, null); PhysicsEntityUtils.setCollidable(entity, null);
PhysicsEntityUtils.clearGeomAndBody(entity);
Vector3d entityPos = EntityUtils.getPosition(entity); Vector3d entityPos = EntityUtils.getPosition(entity);
ServerEntityUtils.repositionEntity(entity, entityPos); ServerEntityUtils.repositionEntity(entity, entityPos);
} }
@ -962,6 +987,18 @@ public class PhysicsEntityUtils {
return (DGeom)entity.getData(EntityDataStrings.PHYSICS_GEOM); return (DGeom)entity.getData(EntityDataStrings.PHYSICS_GEOM);
} }
/**
* Clears the geom and body on an entity
* @param entity The entity
*/
public static void clearGeomAndBody(Entity entity){
if(PhysicsEntityUtils.getCollidable(entity) != null){
throw new Error("Trying to clear geom and body on an entity that still has a collidable!");
}
entity.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY);
entity.removeData(EntityDataStrings.PHYSICS_GEOM);
}
/** /**
* Sets the position of a DGeom * Sets the position of a DGeom
* @param collisionEngine the collision engine * @param collisionEngine the collision engine

View File

@ -37,6 +37,11 @@ public class Collidable {
* The params for the surface of this collidable when a collision occurs * The params for the surface of this collidable when a collision occurs
*/ */
private SurfaceParams surfaceParams; private SurfaceParams surfaceParams;
/**
* Tracks whether this collidable has been simulated or not
*/
private boolean ready = false;
//these should have corresponding category bits along with them //these should have corresponding category bits along with them
public static final String TYPE_STATIC = "static"; public static final String TYPE_STATIC = "static";
@ -122,6 +127,24 @@ public class Collidable {
public void clear(){ public void clear(){
impulses.clear(); impulses.clear();
} }
/**
* Gets whether the collidable is ready or not
* @return true if it is ready, false otherwise
*/
public boolean getReady() {
return ready;
}
/**
* Sets the ready status of collidable
* @param ready true if the collidable is ready, false otherwise
*/
public void setReady(boolean ready) {
this.ready = ready;
}

View File

@ -35,7 +35,7 @@ public class HitboxManager {
* @param resolutionCallback The callback that fires when a collision occurs * @param resolutionCallback The callback that fires when a collision occurs
*/ */
public HitboxManager(CollisionResolutionCallback resolutionCallback){ public HitboxManager(CollisionResolutionCallback resolutionCallback){
collisionEngine = new CollisionEngine(); collisionEngine = new CollisionEngine("hitbox");
collisionEngine.setCollisionResolutionCallback(resolutionCallback); collisionEngine.setCollisionResolutionCallback(resolutionCallback);
} }

View File

@ -160,7 +160,7 @@ public class LoadingUtils {
} }
//set player character template //set player character template
serverPlayerConnection.setCreatureTemplate(template); serverPlayerConnection.setCreatureTemplate(template);
Character chara = Globals.serverState.characterService.createCharacter(template, serverPlayerConnection.getPlayerId()); Character chara = Globals.serverState.characterService.createCharacter(template, serverPlayerConnection.getPlayerId(), new Vector3d());
Globals.clientState.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage(chara.getId() + "")); Globals.clientState.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage(chara.getId() + ""));
//set player world-space coordinates //set player world-space coordinates

View File

@ -37,7 +37,7 @@ public class ClientEntityUtils {
* @param entity * @param entity
* @param position * @param position
*/ */
public static void reositionEntity(Entity entity, Vector3d position, Quaterniond rotation){ public static void repositionEntity(Entity entity, Vector3d position, Quaterniond rotation){
//reposition entity //reposition entity
CollisionObjUtils.clientPositionCharacter(entity, position, rotation); CollisionObjUtils.clientPositionCharacter(entity, position, rotation);
EntityUtils.getPosition(entity).set(position); EntityUtils.getPosition(entity).set(position);

View File

@ -115,7 +115,9 @@ public class DrawableUtils {
}); });
String path = Globals.assetManager.queuedAsset(model); String path = Globals.assetManager.queuedAsset(model);
entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorOfLoadingModel(path)); entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorOfLoadingModel(path));
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
}
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity()); entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
@ -132,7 +134,9 @@ public class DrawableUtils {
*/ */
public static void makeEntityDrawable(Entity entity, String path){ public static void makeEntityDrawable(Entity entity, String path){
entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorFromModelPath(path)); entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorFromModelPath(path));
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
}
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity()); entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);

View File

@ -131,7 +131,9 @@ public class EntityCreationUtils {
*/ */
public static void makeEntityPoseable(Entity entity, String modelPath){ public static void makeEntityPoseable(Entity entity, String modelPath){
entity.putData(EntityDataStrings.POSE_ACTOR, PoseActorUtils.createPoseActorFromModelPath(modelPath)); entity.putData(EntityDataStrings.POSE_ACTOR, PoseActorUtils.createPoseActorFromModelPath(modelPath));
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
}
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity()); entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);
@ -147,7 +149,9 @@ public class EntityCreationUtils {
*/ */
public static void makeEntityDrawable(Entity entity, String modelPath){ public static void makeEntityDrawable(Entity entity, String modelPath){
entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorFromModelPath(modelPath)); entity.putData(EntityDataStrings.DATA_STRING_ACTOR, ActorUtils.createActorFromModelPath(modelPath));
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); if(!entity.containsKey(EntityDataStrings.DATA_STRING_POSITION)){
entity.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0));
}
entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity()); entity.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaterniond().identity());
entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); entity.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1));
entity.putData(EntityDataStrings.DATA_STRING_DRAW, true); entity.putData(EntityDataStrings.DATA_STRING_DRAW, true);

View File

@ -40,10 +40,20 @@ public class ServerEntityUtils {
if(position == null){ if(position == null){
throw new Error("Trying to set server entity position to null!"); throw new Error("Trying to set server entity position to null!");
} }
double startX = position.x;
double startY = position.y;
double startZ = position.z;
//reposition entity, if the position isn't correct then it will spawn at 0,0,0 when the synchronization part is called //reposition entity, if the position isn't correct then it will spawn at 0,0,0 when the synchronization part is called
CollisionObjUtils.serverPositionCharacter(entity, position); CollisionObjUtils.serverPositionCharacter(entity, position);
//get current server data cell //get current server data cell
ServerDataCell cell = realm.getDataCellManager().getDataCellAtPoint(position); ServerDataCell cell = realm.getDataCellManager().getDataCellAtPoint(position);
if(startX != position.x || startX != position.x || startX != position.x){
throw new Error("Position not preserved while initially positioning entity! " + startX + "," + startY + "," + startZ + " " + position.x + "," + position.y + "," + position.z);
}
Vector3d entPos = EntityUtils.getPosition(entity);
if(startX != entPos.x || startX != entPos.x || startX != entPos.x){
throw new Error("Position not preserved while initially positioning entity! " + startX + "," + startY + "," + startZ + " " + entPos.x + "," + entPos.y + "," + entPos.z);
}
if(cell != null){ if(cell != null){
//initialize server datacell tracking of this entity //initialize server datacell tracking of this entity
realm.initializeServerSideEntity(entity, cell); realm.initializeServerSideEntity(entity, cell);
@ -56,6 +66,9 @@ public class ServerEntityUtils {
//initialize server datacell tracking of this entity //initialize server datacell tracking of this entity
realm.initializeServerSideEntity(entity, cell); realm.initializeServerSideEntity(entity, cell);
} }
if(startX != position.x || startX != position.x || startX != position.x){
throw new Error("Position not preserved while initially positioning entity! " + startX + "," + startY + "," + startZ + " " + position.x + "," + position.y + "," + position.z);
}
} }
/** /**
@ -70,6 +83,10 @@ public class ServerEntityUtils {
if(AttachUtils.getParent(entity) != null){ if(AttachUtils.getParent(entity) != null){
throw new Error("Trying to reposition attached entity!"); throw new Error("Trying to reposition attached entity!");
} }
double startX = position.x;
double startY = position.y;
double startZ = position.z;
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
ServerWorldData worldDat = realm.getServerWorldData(); ServerWorldData worldDat = realm.getServerWorldData();
if( if(
@ -85,6 +102,11 @@ public class ServerEntityUtils {
ServerEntityUtils.repositionEntityRecursive(realm, entity, position); ServerEntityUtils.repositionEntityRecursive(realm, entity, position);
//reposition entity //reposition entity
CollisionObjUtils.serverPositionCharacter(entity, position); CollisionObjUtils.serverPositionCharacter(entity, position);
//error checking
if(position.x != startX || position.y != startY || position.z != startZ){
throw new Error("Position mutated while repositioning! " + position + " " + startX + "," + startY + "," + startZ);
}
} }
/** /**

View File

@ -57,7 +57,7 @@ public class Scene {
/** /**
* Lock for threadsafeing the scene * Lock for threadsafeing the scene
*/ */
ReentrantLock lock = new ReentrantLock(); private ReentrantLock lock = new ReentrantLock();
/** /**
* Constructor * Constructor

View File

@ -66,6 +66,8 @@ public class ClientCollidableTree implements BehaviorTree {
} }
PhysicsUtils.setRigidBodyTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), newPosition, rotation, body); PhysicsUtils.setRigidBodyTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), newPosition, rotation, body);
collidable.setReady(true);
//capsule-specific block collision logic //capsule-specific block collision logic
// if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){ // if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){
// //get capsule params // //get capsule params

View File

@ -59,6 +59,8 @@ public class ServerCollidableTree implements BehaviorTree {
this.resetGravityFall(); this.resetGravityFall();
} }
} }
collidable.setReady(true);
//capsule-specific block collision logic //capsule-specific block collision logic
// if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){ // if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){

View File

@ -86,7 +86,7 @@ public class ServerDoorState implements BehaviorTree {
this.setState(DoorState.CLOSED); this.setState(DoorState.CLOSED);
Realm parentRealm = Globals.serverState.realmManager.getEntityRealm(this.parent); Realm parentRealm = Globals.serverState.realmManager.getEntityRealm(this.parent);
Vector3d pos = EntityUtils.getPosition(this.parent); Vector3d pos = EntityUtils.getPosition(this.parent);
PhysicsEntityUtils.serverAttachCollidableTemplate(parentRealm, this.parent, PhysicsEntityUtils.getPhysicsTemplate(this.parent)); PhysicsEntityUtils.serverAttachCollidableTemplate(parentRealm, this.parent, PhysicsEntityUtils.getPhysicsTemplate(this.parent), pos);
ServerEntityUtils.repositionEntity(this.parent, pos); ServerEntityUtils.repositionEntity(this.parent, pos);
} }
), ),

View File

@ -284,7 +284,8 @@ public class HitboxCollectionState {
//register collidable with collision engine //register collidable with collision engine
this.collidable = new Collidable(this.parent, Collidable.TYPE_OBJECT, true); this.collidable = new Collidable(this.parent, Collidable.TYPE_OBJECT, true);
collisionEngine.registerCollisionObject(this.body, this.collidable); Vector3d entPos = EntityUtils.getPosition(this.parent);
collisionEngine.registerCollisionObject(this.body, this.collidable, entPos);
CollisionEngine.unlockOde(); CollisionEngine.unlockOde();
} }

View File

@ -350,7 +350,6 @@ public class ServerInventoryState implements BehaviorTree {
inventory.addItem(inventoryItem); inventory.addItem(inventoryItem);
//if we are the server, immediately send required packets //if we are the server, immediately send required packets
ServerDataCell dataCell = DataCellSearchUtils.getEntityDataCell(item); ServerDataCell dataCell = DataCellSearchUtils.getEntityDataCell(item);
// ServerDataCell dataCell = Globals.dataCellLocationResolver.getDataCellAtPoint(EntityUtils.getPosition(item),item);
//broadcast destroy entityq //broadcast destroy entityq
dataCell.broadcastNetworkMessage(EntityMessage.constructDestroyMessage(item.getId())); dataCell.broadcastNetworkMessage(EntityMessage.constructDestroyMessage(item.getId()));

View File

@ -57,7 +57,7 @@ public class ClientLODComponent implements BehaviorTree {
){ ){
CollidableTemplate physicsTemplate = commonData.getCollidable(); CollidableTemplate physicsTemplate = commonData.getCollidable();
PhysicsEntityUtils.clientAttachCollidableTemplate(this.parent, physicsTemplate); PhysicsEntityUtils.clientAttachCollidableTemplate(this.parent, physicsTemplate);
ClientEntityUtils.reositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent)); ClientEntityUtils.repositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent));
} }
} }
if(cachedLodLevel != lodLevel){ if(cachedLodLevel != lodLevel){
@ -66,7 +66,7 @@ public class ClientLODComponent implements BehaviorTree {
CommonEntityType type = CommonEntityUtils.getCommonData(this.parent); CommonEntityType type = CommonEntityUtils.getCommonData(this.parent);
if(type.getCollidable() != null && PhysicsEntityUtils.getCollidable(this.parent) == null){ if(type.getCollidable() != null && PhysicsEntityUtils.getCollidable(this.parent) == null){
PhysicsEntityUtils.clientAttachCollidableTemplate(parent, type.getCollidable()); PhysicsEntityUtils.clientAttachCollidableTemplate(parent, type.getCollidable());
ClientEntityUtils.reositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent)); ClientEntityUtils.repositionEntity(parent, EntityUtils.getPosition(parent), EntityUtils.getRotation(parent));
} }
} else if(cachedLodLevel == ServerLODComponent.LOW_RES){ } else if(cachedLodLevel == ServerLODComponent.LOW_RES){
if(PhysicsEntityUtils.containsDBody(this.parent)){ if(PhysicsEntityUtils.containsDBody(this.parent)){

View File

@ -17,6 +17,7 @@ import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils; import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.types.common.CommonEntityUtils; import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.net.synchronization.annotation.SyncedField; import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
@ -63,7 +64,8 @@ public class ServerLODComponent implements BehaviorTree {
Realm realm = Globals.serverState.realmManager.getEntityRealm(this.parent); Realm realm = Globals.serverState.realmManager.getEntityRealm(this.parent);
CommonEntityType type = CommonEntityUtils.getCommonData(this.parent); CommonEntityType type = CommonEntityUtils.getCommonData(this.parent);
if(type.getCollidable() != null){ if(type.getCollidable() != null){
PhysicsEntityUtils.serverAttachCollidableTemplate(realm, this.parent, type.getCollidable()); PhysicsEntityUtils.serverDestroyPhysics(this.parent);
PhysicsEntityUtils.serverAttachCollidableTemplate(realm, this.parent, type.getCollidable(),EntityUtils.getPosition(parent));
} }
} }
} else { } else {
@ -71,6 +73,14 @@ public class ServerLODComponent implements BehaviorTree {
//make low res //make low res
this.setLodLevel(LOW_RES); this.setLodLevel(LOW_RES);
PhysicsEntityUtils.serverDestroyPhysics(this.parent); PhysicsEntityUtils.serverDestroyPhysics(this.parent);
Realm realm = Globals.serverState.realmManager.getEntityRealm(parent);
CommonEntityType type = CommonEntityUtils.getCommonData(this.parent);
if(type.getCollidable() != null){
if(CreatureUtils.hasControllerPlayerId(parent)){
throw new Error("Should not be attaching a geometry to a player entity!");
}
PhysicsEntityUtils.serverAttachGeom(realm, parent, type.getCollidable());
}
} }
} }
} }

View File

@ -32,7 +32,7 @@ public class CollisionObjUtils {
Vector3d position = EntityUtils.getPosition(entity); Vector3d position = EntityUtils.getPosition(entity);
Quaterniond rotation = EntityUtils.getRotation(entity); Quaterniond rotation = EntityUtils.getRotation(entity);
Collidable collidable = new Collidable(entity, collidableType, true); Collidable collidable = new Collidable(entity, collidableType, true);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(collisionObject, collidable); Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(collisionObject, collidable, EntityUtils.getPosition(entity));
PhysicsEntityUtils.setDBody(entity, collisionObject); PhysicsEntityUtils.setDBody(entity, collisionObject);
@ -55,7 +55,7 @@ public class CollisionObjUtils {
Vector3d position = EntityUtils.getPosition(entity); Vector3d position = EntityUtils.getPosition(entity);
Collidable collidable = new Collidable(entity, collidableType, true); Collidable collidable = new Collidable(entity, collidableType, true);
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
realm.getCollisionEngine().registerCollisionObject(collisionObject, collidable); realm.getCollisionEngine().registerCollisionObject(collisionObject, collidable, EntityUtils.getPosition(entity));
PhysicsEntityUtils.setDBody(entity, collisionObject); PhysicsEntityUtils.setDBody(entity, collisionObject);
@ -73,7 +73,15 @@ public class CollisionObjUtils {
* @param position The server * @param position The server
*/ */
public static void serverPositionCharacter(Entity e, Vector3d position){ public static void serverPositionCharacter(Entity e, Vector3d position){
EntityUtils.getPosition(e).set(position); CollisionEngine.lockOde();
double startX = position.x;
double startY = position.y;
double startZ = position.z;
Vector3d entPos = EntityUtils.getPosition(e);
entPos.set(position);
if(startX != entPos.x || startX != entPos.x || startX != entPos.x){
throw new Error("Failed to position entity! " + startX + "," + startY + "," + startZ + " " + entPos.x + "," + entPos.y + "," + entPos.z);
}
Quaterniond rotation = EntityUtils.getRotation(e); Quaterniond rotation = EntityUtils.getRotation(e);
DBody body = PhysicsEntityUtils.getDBody(e); DBody body = PhysicsEntityUtils.getDBody(e);
DGeom geom = PhysicsEntityUtils.getDGeom(e); DGeom geom = PhysicsEntityUtils.getDGeom(e);
@ -86,7 +94,7 @@ public class CollisionObjUtils {
if(template == null){ if(template == null){
PhysicsUtils.setGeomTransform( PhysicsUtils.setGeomTransform(
collisionEngine, collisionEngine,
position, new Vector3d(position),
rotation, rotation,
geom geom
); );
@ -99,6 +107,14 @@ public class CollisionObjUtils {
); );
} }
} }
Vector3d finalRef = EntityUtils.getPosition(e);
if(finalRef != entPos){
throw new Error("Reference changed while positioning character! " + entPos + " " + finalRef);
}
if(startX != entPos.x || startX != entPos.x || startX != entPos.x){
throw new Error("Position not preserved while positioning entity! " + startX + "," + startY + "," + startZ + " " + entPos.x + "," + entPos.y + "," + entPos.z + " " + position);
}
CollisionEngine.unlockOde();
} }
/** /**

View File

@ -432,6 +432,10 @@ public class CommonEntityUtils {
*/ */
public static Entity serverApplyCommonEntityTransforms(Realm realm, Vector3d position, Entity entity, CommonEntityType rawType){ public static Entity serverApplyCommonEntityTransforms(Realm realm, Vector3d position, Entity entity, CommonEntityType rawType){
double startX = position.x;
double startY = position.y;
double startZ = position.z;
// //
//Set typing stuff //Set typing stuff
// //
@ -498,6 +502,9 @@ public class CommonEntityUtils {
// Hitbox stuff // Hitbox stuff
// //
// //
if(position.x != startX || position.y != startY || position.z != startZ){
throw new Error("Position mutated while spawning entity!");
}
if(rawType.getHitboxes() != null){ if(rawType.getHitboxes() != null){
HitboxCollectionState.attachHitboxState(realm.getHitboxManager(), true, entity, rawType.getHitboxes()); HitboxCollectionState.attachHitboxState(realm.getHitboxManager(), true, entity, rawType.getHitboxes());
} }
@ -507,9 +514,12 @@ public class CommonEntityUtils {
// //
// //
if(rawType.getCollidable() != null){ if(rawType.getCollidable() != null){
//actually attach collidable
CollidableTemplate physicsTemplate = rawType.getCollidable(); CollidableTemplate physicsTemplate = rawType.getCollidable();
if(Globals.serverState.lodEmitterService.isFullLod(position)){ if(Globals.serverState.lodEmitterService.isFullLod(position)){
PhysicsEntityUtils.serverAttachCollidableTemplate(realm, entity, physicsTemplate); PhysicsEntityUtils.serverAttachCollidableTemplate(realm, entity, physicsTemplate,position);
} else {
PhysicsEntityUtils.serverAttachGeom(realm, entity, physicsTemplate);
} }
ServerLODComponent.attachTree(entity); ServerLODComponent.attachTree(entity);
} }

View File

@ -209,6 +209,11 @@ public class CreatureUtils {
* @return The creature entity * @return The creature entity
*/ */
public static Entity serverSpawnBasicCreature(Realm realm, Vector3d position, String type, ObjectTemplate template){ public static Entity serverSpawnBasicCreature(Realm realm, Vector3d position, String type, ObjectTemplate template){
double posX = position.x;
double posY = position.y;
double posZ = position.z;
CreatureData rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getType(type); CreatureData rawType = Globals.gameConfigCurrent.getCreatureTypeLoader().getType(type);
Entity rVal = EntityCreationUtils.createServerEntity(realm, position); Entity rVal = EntityCreationUtils.createServerEntity(realm, position);
@ -287,6 +292,11 @@ public class CreatureUtils {
storedTemplate.objectType = rawType.getId(); storedTemplate.objectType = rawType.getId();
//store template on creature //store template on creature
CreatureUtils.setCreatureTemplate(rVal, storedTemplate); CreatureUtils.setCreatureTemplate(rVal, storedTemplate);
//error check position modification
if(posX != position.x || posY != position.y || posZ != position.z){
throw new Error("Creature has mutated position! " + posX + "," + posY + "," + posZ + " " + position.x + "," + position.y + "," + position.z);
}
//position entity //position entity
@ -300,6 +310,10 @@ public class CreatureUtils {
if(Globals.serverState.realmManager.getEntityRealm(rVal) == null){ if(Globals.serverState.realmManager.getEntityRealm(rVal) == null){
LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Created creature without it being assigned to a realm!")); LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Created creature without it being assigned to a realm!"));
} }
//make sure position hasn't changed
if(posX != position.x || posY != position.y || posZ != position.z){
throw new Error("Creature has mutated position! " + posX + "," + posY + "," + posZ + " " + position.x + "," + position.y + "," + position.z);
}
return rVal; return rVal;
} }

View File

@ -79,7 +79,7 @@ public class BlockChunkEntity {
EntityCreationUtils.makeEntityDrawablePreexistingModel(solidsEnt, modelPath); EntityCreationUtils.makeEntityDrawablePreexistingModel(solidsEnt, modelPath);
if(levelOfDetail == BlockChunkData.LOD_FULL_RES){ if(levelOfDetail == BlockChunkData.LOD_FULL_RES){
PhysicsEntityUtils.clientAttachTriGeomCollider(solidsEnt, data); PhysicsEntityUtils.clientAttachTriGeomCollider(solidsEnt, data);
ClientEntityUtils.reositionEntity(solidsEnt, new Vector3d(EntityUtils.getPosition(solidsEnt)), new Quaterniond()); ClientEntityUtils.repositionEntity(solidsEnt, new Vector3d(EntityUtils.getPosition(solidsEnt)), new Quaterniond());
} else { } else {
EntityCreationUtils.bypassShadowPass(solidsEnt); EntityCreationUtils.bypassShadowPass(solidsEnt);
EntityCreationUtils.bypassVolumetics(solidsEnt); EntityCreationUtils.bypassVolumetics(solidsEnt);

View File

@ -144,7 +144,7 @@ public class ProceduralTree {
trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS); trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable); Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(trunkChild));
//generate branches //generate branches
@ -549,7 +549,7 @@ public class ProceduralTree {
trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); trunkChild.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS); trunkChild.putData(EntityDataStrings.PHYSICS_MASS, TREE_MASS);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable); realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable, EntityUtils.getPosition(trunkChild));
return trunkChild; return trunkChild;
} }

View File

@ -38,37 +38,37 @@ public class Player {
/** /**
* The corresponding connection handler * The corresponding connection handler
*/ */
ServerConnectionHandler connectionHandler; private ServerConnectionHandler connectionHandler;
/** /**
* The id of the player * The id of the player
*/ */
int id; private int id;
/** /**
* The database's id of the player * The database's id of the player
*/ */
int dbId; private int dbId;
/** /**
* The world position of this player * The world position of this player
*/ */
Vector3i worldPos; private Vector3i worldPos;
/** /**
* The simulation radius of this player * The simulation radius of this player
*/ */
int simulationRadius = DEFAULT_SIMULATION_RADIUS; private int simulationRadius = DEFAULT_SIMULATION_RADIUS;
/** /**
* The player's primary entity * The player's primary entity
*/ */
Entity playerEntity; private Entity playerEntity;
/** /**
* Tracks whether the player's entity has been sent or not * Tracks whether the player's entity has been sent or not
*/ */
boolean hasSentPlayerEntity = false; private boolean hasSentPlayerEntity = false;
/** /**
* Constructor * Constructor

View File

@ -69,8 +69,7 @@ public class CharacterProtocol implements ServerProtocolTemplate<CharacterMessag
case REQUESTCREATECHARACTER: { case REQUESTCREATECHARACTER: {
ObjectTemplate template = Utilities.deserialize(message.getdata(), ObjectTemplate.class); ObjectTemplate template = Utilities.deserialize(message.getdata(), ObjectTemplate.class);
if(template != null){ if(template != null){
Character charaData = Globals.serverState.characterService.createCharacter(template, connectionHandler.getPlayer().getDBID()); Character charaData = Globals.serverState.characterService.createCharacter(template, connectionHandler.getPlayer().getDBID(),Globals.serverState.realmManager.first().getSpawnPoint());
charaData.setPos(Globals.serverState.realmManager.first().getSpawnPoint());
connectionHandler.setCreatureTemplate(Utilities.deserialize(message.getdata(), ObjectTemplate.class)); connectionHandler.setCreatureTemplate(Utilities.deserialize(message.getdata(), ObjectTemplate.class));
connectionHandler.setCharacterId(charaData.getId()); connectionHandler.setCharacterId(charaData.getId());
connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterSuccessMessage()); connectionHandler.addMessagetoOutgoingQueue(CharacterMessage.constructResponseCreateCharacterSuccessMessage());

View File

@ -145,7 +145,7 @@ public class MacroPathfindingNode implements AITreeNode {
if(targetRaw instanceof Vector3d){ if(targetRaw instanceof Vector3d){
targetPos = (Vector3d)targetRaw; targetPos = (Vector3d)targetRaw;
} else if(targetRaw instanceof Entity){ } else if(targetRaw instanceof Entity){
targetPos = EntityUtils.getPosition((Entity)targetRaw); targetPos = new Vector3d(EntityUtils.getPosition((Entity)targetRaw));
} else if(targetRaw instanceof VirtualStructure){ } else if(targetRaw instanceof VirtualStructure){
targetPos = ((VirtualStructure)targetRaw).getPos(); targetPos = ((VirtualStructure)targetRaw).getPos();
} else { } else {
@ -173,7 +173,7 @@ public class MacroPathfindingNode implements AITreeNode {
if(macroData == null){ if(macroData == null){
throw new Error("Macro data undefined!"); throw new Error("Macro data undefined!");
} }
Vector3d entityPos = EntityUtils.getPosition(entity); Vector3d entityPos = new Vector3d(EntityUtils.getPosition(entity));
return macroData.getPathCache().getPathingNode(entityPos); return macroData.getPathCache().getPathingNode(entityPos);
} }

View File

@ -59,11 +59,11 @@ public class RealmManager {
*/ */
public Realm createRealm(){ public Realm createRealm(){
//create chemistry engine //create chemistry engine
CollisionEngine chemistryEngine = new CollisionEngine(); CollisionEngine chemistryEngine = new CollisionEngine("serverChem");
chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback()); chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback());
return new Realm( return new Realm(
new ServerWorldData(), new ServerWorldData(),
new CollisionEngine(), new CollisionEngine("serverPhysics"),
chemistryEngine, chemistryEngine,
new HitboxManager(new ServerHitboxResolutionCallback()), new HitboxManager(new ServerHitboxResolutionCallback()),
ServerContentManager.createServerContentManager(false, null), ServerContentManager.createServerContentManager(false, null),
@ -77,10 +77,10 @@ public class RealmManager {
*/ */
public Realm createGriddedRealm(ServerWorldData serverWorldData, ServerContentManager serverContentManager){ public Realm createGriddedRealm(ServerWorldData serverWorldData, ServerContentManager serverContentManager){
//create collision engine //create collision engine
CollisionEngine collisionEngine = new CollisionEngine(); CollisionEngine collisionEngine = new CollisionEngine("serverPhysics");
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
//create chemistry engine //create chemistry engine
CollisionEngine chemistryEngine = new CollisionEngine(); CollisionEngine chemistryEngine = new CollisionEngine("serverChem");
chemistryEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); chemistryEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback()); chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback());
//create realm //create realm
@ -111,11 +111,11 @@ public class RealmManager {
ServerWorldData serverWorldData = ServerWorldData.createFixedWorldData(minPoint, maxPoint); ServerWorldData serverWorldData = ServerWorldData.createFixedWorldData(minPoint, maxPoint);
//create collision engine //create collision engine
CollisionEngine collisionEngine = new CollisionEngine(); CollisionEngine collisionEngine = new CollisionEngine("serverPhysics");
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
//create chemistry engine //create chemistry engine
CollisionEngine chemistryEngine = new CollisionEngine(); CollisionEngine chemistryEngine = new CollisionEngine("serverChem");
chemistryEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData)); chemistryEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback()); chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback());

View File

@ -434,7 +434,8 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
} }
if(cell.containsPlayer(player) && !this.shouldContainPlayer(distance, playerSimulationRadius)){ if(cell.containsPlayer(player) && !this.shouldContainPlayer(distance, playerSimulationRadius)){
if(cell.getScene().containsEntity(player.getPlayerEntity())){ if(cell.getScene().containsEntity(player.getPlayerEntity())){
throw new Error("Trying to remove player from a cell that contains its entity!"); // throw new Error("Trying to remove player from a cell that contains its entity!");
continue;
} }
cell.removePlayer(player); cell.removePlayer(player);
this.broadcastDestructionToPlayer(player, cell); this.broadcastDestructionToPlayer(player, cell);
@ -566,8 +567,12 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
//don't trigger the chunk to be re-created //don't trigger the chunk to be re-created
Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Store data"); Globals.profiler.beginCpuSample("GriddedDataCellManager.unloadPlayerlessChunks - Store data");
this.loaderService.queueLocationBasedOperation(key, () -> { this.loaderService.queueLocationBasedOperation(key, () -> {
serverContentManager.saveSerializationToDisk(key, serializedEntities); try {
serverTerrainManager.savePositionToDisk(worldPos); serverContentManager.saveSerializationToDisk(key, serializedEntities);
serverTerrainManager.savePositionToDisk(worldPos);
} catch(Throwable e){
e.printStackTrace();
}
}); });
Globals.profiler.endCpuSample(); Globals.profiler.endCpuSample();
@ -895,9 +900,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
this.loaderService.queueLocationBasedOperation(key, () -> { this.loaderService.queueLocationBasedOperation(key, () -> {
try { try {
serverContentManager.generateContentForDataCell(parent, localWorldPos, rVal, cellKey); serverContentManager.generateContentForDataCell(parent, localWorldPos, rVal, cellKey);
} catch(Error e){ } catch(Throwable e){
e.printStackTrace();
} catch(Exception e){
e.printStackTrace(); e.printStackTrace();
} }
}); });

View File

@ -5,6 +5,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.joml.Vector3d;
import org.joml.Vector3i; import org.joml.Vector3i;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;

View File

@ -99,8 +99,7 @@ public class CharacterUtils {
public static Character spawnCharacter(Realm realm, Vector3d position, String race){ public static Character spawnCharacter(Realm realm, Vector3d position, String race){
Race raceData = Globals.gameConfigCurrent.getRaceMap().getRace(race); Race raceData = Globals.gameConfigCurrent.getRaceMap().getRace(race);
String creatureType = raceData.getAssociatedCreature(); String creatureType = raceData.getAssociatedCreature();
Character rVal = Globals.serverState.characterService.createCharacter(ObjectTemplate.createDefault(EntityType.CREATURE, creatureType), CharacterService.NO_PLAYER); Character rVal = Globals.serverState.characterService.createCharacter(ObjectTemplate.createDefault(EntityType.CREATURE, creatureType), CharacterService.NO_PLAYER, position);
rVal.setPos(position);
Race.setRace(rVal, Race.create(race, creatureType)); Race.setRace(rVal, Race.create(race, creatureType));
realm.getDataCellManager().evaluateMacroObject(rVal); realm.getDataCellManager().evaluateMacroObject(rVal);
return rVal; return rVal;

View File

@ -30,12 +30,12 @@ public class TownPopulator {
List<VirtualStructure> structs = town.getStructures(macroData); List<VirtualStructure> structs = town.getStructures(macroData);
Random rand = new Random(town.getId()); Random rand = new Random(town.getId());
for(VirtualStructure struct : structs){ for(VirtualStructure struct : structs){
Vector3d placePos = new Vector3d(struct.getPos()).add(1,1,1);
ObjectTemplate template = ObjectTemplate.create(EntityType.CREATURE, "human"); ObjectTemplate template = ObjectTemplate.create(EntityType.CREATURE, "human");
Character chara = Globals.serverState.characterService.createCharacter(template, CharacterService.NO_PLAYER); Character chara = Globals.serverState.characterService.createCharacter(template, CharacterService.NO_PLAYER, placePos);
Race.setRace(chara, Globals.gameConfigCurrent.getRaceMap().getRace("human")); Race.setRace(chara, Globals.gameConfigCurrent.getRaceMap().getRace("human"));
CharacterUtils.addShelter(chara, struct); CharacterUtils.addShelter(chara, struct);
town.addResident(chara); town.addResident(chara);
chara.setPos(new Vector3d(struct.getPos()).add(1,1,1));
} }
//assign jobs to created characters //assign jobs to created characters

View File

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.joml.Vector3d;
import org.joml.Vector3i; import org.joml.Vector3i;
import com.google.gson.Gson; import com.google.gson.Gson;
@ -61,13 +62,15 @@ public class CharacterService extends SignalServiceImpl {
* Creates a character in the database * Creates a character in the database
* @param template The creature template for the character * @param template The creature template for the character
* @param playerId The player's id * @param playerId The player's id
* @param pos The position to place the character at
*/ */
public Character createCharacter(ObjectTemplate template, int playerId){ public Character createCharacter(ObjectTemplate template, int playerId, Vector3d pos){
if(template == null){ if(template == null){
throw new Error("Template is null!"); throw new Error("Template is null!");
} }
lock.lock(); lock.lock();
Character toStore = new Character(template); Character toStore = new Character(template);
toStore.setPos(pos);
toStore.setPlayerId(playerId); toStore.setPlayerId(playerId);
DatabaseResult result = Globals.serverState.dbController.executePreparedQuery( DatabaseResult result = Globals.serverState.dbController.executePreparedQuery(
"INSERT INTO charaData (playerId,dataVal) VALUES (?,?) RETURNING id;", "INSERT INTO charaData (playerId,dataVal) VALUES (?,?) RETURNING id;",

View File

@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.joml.Vector3d;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -165,7 +166,7 @@ public class TestEngineUtils {
ObjectTemplate creatureTemplate = ObjectTemplate.createDefault(EntityType.CREATURE, "human"); ObjectTemplate creatureTemplate = ObjectTemplate.createDefault(EntityType.CREATURE, "human");
ServerConnectionHandler serverConnection = Globals.serverState.server.getFirstConnection(); ServerConnectionHandler serverConnection = Globals.serverState.server.getFirstConnection();
serverConnection.setCreatureTemplate(creatureTemplate); serverConnection.setCreatureTemplate(creatureTemplate);
Character chara = Globals.serverState.characterService.createCharacter(creatureTemplate, serverConnection.getPlayerId()); Character chara = Globals.serverState.characterService.createCharacter(creatureTemplate, serverConnection.getPlayerId(), new Vector3d());
serverConnection.setCharacterId(chara.getId()); serverConnection.setCharacterId(chara.getId());
PlayerCharacterCreation.spawnPlayerCharacter(serverConnection); PlayerCharacterCreation.spawnPlayerCharacter(serverConnection);
} }