block colliders
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-22 14:10:38 -04:00
parent cbd5c98e0a
commit 4e4367f915
12 changed files with 547 additions and 207 deletions

View File

@ -1930,6 +1930,9 @@ Fix town placement structure-road intersection test
Kinematic collision templates now use geoms instead of setting kinematic (on client) Kinematic collision templates now use geoms instead of setting kinematic (on client)
Geom-only collidables on server Geom-only collidables on server
(05/22/2025)
Block colliders leveraging spaces
Scene view debug window

View File

@ -13,6 +13,7 @@ import electrosphere.client.ui.menu.debug.perf.ImGuiMemory;
import electrosphere.client.ui.menu.debug.perf.ImGuiNetworkMonitor; import electrosphere.client.ui.menu.debug.perf.ImGuiNetworkMonitor;
import electrosphere.client.ui.menu.debug.render.ImGuiRenderer; import electrosphere.client.ui.menu.debug.render.ImGuiRenderer;
import electrosphere.client.ui.menu.debug.render.ImGuiUIFramework; import electrosphere.client.ui.menu.debug.render.ImGuiUIFramework;
import electrosphere.client.ui.menu.debug.scene.ImGuiSceneWindow;
import electrosphere.client.ui.menu.debug.server.ImGuiAI; import electrosphere.client.ui.menu.debug.server.ImGuiAI;
import electrosphere.client.ui.menu.debug.server.ImGuiFluidMonitor; import electrosphere.client.ui.menu.debug.server.ImGuiFluidMonitor;
import electrosphere.client.ui.menu.debug.server.ImGuiGriddedManager; import electrosphere.client.ui.menu.debug.server.ImGuiGriddedManager;
@ -67,6 +68,7 @@ public class ImGuiWindowMacros {
ImGuiMemory.createMemoryDebugWindow(); ImGuiMemory.createMemoryDebugWindow();
ImGuiEditorWindows.initEditorWindows(); ImGuiEditorWindows.initEditorWindows();
ImGuiClientServices.createClientServicesWindow(); ImGuiClientServices.createClientServicesWindow();
ImGuiSceneWindow.createChunkMonitorWindow();
} }
/** /**
@ -149,6 +151,9 @@ public class ImGuiWindowMacros {
if(ImGui.button("Client Entity Debug")){ if(ImGui.button("Client Entity Debug")){
ImGuiEntityMacros.clientEntityListWindow.setOpen(true); ImGuiEntityMacros.clientEntityListWindow.setOpen(true);
} }
if(ImGui.button("Client Scene")){
ImGuiSceneWindow.viewScene(Globals.clientState.clientScene, Globals.clientState.clientSceneWrapper.getCollisionEngine());
}
//controls state debug //controls state debug
if(ImGui.button("Control State Debug")){ if(ImGui.button("Control State Debug")){
ImGuiControls.controlsWindow.setOpen(true); ImGuiControls.controlsWindow.setOpen(true);
@ -187,6 +192,9 @@ public class ImGuiWindowMacros {
if(ImGui.button("Gridded Data Cell Monitor")){ if(ImGui.button("Gridded Data Cell Monitor")){
ImGuiGriddedManager.griddedManagerWindow.setOpen(true); ImGuiGriddedManager.griddedManagerWindow.setOpen(true);
} }
if(ImGui.button("Server Scene")){
ImGuiSceneWindow.viewScene(null, Globals.serverState.realmManager.first().getCollisionEngine());
}
//memory usage //memory usage
if(ImGui.button("Memory Usage")){ if(ImGui.button("Memory Usage")){
ImGuiMemory.memoryWindow.setOpen(!ImGuiMemory.memoryWindow.isOpen()); ImGuiMemory.memoryWindow.setOpen(!ImGuiMemory.memoryWindow.isOpen());

View File

@ -0,0 +1,59 @@
package electrosphere.client.ui.menu.debug.scene;
import electrosphere.collision.CollisionEngine;
import electrosphere.engine.Globals;
import electrosphere.entity.scene.Scene;
import electrosphere.renderer.ui.imgui.ImGuiWindow;
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
import imgui.ImGui;
/**
* Views a scene
*/
public class ImGuiSceneWindow {
/**
* The target scene
*/
public static Scene targetScene;
/**
* The associated collision engine
*/
public static CollisionEngine targetCollisionEngine;
/**
* Window for scene data
*/
public static ImGuiWindow sceneWindow;
/**
* Scene view
*/
public static void createChunkMonitorWindow(){
sceneWindow = new ImGuiWindow("Scene Data");
sceneWindow.setCallback(new ImGuiWindowCallback() {
@Override
public void exec() {
if(targetCollisionEngine != null && ImGui.collapsingHeader("Collision Engine")){
ImGui.text(targetCollisionEngine.getStatus());
}
}
});
sceneWindow.setOpen(false);
Globals.renderingEngine.getImGuiPipeline().addImGuiWindow(sceneWindow);
}
/**
* Views a scene
* @param scene The scene
* @param engine The collision engine associated with the scene (optional)
*/
public static void viewScene(Scene scene, CollisionEngine engine){
ImGuiSceneWindow.targetScene = scene;
ImGuiSceneWindow.targetCollisionEngine = engine;
sceneWindow.setOpen(true);
}
}

View File

@ -16,6 +16,7 @@ import org.ode4j.ode.DCapsule;
import org.ode4j.ode.DCylinder; import org.ode4j.ode.DCylinder;
import org.ode4j.ode.DGeom; import org.ode4j.ode.DGeom;
import org.ode4j.ode.DMass; import org.ode4j.ode.DMass;
import org.ode4j.ode.DSpace;
import org.ode4j.ode.DSphere; import org.ode4j.ode.DSphere;
import org.ode4j.ode.DTriMesh; import org.ode4j.ode.DTriMesh;
@ -296,6 +297,22 @@ public class CollisionBodyCreation {
return body; return body;
} }
/**
* Creates an ode collider from a terrain chunk data object
* @param data The terrain data
* @return The geom
*/
public static DGeom generateGeomFromTerrainData(CollisionEngine collisionEngine, TriGeomData data, long categoryBits){
DGeom geom = null;
//create trimesh
if(data.getFaceElements().length > 0){
geom = collisionEngine.createTrimeshGeom(data.getVertices(),data.getFaceElements(),categoryBits);
}
return geom;
}
/** /**
* Creates an ode DBody from a mesh data set containing multiple shapes * Creates an ode DBody from a mesh data set containing multiple shapes
* @param data The mesh data data * @param data The mesh data data
@ -325,6 +342,24 @@ public class CollisionBodyCreation {
return body; return body;
} }
/**
* Creates an ode DBody from a mesh data set containing multiple shapes
* @param data The mesh data data
* @return The DBody
*/
public static DGeom generateColliderFromMultiShapeMeshData(CollisionEngine collisionEngine, MultiShapeTriGeomData data, long categoryBits){
DSpace multishape = collisionEngine.createSpace();
//create trimeshes
for(TriGeomData shapeData : data.getData()){
if(shapeData.getFaceElements().length > 0){
collisionEngine.createTrimeshGeom(shapeData.getVertices(),shapeData.getFaceElements(),categoryBits,multishape);
}
}
return multishape;
}
/** /**
* Generates a body from an AIScene * Generates a body from an AIScene
* @param scene The AIScene to generate a rigid body off of * @param scene The AIScene to generate a rigid body off of

View File

@ -404,10 +404,13 @@ public class CollisionEngine {
//make sure we have collidables for both //make sure we have collidables for both
if(c1 == null || c2 == null){ if(c1 == null || c2 == null){
String message = "Collidable is undefined!\n" + String message = "Collidable is undefined!\n" +
"Geoms:\n" +
o1 + " \n" + o1 + " \n" +
o2 + " \n" + o2 + " \n" +
"Bodies:\n" +
b1 + " \n" + b1 + " \n" +
b2 + " \n" + b2 + " \n" +
"Colliders:\n" +
c1 + " \n" + c1 + " \n" +
c2 + " \n" + c2 + " \n" +
"Obj 1 pointers:\n" + "Obj 1 pointers:\n" +
@ -621,18 +624,21 @@ public class CollisionEngine {
public void updateDynamicObjectTransforms(){ public void updateDynamicObjectTransforms(){
Globals.profiler.beginCpuSample("updateDynamicObjectTransforms"); Globals.profiler.beginCpuSample("updateDynamicObjectTransforms");
spaceLock.lock(); spaceLock.lock();
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()){
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);
Matrix4d inverseTransform = new Matrix4d();
Vector4d rawPos = null; Vector4d rawPos = null;
inverseTransform.identity();
if(rigidBody != null){ if(rigidBody != null){
rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin),1)); rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin),1));
} else if(geom != null){ } else if(geom != null){
rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin),1)); rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(geom.getPosition()).add(this.floatingOrigin),1));
} else {
continue;
} }
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);
@ -650,8 +656,10 @@ public class CollisionEngine {
} }
if(geom != null){ if(geom != null){
CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(physicsEntity); CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(physicsEntity);
suggestedPosition.sub(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()); if(template != null){
newRotation.mul(new Quaterniond(template.getRotX(),template.getRotY(),template.getRotZ(),template.getRotW()).invert()); suggestedPosition.sub(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ());
newRotation.mul(new Quaterniond(template.getRotX(),template.getRotY(),template.getRotZ(),template.getRotW()).invert());
}
} }
EntityUtils.getPosition(physicsEntity).set(suggestedPosition); EntityUtils.getPosition(physicsEntity).set(suggestedPosition);
EntityUtils.getRotation(physicsEntity).set(newRotation); EntityUtils.getRotation(physicsEntity).set(newRotation);
@ -668,7 +676,7 @@ public class CollisionEngine {
public void rebaseWorldOrigin(){ public void rebaseWorldOrigin(){
Globals.profiler.beginCpuSample("rebaseWorldOrigin"); Globals.profiler.beginCpuSample("rebaseWorldOrigin");
spaceLock.lock(); spaceLock.lock();
if(this.collisionWorldData != null && this.floatingOrigin.x == 0 && this.floatingOrigin.z == 0){ if(this.collisionWorldData != null){
int collected = 0; int collected = 0;
Vector3d newOrigin = new Vector3d(); Vector3d newOrigin = new Vector3d();
//calculate new origin //calculate new origin
@ -686,6 +694,32 @@ public class CollisionEngine {
} }
collected++; collected++;
} }
DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity);
if(geom != null){
if(geom instanceof DSpace space){
for(DGeom child : space.getGeoms()){
Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(child.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++;
}
} else {
Vector3d currentBodyOffset = PhysicsUtils.odeVecToJomlVec(geom.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); Vector3d delta = new Vector3d(this.floatingOrigin).sub(newOrigin);
this.floatingOrigin = this.floatingOrigin.set(newOrigin); this.floatingOrigin = this.floatingOrigin.set(newOrigin);
@ -700,8 +734,15 @@ public class CollisionEngine {
} }
DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity); DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity);
if(geom != null){ if(geom != null){
Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(geom.getPosition()); if(geom instanceof DSpace space){
geom.setPosition(PhysicsUtils.jomlVecToOdeVec(existingPosition.add(delta))); for(DGeom child : space.getGeoms()){
Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(child.getPosition());
child.setPosition(PhysicsUtils.jomlVecToOdeVec(existingPosition.add(delta)));
}
} else {
Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(geom.getPosition());
geom.setPosition(PhysicsUtils.jomlVecToOdeVec(existingPosition.add(delta)));
}
} }
} }
} }
@ -740,6 +781,23 @@ public class CollisionEngine {
spaceLock.unlock(); spaceLock.unlock();
} }
/**
* Registers a collision object with the server
* @param geoms The list of geoms
* @param collidable The corresponding collidable
*/
public void registerCollisionObject(List<DGeom> geoms, Collidable collidable){
if(collidable == null){
throw new Error("Collidable is null!");
}
spaceLock.lock();
for(DGeom geom : geoms){
geomPointerMap.put(geom,collidable);
}
collidableList.add(collidable);
spaceLock.unlock();
}
/** /**
* Deregisters a collidable from the physics engine * Deregisters a collidable from the physics engine
* @param collidable The collidable * @param collidable The collidable
@ -751,6 +809,17 @@ public class CollisionEngine {
collidableList.remove(collidable); collidableList.remove(collidable);
spaceLock.unlock(); spaceLock.unlock();
} }
/**
* Deregisters a collidable from the physics engine
* @param collidable The collidable
*/
public void deregisterCollisionObject(DGeom geom, Collidable collidable){
spaceLock.lock();
geomPointerMap.remove(geom);
collidableList.remove(collidable);
spaceLock.unlock();
}
public void listBodyPositions(){ public void listBodyPositions(){
for(DBody body : bodies){ for(DBody body : bodies){
@ -890,6 +959,21 @@ public class CollisionEngine {
} }
spaceLock.unlock(); spaceLock.unlock();
} }
/**
* Destroys a geom
* @param body The DGeom to destroy
*/
protected void destroyDGeom(DGeom geom){
spaceLock.lock();
try {
geom.destroy();
} catch (NullPointerException ex){
LoggerInterface.loggerEngine.ERROR(ex);
spaceLock.unlock();
}
spaceLock.unlock();
}
/** /**
* Destroys the physics on an entity * Destroys the physics on an entity
@ -906,6 +990,20 @@ public class CollisionEngine {
e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY); e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY);
this.destroyDBody(rigidBody); this.destroyDBody(rigidBody);
} }
if(PhysicsEntityUtils.containsDGeom(e)){
DGeom geom = PhysicsEntityUtils.getDGeom(e);
if(geom == null){
throw new Error("DGeom key set to null rigid body! " + geom);
}
if(geom instanceof DSpace space){
for(DGeom child : space.getGeoms()){
this.destroyDGeom(child);
}
}
this.deregisterCollisionObject(geom,PhysicsEntityUtils.getCollidable(e));
e.removeData(EntityDataStrings.PHYSICS_GEOM);
this.destroyDGeom(geom);
}
if(ServerPhysicsSyncTree.hasTree(e)){ if(ServerPhysicsSyncTree.hasTree(e)){
ServerPhysicsSyncTree.detachTree(e, ServerPhysicsSyncTree.getTree(e)); ServerPhysicsSyncTree.detachTree(e, ServerPhysicsSyncTree.getTree(e));
} }
@ -954,7 +1052,7 @@ public class CollisionEngine {
spaceLock.unlock(); spaceLock.unlock();
return rVal; return rVal;
} }
/** /**
* Creates a trimesh from a given set of vertices and indices * Creates a trimesh from a given set of vertices and indices
* @param verts The vertices * @param verts The vertices
@ -962,6 +1060,30 @@ public class CollisionEngine {
* @return The DTriMesh * @return The DTriMesh
*/ */
protected DTriMesh createTrimeshGeom(float[] verts, int[] indices, long categoryBits){ protected DTriMesh createTrimeshGeom(float[] verts, int[] indices, long categoryBits){
spaceLock.lock();
DTriMeshData data = OdeHelper.createTriMeshData();
data.build(verts, indices);
final int preprocessFlags =
(1 << DTriMeshData.dTRIDATAPREPROCESS_BUILD.CONCAVE_EDGES) |
(1 << DTriMeshData.dTRIDATAPREPROCESS_BUILD.FACE_ANGLES) |
(1 << DTriMeshData.dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MAX)
;
data.preprocess2(preprocessFlags,null);
DTriMesh rVal = OdeHelper.createTriMesh(this.space, data);
rVal.setTrimeshData(data);
rVal.setCategoryBits(categoryBits);
spaceLock.unlock();
return rVal;
}
/**
* Creates a trimesh from a given set of vertices and indices
* @param verts The vertices
* @param indices The indices
* @param space The space to create it within
* @return The DTriMesh
*/
protected DTriMesh createTrimeshGeom(float[] verts, int[] indices, long categoryBits, DSpace space){
spaceLock.lock(); spaceLock.lock();
DTriMeshData data = OdeHelper.createTriMeshData(); DTriMeshData data = OdeHelper.createTriMeshData();
data.build(verts, indices); data.build(verts, indices);
@ -1031,6 +1153,18 @@ public class CollisionEngine {
return capsuleGeom; return capsuleGeom;
} }
/**
* Creates a space
* @return The space
*/
protected DSpace createSpace(){
spaceLock.lock();
DSpace rVal = OdeHelper.createSimpleSpace();
this.space.add(rVal);
spaceLock.unlock();
return rVal;
}
/** /**
* Creates a DBody. Can optionally be passed DGeom objects to be attached to the body when it is created. * Creates a DBody. Can optionally be passed DGeom objects to be attached to the body when it is created.
* @param geom The geometry objects to attach to the body on creation * @param geom The geometry objects to attach to the body on creation
@ -1210,11 +1344,17 @@ public class CollisionEngine {
*/ */
protected void setGeomTransform(DGeom geom, Vector3d position, Quaterniond rotation){ protected void setGeomTransform(DGeom geom, Vector3d position, Quaterniond rotation){
spaceLock.lock(); spaceLock.lock();
geom.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z); if(geom instanceof DSpace space){
if(geom instanceof DCylinder || geom instanceof DCapsule){ for(DGeom child : space.getGeoms()){
geom.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(new Quaterniond(rotation).rotateX(Math.PI/2.0))); this.setGeomTransform(child, position, rotation);
}
} else { } else {
geom.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation)); geom.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z);
if(geom instanceof DCylinder || geom instanceof DCapsule){
geom.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(new Quaterniond(rotation).rotateX(Math.PI/2.0)));
} else {
geom.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
}
} }
spaceLock.unlock(); spaceLock.unlock();
} }
@ -1331,6 +1471,22 @@ public class CollisionEngine {
protected void attachGeomToBody(DBody body, DGeom geom){ protected void attachGeomToBody(DBody body, DGeom geom){
geom.setBody(body); geom.setBody(body);
} }
/**
* Gets the status of the collision engine
* @return The status of the collision engine
*/
public String getStatus(){
String message = "" +
"Bodies: " + this.bodies.size() + "\n" +
"Body Ptrs: " + this.bodyPointerMap.size() + "\n" +
"Geom Ptrs: " + this.geomPointerMap.size() + "\n" +
"Collidables: " + this.collidableList.size() + "\n" +
"Space geom count: " + this.space.getNumGeoms() + "\n" +
""
;
return message;
}
/** /**

View File

@ -704,6 +704,20 @@ public class PhysicsEntityUtils {
terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
} }
/**
* [CLIENT ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity
* @param terrain The entity
* @param data The terrain description
* @return The rigid body created (note, attachment has already been performed)
*/
public static void clientAttachTriGeomCollider(Entity terrain, TriGeomData data){
DGeom terrainGeom = CollisionBodyCreation.generateGeomFromTerrainData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false);
PhysicsEntityUtils.setCollidable(terrain, collidable);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainGeom, collidable);
PhysicsEntityUtils.setDGeom(terrain,terrainGeom);
}
/** /**
* [CLIENT ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity * [CLIENT ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity
* @param terrain The entity * @param terrain The entity
@ -719,6 +733,20 @@ public class PhysicsEntityUtils {
terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); terrain.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
} }
/**
* [CLIENT ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity
* @param terrain The entity
* @param data The trimesh description
* @return The collider created (note, attachment has already been performed)
*/
public static void clientAttachMultiShapeTriGeomCollider(Entity terrain, MultiShapeTriGeomData data){
DGeom terrainBody = CollisionBodyCreation.generateColliderFromMultiShapeMeshData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false);
PhysicsEntityUtils.setCollidable(terrain, collidable);
Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, collidable);
PhysicsEntityUtils.setDGeom(terrain,terrainBody);
}
/** /**
* [SERVER ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity * [SERVER ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity
@ -737,6 +765,24 @@ public class PhysicsEntityUtils {
return terrainBody; return terrainBody;
} }
/**
* [SERVER ONLY] Given an entity and a terrain chunk description, create physics for the chunk and attach it to the entity
* @param terrain The entity
* @param data The terrain description
* @return The rigid body created (note, attachment has already been performed)
*/
public static DGeom serverAttachTriGeomCollider(Entity terrain, TriGeomData data){
Realm realm = Globals.serverState.realmManager.getEntityRealm(terrain);
DGeom terrainCollider = CollisionBodyCreation.generateGeomFromTerrainData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT);
Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false);
PhysicsEntityUtils.setCollidable(terrain, collidable);
realm.getCollisionEngine().registerCollisionObject(terrainCollider, collidable);
PhysicsEntityUtils.setDGeom(terrain,terrainCollider);
return terrainCollider;
}
/** /**
* [SERVER ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity * [SERVER ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity
* @param terrain The entity * @param terrain The entity
@ -754,6 +800,24 @@ public class PhysicsEntityUtils {
return terrainBody; return terrainBody;
} }
/**
* [SERVER ONLY] Given an entity and a multi-shape trimesh description, create physics for the shapes and attach it to the entity
* @param terrain The entity
* @param data The trimesh description
* @return The rigid body created (note, attachment has already been performed)
*/
public static DGeom serverAttachMultiShapeTriGeomCollider(Entity terrain, MultiShapeTriGeomData data){
Realm realm = Globals.serverState.realmManager.getEntityRealm(terrain);
DGeom terrainBody = CollisionBodyCreation.generateColliderFromMultiShapeMeshData(realm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT);
Collidable collidable = new Collidable(terrain,Collidable.TYPE_STATIC, false);
PhysicsEntityUtils.setCollidable(terrain, collidable);
realm.getCollisionEngine().registerCollisionObject(terrainBody, collidable);
PhysicsEntityUtils.setDGeom(terrain,terrainBody);
return terrainBody;
}
/** /**
* Repositions all active physics-scoped entities on a given realm * Repositions all active physics-scoped entities on a given realm
* @param collisionEngine The realm's collision engine * @param collisionEngine The realm's collision engine
@ -828,6 +892,15 @@ public class PhysicsEntityUtils {
return (DBody)entity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); return (DBody)entity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY);
} }
/**
* Checks if the entity contains a dgeom
* @param entity the entity
* @return true if contains, false otherwise
*/
public static boolean containsDGeom(Entity entity){
return entity.containsKey(EntityDataStrings.PHYSICS_GEOM);
}
/** /**
* Sets the static geom on the entity * Sets the static geom on the entity
* @param entity The entity * @param entity The entity
@ -867,6 +940,15 @@ public class PhysicsEntityUtils {
return (Collidable)entity.getData(EntityDataStrings.PHYSICS_COLLIDABLE); return (Collidable)entity.getData(EntityDataStrings.PHYSICS_COLLIDABLE);
} }
/**
* Gets the collidable attached to the entity
* @param entity The entity
* @param collidable The collidable
*/
public static void setCollidable(Entity entity, Collidable collidable){
entity.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
}
/** /**
* Enables a body * Enables a body
* @param collisionEngine The collision engine * @param collisionEngine The collision engine

View File

@ -1,24 +1,16 @@
package electrosphere.entity.state.collidable; package electrosphere.entity.state.collidable;
import org.joml.AABBd;
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 org.ode4j.ode.DCapsule;
import electrosphere.client.block.BlockChunkData;
import electrosphere.client.scene.ClientWorldData;
import electrosphere.collision.PhysicsUtils; import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.physics.CollisionResult;
import electrosphere.engine.Globals; 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.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.util.math.CollisionUtils;
/** /**
* Client collidable tree * Client collidable tree
@ -28,17 +20,17 @@ public class ClientCollidableTree implements BehaviorTree {
/** /**
* The parent entity of this tree * The parent entity of this tree
*/ */
Entity parent; private Entity parent;
/** /**
* The body for this tree * The body for this tree
*/ */
DBody body; protected DBody body;
/** /**
* The collidable for this tree * The collidable for this tree
*/ */
Collidable collidable; protected Collidable collidable;
/** /**
* Constructor * Constructor
@ -75,89 +67,89 @@ public class ClientCollidableTree implements BehaviorTree {
PhysicsUtils.setRigidBodyTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), newPosition, rotation, body); PhysicsUtils.setRigidBodyTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), newPosition, rotation, body);
//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
DCapsule capsuleGeom = (DCapsule)body.getFirstGeom(); // DCapsule capsuleGeom = (DCapsule)body.getFirstGeom();
double length = capsuleGeom.getLength(); // double length = capsuleGeom.getLength();
double halfLength = length / 2.0; // double halfLength = length / 2.0;
double radius = capsuleGeom.getRadius(); // double radius = capsuleGeom.getRadius();
Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition()); // Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition());
//entity spatial transforms // //entity spatial transforms
Vector3d entRealPos = EntityUtils.getPosition(parent); // Vector3d entRealPos = EntityUtils.getPosition(parent);
Quaterniond entRot = EntityUtils.getRotation(parent); // Quaterniond entRot = EntityUtils.getRotation(parent);
//start and end of capsule // //start and end of capsule
Vector3d realStart = new Vector3d(0,-halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset); // Vector3d realStart = new Vector3d(0,-halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset);
Vector3d realEnd = new Vector3d(0,halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset); // Vector3d realEnd = new Vector3d(0,halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset);
//block position of body // //block position of body
Vector3d blockPos = ClientWorldData.clampRealToBlock(entRealPos); // Vector3d blockPos = ClientWorldData.clampRealToBlock(entRealPos);
Vector3d currBlockPos = new Vector3d(); // Vector3d currBlockPos = new Vector3d();
//get dims to scan along (ceil to overcompensate -- better to over scan than underscan) // //get dims to scan along (ceil to overcompensate -- better to over scan than underscan)
int halfRadBlockLen = (int)Math.ceil(halfLength / BlockChunkData.BLOCK_SIZE_MULTIPLIER); // int halfRadBlockLen = (int)Math.ceil(halfLength / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
int radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER); // int radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
//final corrected position // //final corrected position
Vector3d corrected = new Vector3d(entRealPos); // Vector3d corrected = new Vector3d(entRealPos);
//scan for all potential blocks // //scan for all potential blocks
for(int x = -radBlockLen; x <= radBlockLen; x++){ // for(int x = -radBlockLen; x <= radBlockLen; x++){
for(int z = -radBlockLen; z <= radBlockLen; z++){ // for(int z = -radBlockLen; z <= radBlockLen; z++){
for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){ // for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){
currBlockPos.set(blockPos).add( // currBlockPos.set(blockPos).add(
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER, // x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER, // y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER // z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
); // );
Vector3i chunkPos = ClientWorldData.convertRealToChunkSpace(currBlockPos); // Vector3i chunkPos = ClientWorldData.convertRealToChunkSpace(currBlockPos);
Vector3i entBlockPos = ClientWorldData.convertRealToLocalBlockSpace(currBlockPos); // Vector3i entBlockPos = ClientWorldData.convertRealToLocalBlockSpace(currBlockPos);
//error check bounds // //error check bounds
if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){ // if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){
continue; // continue;
} // }
//get block data for block to check // //get block data for block to check
BlockChunkData data = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(chunkPos, BlockChunkData.LOD_FULL_RES); // BlockChunkData data = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(chunkPos, BlockChunkData.LOD_FULL_RES);
if(data != null){ // if(data != null){
//check type of voxel to skip math // //check type of voxel to skip math
short type = data.getType(entBlockPos.x, entBlockPos.y, entBlockPos.z); // short type = data.getType(entBlockPos.x, entBlockPos.y, entBlockPos.z);
if(type != BlockChunkData.BLOCK_TYPE_EMPTY){ // if(type != BlockChunkData.BLOCK_TYPE_EMPTY){
//AABB for the voxel // //AABB for the voxel
AABBd voxelBox = new AABBd( // AABBd voxelBox = new AABBd(
currBlockPos.x, // currBlockPos.x,
currBlockPos.y, // currBlockPos.y,
currBlockPos.z, // currBlockPos.z,
currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER, // currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER, // currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER // currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER
); // );
//actually collision check // //actually collision check
CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox); // CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox);
if(collisionResult != null){ // if(collisionResult != null){
double pen = collisionResult.getPenetration(); // double pen = collisionResult.getPenetration();
double forceMul = pen * 0.3; // double forceMul = pen * 0.3;
Vector3d normal = collisionResult.getNormal().mul(forceMul); // Vector3d normal = collisionResult.getNormal().mul(forceMul);
if(normal != null){ // if(normal != null){
// body.addForce(normal.x, normal.y, normal.z); // // body.addForce(normal.x, normal.y, normal.z);
//correct the position of the capsule // //correct the position of the capsule
corrected.add(normal); // corrected.add(normal);
} // }
} // }
} // }
} // }
} // }
} // }
} // }
//apply correction // //apply correction
CollisionObjUtils.clientPositionCharacter(parent, newPosition, entRot); // CollisionObjUtils.clientPositionCharacter(parent, newPosition, entRot);
} // }
} }
/** /**

View File

@ -1,28 +1,13 @@
package electrosphere.entity.state.collidable; package electrosphere.entity.state.collidable;
import electrosphere.client.block.BlockChunkData;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.physics.CollisionResult;
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.btree.BehaviorTree; import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.state.gravity.ServerGravityTree; import electrosphere.entity.state.gravity.ServerGravityTree;
import electrosphere.entity.state.movement.fall.ServerFallTree; import electrosphere.entity.state.movement.fall.ServerFallTree;
import electrosphere.entity.types.collision.CollisionObjUtils;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerWorldData;
import electrosphere.server.datacell.interfaces.VoxelCellManager;
import electrosphere.util.math.CollisionUtils;
import org.joml.AABBd;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector3i;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
import org.ode4j.ode.DCapsule;
/** /**
* Server collidable tree * Server collidable tree
@ -32,17 +17,17 @@ public class ServerCollidableTree implements BehaviorTree {
/** /**
* The parent of the collidable * The parent of the collidable
*/ */
Entity parent; private Entity parent;
/** /**
* The body * The body
*/ */
DBody body; protected DBody body;
/** /**
* The collidable * The collidable
*/ */
Collidable collidable; private Collidable collidable;
/** /**
@ -76,92 +61,92 @@ public class ServerCollidableTree implements BehaviorTree {
} }
//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)){
Realm realm = Globals.serverState.realmManager.getEntityRealm(parent); // Realm realm = Globals.serverState.realmManager.getEntityRealm(parent);
if(realm.getDataCellManager() instanceof VoxelCellManager){ // if(realm.getDataCellManager() instanceof VoxelCellManager){
VoxelCellManager voxelCellManager = (VoxelCellManager)realm.getDataCellManager(); // VoxelCellManager voxelCellManager = (VoxelCellManager)realm.getDataCellManager();
//get capsule params // //get capsule params
DCapsule capsuleGeom = (DCapsule)body.getFirstGeom(); // DCapsule capsuleGeom = (DCapsule)body.getFirstGeom();
double length = capsuleGeom.getLength(); // double length = capsuleGeom.getLength();
double halfLength = length / 2.0; // double halfLength = length / 2.0;
double radius = capsuleGeom.getRadius(); // double radius = capsuleGeom.getRadius();
Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition()); // Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition());
//entity spatial transforms // //entity spatial transforms
Vector3d entRealPos = EntityUtils.getPosition(parent); // Vector3d entRealPos = EntityUtils.getPosition(parent);
Quaterniond entRot = EntityUtils.getRotation(parent); // Quaterniond entRot = EntityUtils.getRotation(parent);
//start and end of capsule // //start and end of capsule
Vector3d realStart = new Vector3d(0,-halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset); // Vector3d realStart = new Vector3d(0,-halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset);
Vector3d realEnd = new Vector3d(0,halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset); // Vector3d realEnd = new Vector3d(0,halfLength,0).rotate(entRot).add(entRealPos).add(bodyOffset);
//block position of body // //block position of body
Vector3d blockPos = ServerWorldData.clampRealToBlock(entRealPos); // Vector3d blockPos = ServerWorldData.clampRealToBlock(entRealPos);
Vector3d currBlockPos = new Vector3d(); // Vector3d currBlockPos = new Vector3d();
//get dims to scan along (ceil to overcompensate -- better to over scan than underscan) // //get dims to scan along (ceil to overcompensate -- better to over scan than underscan)
int halfRadBlockLen = (int)Math.ceil(halfLength / BlockChunkData.BLOCK_SIZE_MULTIPLIER); // int halfRadBlockLen = (int)Math.ceil(halfLength / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
int radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER); // int radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
//final corrected position // //final corrected position
Vector3d corrected = new Vector3d(entRealPos); // Vector3d corrected = new Vector3d(entRealPos);
//scan for all potential blocks // //scan for all potential blocks
for(int x = -radBlockLen; x <= radBlockLen; x++){ // for(int x = -radBlockLen; x <= radBlockLen; x++){
for(int z = -radBlockLen; z <= radBlockLen; z++){ // for(int z = -radBlockLen; z <= radBlockLen; z++){
for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){ // for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){
currBlockPos.set(blockPos).add( // currBlockPos.set(blockPos).add(
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER, // x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER, // y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER // z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
); // );
Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(currBlockPos); // Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(currBlockPos);
Vector3i entBlockPos = ServerWorldData.convertRealToLocalBlockSpace(currBlockPos); // Vector3i entBlockPos = ServerWorldData.convertRealToLocalBlockSpace(currBlockPos);
//error check bounds // //error check bounds
if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){ // if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){
continue; // continue;
} // }
//get block data for block to check // //get block data for block to check
BlockChunkData data = voxelCellManager.getBlocksAtPosition(chunkPos); // BlockChunkData data = voxelCellManager.getBlocksAtPosition(chunkPos);
short type = data.getType(entBlockPos.x, entBlockPos.y, entBlockPos.z); // short type = data.getType(entBlockPos.x, entBlockPos.y, entBlockPos.z);
if(type != BlockChunkData.BLOCK_TYPE_EMPTY){ // if(type != BlockChunkData.BLOCK_TYPE_EMPTY){
//AABB for the voxel // //AABB for the voxel
AABBd voxelBox = new AABBd( // AABBd voxelBox = new AABBd(
currBlockPos.x, // currBlockPos.x,
currBlockPos.y, // currBlockPos.y,
currBlockPos.z, // currBlockPos.z,
currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER, // currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER, // currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER // currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER
); // );
//actually collision check // //actually collision check
CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox); // CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox);
if(collisionResult != null){ // if(collisionResult != null){
double pen = collisionResult.getPenetration(); // double pen = collisionResult.getPenetration();
double forceMul = pen * 0.3; // double forceMul = pen * 0.3;
Vector3d normal = collisionResult.getNormal().mul(forceMul); // Vector3d normal = collisionResult.getNormal().mul(forceMul);
if(normal != null){ // if(normal != null){
// body.addForce(normal.x, normal.y, normal.z); // // body.addForce(normal.x, normal.y, normal.z);
//correct the position of the capsule // //correct the position of the capsule
corrected.add(normal); // corrected.add(normal);
} // }
} // }
} // }
} // }
} // }
} // }
//apply correction // //apply correction
CollisionObjUtils.serverPositionCharacter(parent, corrected); // CollisionObjUtils.serverPositionCharacter(parent, corrected);
} // }
} // }
} }

View File

@ -83,12 +83,21 @@ public class CollisionObjUtils {
} }
if(geom != null){ if(geom != null){
CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e); CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e);
PhysicsUtils.setGeomTransform( if(template == null){
collisionEngine, PhysicsUtils.setGeomTransform(
new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()), collisionEngine,
rotation, position,
geom rotation,
); geom
);
} else {
PhysicsUtils.setGeomTransform(
collisionEngine,
new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()),
rotation,
geom
);
}
} }
} }
@ -107,12 +116,21 @@ public class CollisionObjUtils {
DGeom geom = PhysicsEntityUtils.getDGeom(e); DGeom geom = PhysicsEntityUtils.getDGeom(e);
if(geom != null){ if(geom != null){
CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e); CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e);
PhysicsUtils.setGeomTransform( if(template == null){
Globals.clientState.clientSceneWrapper.getCollisionEngine(), PhysicsUtils.setGeomTransform(
new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()), Globals.clientState.clientSceneWrapper.getCollisionEngine(),
rotation, new Vector3d(position),
geom rotation,
); geom
);
} else {
PhysicsUtils.setGeomTransform(
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()),
rotation,
geom
);
}
} }
} }

View File

@ -8,7 +8,7 @@ import java.util.concurrent.Executors;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.ode4j.ode.DBody; import org.ode4j.ode.DGeom;
import electrosphere.client.block.BlockChunkData; import electrosphere.client.block.BlockChunkData;
import electrosphere.client.block.cells.BlockDrawCell; import electrosphere.client.block.cells.BlockDrawCell;
@ -78,7 +78,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.clientAttachMultiShapeTriGeomRigidBody(solidsEnt, data); PhysicsEntityUtils.clientAttachMultiShapeTriGeomCollider(solidsEnt, data);
CollisionObjUtils.clientPositionCharacter(solidsEnt, new Vector3d(EntityUtils.getPosition(solidsEnt)), new Quaterniond()); CollisionObjUtils.clientPositionCharacter(solidsEnt, new Vector3d(EntityUtils.getPosition(solidsEnt)), new Quaterniond());
} else { } else {
EntityCreationUtils.bypassShadowPass(solidsEnt); EntityCreationUtils.bypassShadowPass(solidsEnt);
@ -129,7 +129,7 @@ public class BlockChunkEntity {
})); }));
EntityCreationUtils.makeEntityDrawablePreexistingModel(transparentEnt, modelPath); EntityCreationUtils.makeEntityDrawablePreexistingModel(transparentEnt, modelPath);
if(levelOfDetail == BlockChunkData.LOD_FULL_RES){ if(levelOfDetail == BlockChunkData.LOD_FULL_RES){
PhysicsEntityUtils.clientAttachMultiShapeTriGeomRigidBody(transparentEnt, data); PhysicsEntityUtils.clientAttachMultiShapeTriGeomCollider(transparentEnt, data);
CollisionObjUtils.clientPositionCharacter(transparentEnt, new Vector3d(EntityUtils.getPosition(transparentEnt)), new Quaterniond()); CollisionObjUtils.clientPositionCharacter(transparentEnt, new Vector3d(EntityUtils.getPosition(transparentEnt)), new Quaterniond());
} else { } else {
EntityCreationUtils.bypassShadowPass(transparentEnt); EntityCreationUtils.bypassShadowPass(transparentEnt);
@ -182,12 +182,12 @@ public class BlockChunkEntity {
*/ */
public static void serverCreateBlockChunkEntity(Entity entity, BlockMeshData blockChunkData){ public static void serverCreateBlockChunkEntity(Entity entity, BlockMeshData blockChunkData){
if(blockChunkData.getVertices().length > 0){ if(blockChunkData.getVertices().length > 0){
PhysicsEntityUtils.serverAttachMultiShapeTriGeomRigidBody(entity, blockChunkData); PhysicsEntityUtils.serverAttachMultiShapeTriGeomCollider(entity, blockChunkData);
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
DBody terrainBody = PhysicsEntityUtils.getDBody(entity); DGeom terrainCollider = PhysicsEntityUtils.getDGeom(entity);
Vector3d entityPos = EntityUtils.getPosition(entity); Vector3d entityPos = EntityUtils.getPosition(entity);
Quaterniond entityRot = EntityUtils.getRotation(entity); Quaterniond entityRot = EntityUtils.getRotation(entity);
PhysicsUtils.setRigidBodyTransform(realm.getCollisionEngine(), entityPos, entityRot, terrainBody); PhysicsUtils.setGeomTransform(realm.getCollisionEngine(), entityPos, entityRot, terrainCollider);
entity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); entity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
CommonEntityUtils.setEntityType(entity, EntityType.ENGINE); CommonEntityUtils.setEntityType(entity, EntityType.ENGINE);
} }

View File

@ -6,7 +6,7 @@ import java.util.concurrent.Executors;
import org.joml.Quaterniond; import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3i; import org.joml.Vector3i;
import org.ode4j.ode.DBody; import org.ode4j.ode.DGeom;
import electrosphere.client.block.BlockChunkData; import electrosphere.client.block.BlockChunkData;
import electrosphere.client.terrain.cells.ClientDrawCellManager; import electrosphere.client.terrain.cells.ClientDrawCellManager;
@ -73,7 +73,7 @@ public class TerrainChunk {
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data, atlas, notifyTarget, toDelete); String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data, atlas, notifyTarget, toDelete);
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath); EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
if(levelOfDetail == BlockChunkData.LOD_FULL_RES && data.getFaceElements().length > 0){ if(levelOfDetail == BlockChunkData.LOD_FULL_RES && data.getFaceElements().length > 0){
PhysicsEntityUtils.clientAttachTriGeomRigidBody(rVal, data); PhysicsEntityUtils.clientAttachTriGeomCollider(rVal, data);
Vector3d finalPos = new Vector3d(EntityUtils.getPosition(rVal)); Vector3d finalPos = new Vector3d(EntityUtils.getPosition(rVal));
CollisionObjUtils.clientPositionCharacter(rVal, finalPos, new Quaterniond()); CollisionObjUtils.clientPositionCharacter(rVal, finalPos, new Quaterniond());
} else { } else {
@ -131,11 +131,11 @@ public class TerrainChunk {
if(data.getVertices().length > 0){ if(data.getVertices().length > 0){
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity); Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
if(realm != null){ if(realm != null){
PhysicsEntityUtils.serverAttachTriGeomRigidBody(entity, data); PhysicsEntityUtils.serverAttachTriGeomCollider(entity, data);
DBody terrainBody = PhysicsEntityUtils.getDBody(entity); DGeom terrainGeom = PhysicsEntityUtils.getDGeom(entity);
Vector3d entityPos = EntityUtils.getPosition(entity); Vector3d entityPos = EntityUtils.getPosition(entity);
Quaterniond entityRot = EntityUtils.getRotation(entity); Quaterniond entityRot = EntityUtils.getRotation(entity);
PhysicsUtils.setRigidBodyTransform(realm.getCollisionEngine(), entityPos, entityRot, terrainBody); PhysicsUtils.setGeomTransform(realm.getCollisionEngine(), entityPos, entityRot, terrainGeom);
entity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); entity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
CommonEntityUtils.setEntityType(entity, EntityType.ENGINE); CommonEntityUtils.setEntityType(entity, EntityType.ENGINE);
} }

View File

@ -94,10 +94,12 @@ public class PhysicsDataCell {
return; return;
} }
//generate //generate terrain
this.terrainChunkData = TerrainChunk.serverGenerateTerrainChunkData(weights, types); this.terrainChunkData = TerrainChunk.serverGenerateTerrainChunkData(weights, types);
TerrainChunk.serverCreateTerrainChunkEntity(localPhysicsEnt, this.terrainChunkData); TerrainChunk.serverCreateTerrainChunkEntity(localPhysicsEnt, this.terrainChunkData);
localPhysicsEnt.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); localPhysicsEnt.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
//generate blocks
this.blockData = BlockMeshgen.rasterize(this.blockChunk); this.blockData = BlockMeshgen.rasterize(this.blockChunk);
BlockChunkEntity.serverCreateBlockChunkEntity(localBlockPhysicsEntity, this.blockData); BlockChunkEntity.serverCreateBlockChunkEntity(localBlockPhysicsEntity, this.blockData);
localBlockPhysicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); localBlockPhysicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);