block colliders
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
cbd5c98e0a
commit
4e4367f915
@ -1930,6 +1930,9 @@ Fix town placement structure-road intersection test
|
||||
Kinematic collision templates now use geoms instead of setting kinematic (on client)
|
||||
Geom-only collidables on server
|
||||
|
||||
(05/22/2025)
|
||||
Block colliders leveraging spaces
|
||||
Scene view debug window
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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.render.ImGuiRenderer;
|
||||
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.ImGuiFluidMonitor;
|
||||
import electrosphere.client.ui.menu.debug.server.ImGuiGriddedManager;
|
||||
@ -67,6 +68,7 @@ public class ImGuiWindowMacros {
|
||||
ImGuiMemory.createMemoryDebugWindow();
|
||||
ImGuiEditorWindows.initEditorWindows();
|
||||
ImGuiClientServices.createClientServicesWindow();
|
||||
ImGuiSceneWindow.createChunkMonitorWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,6 +151,9 @@ public class ImGuiWindowMacros {
|
||||
if(ImGui.button("Client Entity Debug")){
|
||||
ImGuiEntityMacros.clientEntityListWindow.setOpen(true);
|
||||
}
|
||||
if(ImGui.button("Client Scene")){
|
||||
ImGuiSceneWindow.viewScene(Globals.clientState.clientScene, Globals.clientState.clientSceneWrapper.getCollisionEngine());
|
||||
}
|
||||
//controls state debug
|
||||
if(ImGui.button("Control State Debug")){
|
||||
ImGuiControls.controlsWindow.setOpen(true);
|
||||
@ -187,6 +192,9 @@ public class ImGuiWindowMacros {
|
||||
if(ImGui.button("Gridded Data Cell Monitor")){
|
||||
ImGuiGriddedManager.griddedManagerWindow.setOpen(true);
|
||||
}
|
||||
if(ImGui.button("Server Scene")){
|
||||
ImGuiSceneWindow.viewScene(null, Globals.serverState.realmManager.first().getCollisionEngine());
|
||||
}
|
||||
//memory usage
|
||||
if(ImGui.button("Memory Usage")){
|
||||
ImGuiMemory.memoryWindow.setOpen(!ImGuiMemory.memoryWindow.isOpen());
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,6 +16,7 @@ import org.ode4j.ode.DCapsule;
|
||||
import org.ode4j.ode.DCylinder;
|
||||
import org.ode4j.ode.DGeom;
|
||||
import org.ode4j.ode.DMass;
|
||||
import org.ode4j.ode.DSpace;
|
||||
import org.ode4j.ode.DSphere;
|
||||
import org.ode4j.ode.DTriMesh;
|
||||
|
||||
@ -296,6 +297,22 @@ public class CollisionBodyCreation {
|
||||
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
|
||||
* @param data The mesh data data
|
||||
@ -325,6 +342,24 @@ public class CollisionBodyCreation {
|
||||
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
|
||||
* @param scene The AIScene to generate a rigid body off of
|
||||
|
||||
@ -404,10 +404,13 @@ public class CollisionEngine {
|
||||
//make sure we have collidables for both
|
||||
if(c1 == null || c2 == null){
|
||||
String message = "Collidable is undefined!\n" +
|
||||
"Geoms:\n" +
|
||||
o1 + " \n" +
|
||||
o2 + " \n" +
|
||||
"Bodies:\n" +
|
||||
b1 + " \n" +
|
||||
b2 + " \n" +
|
||||
"Colliders:\n" +
|
||||
c1 + " \n" +
|
||||
c2 + " \n" +
|
||||
"Obj 1 pointers:\n" +
|
||||
@ -621,18 +624,21 @@ public class CollisionEngine {
|
||||
public void updateDynamicObjectTransforms(){
|
||||
Globals.profiler.beginCpuSample("updateDynamicObjectTransforms");
|
||||
spaceLock.lock();
|
||||
Matrix4d inverseTransform = new Matrix4d();
|
||||
if(this.collisionWorldData != null){
|
||||
for(Collidable collidable : collidableList){
|
||||
if(collidable.getParentTracksCollidable()){
|
||||
Entity physicsEntity = collidable.getParent();
|
||||
DBody rigidBody = PhysicsEntityUtils.getDBody(physicsEntity);
|
||||
DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity);
|
||||
Matrix4d inverseTransform = new Matrix4d();
|
||||
Vector4d rawPos = null;
|
||||
inverseTransform.identity();
|
||||
if(rigidBody != null){
|
||||
rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition()).add(this.floatingOrigin),1));
|
||||
} else if(geom != null){
|
||||
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 suggestedPosition = this.suggestMovementPosition(collisionWorldData, calculatedPosition);
|
||||
@ -650,8 +656,10 @@ public class CollisionEngine {
|
||||
}
|
||||
if(geom != null){
|
||||
CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(physicsEntity);
|
||||
suggestedPosition.sub(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ());
|
||||
newRotation.mul(new Quaterniond(template.getRotX(),template.getRotY(),template.getRotZ(),template.getRotW()).invert());
|
||||
if(template != null){
|
||||
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.getRotation(physicsEntity).set(newRotation);
|
||||
@ -668,7 +676,7 @@ public class CollisionEngine {
|
||||
public void rebaseWorldOrigin(){
|
||||
Globals.profiler.beginCpuSample("rebaseWorldOrigin");
|
||||
spaceLock.lock();
|
||||
if(this.collisionWorldData != null && this.floatingOrigin.x == 0 && this.floatingOrigin.z == 0){
|
||||
if(this.collisionWorldData != null){
|
||||
int collected = 0;
|
||||
Vector3d newOrigin = new Vector3d();
|
||||
//calculate new origin
|
||||
@ -686,6 +694,32 @@ public class CollisionEngine {
|
||||
}
|
||||
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);
|
||||
this.floatingOrigin = this.floatingOrigin.set(newOrigin);
|
||||
@ -700,8 +734,15 @@ public class CollisionEngine {
|
||||
}
|
||||
DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity);
|
||||
if(geom != null){
|
||||
Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(geom.getPosition());
|
||||
geom.setPosition(PhysicsUtils.jomlVecToOdeVec(existingPosition.add(delta)));
|
||||
if(geom instanceof DSpace space){
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param collidable The collidable
|
||||
@ -751,6 +809,17 @@ public class CollisionEngine {
|
||||
collidableList.remove(collidable);
|
||||
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(){
|
||||
for(DBody body : bodies){
|
||||
@ -890,6 +959,21 @@ public class CollisionEngine {
|
||||
}
|
||||
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
|
||||
@ -906,6 +990,20 @@ public class CollisionEngine {
|
||||
e.removeData(EntityDataStrings.PHYSICS_COLLISION_BODY);
|
||||
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)){
|
||||
ServerPhysicsSyncTree.detachTree(e, ServerPhysicsSyncTree.getTree(e));
|
||||
}
|
||||
@ -954,7 +1052,7 @@ public class CollisionEngine {
|
||||
spaceLock.unlock();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a trimesh from a given set of vertices and indices
|
||||
* @param verts The vertices
|
||||
@ -962,6 +1060,30 @@ public class CollisionEngine {
|
||||
* @return The DTriMesh
|
||||
*/
|
||||
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();
|
||||
DTriMeshData data = OdeHelper.createTriMeshData();
|
||||
data.build(verts, indices);
|
||||
@ -1031,6 +1153,18 @@ public class CollisionEngine {
|
||||
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.
|
||||
* @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){
|
||||
spaceLock.lock();
|
||||
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)));
|
||||
if(geom instanceof DSpace space){
|
||||
for(DGeom child : space.getGeoms()){
|
||||
this.setGeomTransform(child, position, rotation);
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
@ -1331,6 +1471,22 @@ public class CollisionEngine {
|
||||
protected void attachGeomToBody(DBody body, DGeom geom){
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -704,6 +704,20 @@ public class PhysicsEntityUtils {
|
||||
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
|
||||
* @param terrain The entity
|
||||
@ -719,6 +733,20 @@ public class PhysicsEntityUtils {
|
||||
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
|
||||
@ -737,6 +765,24 @@ public class PhysicsEntityUtils {
|
||||
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
|
||||
* @param terrain The entity
|
||||
@ -754,6 +800,24 @@ public class PhysicsEntityUtils {
|
||||
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
|
||||
* @param collisionEngine The realm's collision engine
|
||||
@ -828,6 +892,15 @@ public class PhysicsEntityUtils {
|
||||
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
|
||||
* @param entity The entity
|
||||
@ -867,6 +940,15 @@ public class PhysicsEntityUtils {
|
||||
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
|
||||
* @param collisionEngine The collision engine
|
||||
|
||||
@ -1,24 +1,16 @@
|
||||
package electrosphere.entity.state.collidable;
|
||||
|
||||
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.DCapsule;
|
||||
|
||||
import electrosphere.client.block.BlockChunkData;
|
||||
import electrosphere.client.scene.ClientWorldData;
|
||||
import electrosphere.collision.PhysicsUtils;
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.collision.physics.CollisionResult;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||
import electrosphere.util.math.CollisionUtils;
|
||||
|
||||
/**
|
||||
* Client collidable tree
|
||||
@ -28,17 +20,17 @@ public class ClientCollidableTree implements BehaviorTree {
|
||||
/**
|
||||
* The parent entity of this tree
|
||||
*/
|
||||
Entity parent;
|
||||
private Entity parent;
|
||||
|
||||
/**
|
||||
* The body for this tree
|
||||
*/
|
||||
DBody body;
|
||||
protected DBody body;
|
||||
|
||||
/**
|
||||
* The collidable for this tree
|
||||
*/
|
||||
Collidable collidable;
|
||||
protected Collidable collidable;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@ -75,89 +67,89 @@ public class ClientCollidableTree implements BehaviorTree {
|
||||
PhysicsUtils.setRigidBodyTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), newPosition, rotation, body);
|
||||
|
||||
//capsule-specific block collision logic
|
||||
if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){
|
||||
//get capsule params
|
||||
DCapsule capsuleGeom = (DCapsule)body.getFirstGeom();
|
||||
double length = capsuleGeom.getLength();
|
||||
double halfLength = length / 2.0;
|
||||
double radius = capsuleGeom.getRadius();
|
||||
Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition());
|
||||
// if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){
|
||||
// //get capsule params
|
||||
// DCapsule capsuleGeom = (DCapsule)body.getFirstGeom();
|
||||
// double length = capsuleGeom.getLength();
|
||||
// double halfLength = length / 2.0;
|
||||
// double radius = capsuleGeom.getRadius();
|
||||
// Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition());
|
||||
|
||||
//entity spatial transforms
|
||||
Vector3d entRealPos = EntityUtils.getPosition(parent);
|
||||
Quaterniond entRot = EntityUtils.getRotation(parent);
|
||||
// //entity spatial transforms
|
||||
// Vector3d entRealPos = EntityUtils.getPosition(parent);
|
||||
// Quaterniond entRot = EntityUtils.getRotation(parent);
|
||||
|
||||
//start and end of capsule
|
||||
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);
|
||||
// //start and end of capsule
|
||||
// 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);
|
||||
|
||||
|
||||
//block position of body
|
||||
Vector3d blockPos = ClientWorldData.clampRealToBlock(entRealPos);
|
||||
Vector3d currBlockPos = new Vector3d();
|
||||
// //block position of body
|
||||
// Vector3d blockPos = ClientWorldData.clampRealToBlock(entRealPos);
|
||||
// Vector3d currBlockPos = new Vector3d();
|
||||
|
||||
//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 radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
|
||||
// //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 radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
|
||||
|
||||
//final corrected position
|
||||
Vector3d corrected = new Vector3d(entRealPos);
|
||||
// //final corrected position
|
||||
// Vector3d corrected = new Vector3d(entRealPos);
|
||||
|
||||
//scan for all potential blocks
|
||||
for(int x = -radBlockLen; x <= radBlockLen; x++){
|
||||
for(int z = -radBlockLen; z <= radBlockLen; z++){
|
||||
for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){
|
||||
currBlockPos.set(blockPos).add(
|
||||
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
);
|
||||
Vector3i chunkPos = ClientWorldData.convertRealToChunkSpace(currBlockPos);
|
||||
Vector3i entBlockPos = ClientWorldData.convertRealToLocalBlockSpace(currBlockPos);
|
||||
// //scan for all potential blocks
|
||||
// for(int x = -radBlockLen; x <= radBlockLen; x++){
|
||||
// for(int z = -radBlockLen; z <= radBlockLen; z++){
|
||||
// for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){
|
||||
// currBlockPos.set(blockPos).add(
|
||||
// x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
// );
|
||||
// Vector3i chunkPos = ClientWorldData.convertRealToChunkSpace(currBlockPos);
|
||||
// Vector3i entBlockPos = ClientWorldData.convertRealToLocalBlockSpace(currBlockPos);
|
||||
|
||||
//error check bounds
|
||||
if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){
|
||||
continue;
|
||||
}
|
||||
// //error check bounds
|
||||
// if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){
|
||||
// continue;
|
||||
// }
|
||||
|
||||
//get block data for block to check
|
||||
BlockChunkData data = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(chunkPos, BlockChunkData.LOD_FULL_RES);
|
||||
if(data != null){
|
||||
//check type of voxel to skip math
|
||||
short type = data.getType(entBlockPos.x, entBlockPos.y, entBlockPos.z);
|
||||
if(type != BlockChunkData.BLOCK_TYPE_EMPTY){
|
||||
// //get block data for block to check
|
||||
// BlockChunkData data = Globals.clientState.clientBlockManager.getChunkDataAtWorldPoint(chunkPos, BlockChunkData.LOD_FULL_RES);
|
||||
// if(data != null){
|
||||
// //check type of voxel to skip math
|
||||
// short type = data.getType(entBlockPos.x, entBlockPos.y, entBlockPos.z);
|
||||
// if(type != BlockChunkData.BLOCK_TYPE_EMPTY){
|
||||
|
||||
//AABB for the voxel
|
||||
AABBd voxelBox = new AABBd(
|
||||
currBlockPos.x,
|
||||
currBlockPos.y,
|
||||
currBlockPos.z,
|
||||
currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
);
|
||||
// //AABB for the voxel
|
||||
// AABBd voxelBox = new AABBd(
|
||||
// currBlockPos.x,
|
||||
// currBlockPos.y,
|
||||
// currBlockPos.z,
|
||||
// currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
// );
|
||||
|
||||
//actually collision check
|
||||
CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox);
|
||||
if(collisionResult != null){
|
||||
double pen = collisionResult.getPenetration();
|
||||
double forceMul = pen * 0.3;
|
||||
Vector3d normal = collisionResult.getNormal().mul(forceMul);
|
||||
if(normal != null){
|
||||
// body.addForce(normal.x, normal.y, normal.z);
|
||||
//correct the position of the capsule
|
||||
corrected.add(normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// //actually collision check
|
||||
// CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox);
|
||||
// if(collisionResult != null){
|
||||
// double pen = collisionResult.getPenetration();
|
||||
// double forceMul = pen * 0.3;
|
||||
// Vector3d normal = collisionResult.getNormal().mul(forceMul);
|
||||
// if(normal != null){
|
||||
// // body.addForce(normal.x, normal.y, normal.z);
|
||||
// //correct the position of the capsule
|
||||
// corrected.add(normal);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//apply correction
|
||||
CollisionObjUtils.clientPositionCharacter(parent, newPosition, entRot);
|
||||
}
|
||||
// //apply correction
|
||||
// CollisionObjUtils.clientPositionCharacter(parent, newPosition, entRot);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,28 +1,13 @@
|
||||
package electrosphere.entity.state.collidable;
|
||||
|
||||
import electrosphere.client.block.BlockChunkData;
|
||||
import electrosphere.collision.PhysicsUtils;
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.collision.physics.CollisionResult;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.state.gravity.ServerGravityTree;
|
||||
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.DCapsule;
|
||||
|
||||
/**
|
||||
* Server collidable tree
|
||||
@ -32,17 +17,17 @@ public class ServerCollidableTree implements BehaviorTree {
|
||||
/**
|
||||
* The parent of the collidable
|
||||
*/
|
||||
Entity parent;
|
||||
private Entity parent;
|
||||
|
||||
/**
|
||||
* The body
|
||||
*/
|
||||
DBody body;
|
||||
protected DBody body;
|
||||
|
||||
/**
|
||||
* The collidable
|
||||
*/
|
||||
Collidable collidable;
|
||||
private Collidable collidable;
|
||||
|
||||
|
||||
/**
|
||||
@ -76,92 +61,92 @@ public class ServerCollidableTree implements BehaviorTree {
|
||||
}
|
||||
|
||||
//capsule-specific block collision logic
|
||||
if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){
|
||||
Realm realm = Globals.serverState.realmManager.getEntityRealm(parent);
|
||||
if(realm.getDataCellManager() instanceof VoxelCellManager){
|
||||
VoxelCellManager voxelCellManager = (VoxelCellManager)realm.getDataCellManager();
|
||||
// if(body.isEnabled() && body.getFirstGeom() != null && (body.getFirstGeom() instanceof DCapsule)){
|
||||
// Realm realm = Globals.serverState.realmManager.getEntityRealm(parent);
|
||||
// if(realm.getDataCellManager() instanceof VoxelCellManager){
|
||||
// VoxelCellManager voxelCellManager = (VoxelCellManager)realm.getDataCellManager();
|
||||
|
||||
//get capsule params
|
||||
DCapsule capsuleGeom = (DCapsule)body.getFirstGeom();
|
||||
double length = capsuleGeom.getLength();
|
||||
double halfLength = length / 2.0;
|
||||
double radius = capsuleGeom.getRadius();
|
||||
Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition());
|
||||
// //get capsule params
|
||||
// DCapsule capsuleGeom = (DCapsule)body.getFirstGeom();
|
||||
// double length = capsuleGeom.getLength();
|
||||
// double halfLength = length / 2.0;
|
||||
// double radius = capsuleGeom.getRadius();
|
||||
// Vector3d bodyOffset = PhysicsUtils.odeVecToJomlVec(body.getFirstGeom().getOffsetPosition());
|
||||
|
||||
//entity spatial transforms
|
||||
Vector3d entRealPos = EntityUtils.getPosition(parent);
|
||||
Quaterniond entRot = EntityUtils.getRotation(parent);
|
||||
// //entity spatial transforms
|
||||
// Vector3d entRealPos = EntityUtils.getPosition(parent);
|
||||
// Quaterniond entRot = EntityUtils.getRotation(parent);
|
||||
|
||||
//start and end of capsule
|
||||
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);
|
||||
// //start and end of capsule
|
||||
// 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);
|
||||
|
||||
|
||||
//block position of body
|
||||
Vector3d blockPos = ServerWorldData.clampRealToBlock(entRealPos);
|
||||
Vector3d currBlockPos = new Vector3d();
|
||||
// //block position of body
|
||||
// Vector3d blockPos = ServerWorldData.clampRealToBlock(entRealPos);
|
||||
// Vector3d currBlockPos = new Vector3d();
|
||||
|
||||
//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 radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
|
||||
// //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 radBlockLen = (int)Math.ceil(radius / BlockChunkData.BLOCK_SIZE_MULTIPLIER);
|
||||
|
||||
//final corrected position
|
||||
Vector3d corrected = new Vector3d(entRealPos);
|
||||
// //final corrected position
|
||||
// Vector3d corrected = new Vector3d(entRealPos);
|
||||
|
||||
//scan for all potential blocks
|
||||
for(int x = -radBlockLen; x <= radBlockLen; x++){
|
||||
for(int z = -radBlockLen; z <= radBlockLen; z++){
|
||||
for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){
|
||||
currBlockPos.set(blockPos).add(
|
||||
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
);
|
||||
Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(currBlockPos);
|
||||
Vector3i entBlockPos = ServerWorldData.convertRealToLocalBlockSpace(currBlockPos);
|
||||
// //scan for all potential blocks
|
||||
// for(int x = -radBlockLen; x <= radBlockLen; x++){
|
||||
// for(int z = -radBlockLen; z <= radBlockLen; z++){
|
||||
// for(int y = -halfRadBlockLen; y <= halfRadBlockLen; y++){
|
||||
// currBlockPos.set(blockPos).add(
|
||||
// x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
// );
|
||||
// Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(currBlockPos);
|
||||
// Vector3i entBlockPos = ServerWorldData.convertRealToLocalBlockSpace(currBlockPos);
|
||||
|
||||
//error check bounds
|
||||
if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){
|
||||
continue;
|
||||
}
|
||||
// //error check bounds
|
||||
// if(chunkPos.x < 0 || chunkPos.y < 0 || chunkPos.z < 0){
|
||||
// continue;
|
||||
// }
|
||||
|
||||
//get block data for block to check
|
||||
BlockChunkData data = voxelCellManager.getBlocksAtPosition(chunkPos);
|
||||
short type = data.getType(entBlockPos.x, entBlockPos.y, entBlockPos.z);
|
||||
// //get block data for block to check
|
||||
// BlockChunkData data = voxelCellManager.getBlocksAtPosition(chunkPos);
|
||||
// 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
|
||||
AABBd voxelBox = new AABBd(
|
||||
currBlockPos.x,
|
||||
currBlockPos.y,
|
||||
currBlockPos.z,
|
||||
currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
);
|
||||
// //AABB for the voxel
|
||||
// AABBd voxelBox = new AABBd(
|
||||
// currBlockPos.x,
|
||||
// currBlockPos.y,
|
||||
// currBlockPos.z,
|
||||
// currBlockPos.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// currBlockPos.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER,
|
||||
// currBlockPos.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER
|
||||
// );
|
||||
|
||||
//actually collision check
|
||||
CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox);
|
||||
if(collisionResult != null){
|
||||
double pen = collisionResult.getPenetration();
|
||||
double forceMul = pen * 0.3;
|
||||
Vector3d normal = collisionResult.getNormal().mul(forceMul);
|
||||
if(normal != null){
|
||||
// body.addForce(normal.x, normal.y, normal.z);
|
||||
//correct the position of the capsule
|
||||
corrected.add(normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// //actually collision check
|
||||
// CollisionResult collisionResult = CollisionUtils.collideCapsuleAABB(realStart, realEnd, radius, voxelBox);
|
||||
// if(collisionResult != null){
|
||||
// double pen = collisionResult.getPenetration();
|
||||
// double forceMul = pen * 0.3;
|
||||
// Vector3d normal = collisionResult.getNormal().mul(forceMul);
|
||||
// if(normal != null){
|
||||
// // body.addForce(normal.x, normal.y, normal.z);
|
||||
// //correct the position of the capsule
|
||||
// corrected.add(normal);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//apply correction
|
||||
CollisionObjUtils.serverPositionCharacter(parent, corrected);
|
||||
}
|
||||
}
|
||||
// //apply correction
|
||||
// CollisionObjUtils.serverPositionCharacter(parent, corrected);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -83,12 +83,21 @@ public class CollisionObjUtils {
|
||||
}
|
||||
if(geom != null){
|
||||
CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e);
|
||||
PhysicsUtils.setGeomTransform(
|
||||
collisionEngine,
|
||||
new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()),
|
||||
rotation,
|
||||
geom
|
||||
);
|
||||
if(template == null){
|
||||
PhysicsUtils.setGeomTransform(
|
||||
collisionEngine,
|
||||
position,
|
||||
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);
|
||||
if(geom != null){
|
||||
CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e);
|
||||
PhysicsUtils.setGeomTransform(
|
||||
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
|
||||
new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()),
|
||||
rotation,
|
||||
geom
|
||||
);
|
||||
if(template == null){
|
||||
PhysicsUtils.setGeomTransform(
|
||||
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
|
||||
new Vector3d(position),
|
||||
rotation,
|
||||
geom
|
||||
);
|
||||
} else {
|
||||
PhysicsUtils.setGeomTransform(
|
||||
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
|
||||
new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()),
|
||||
rotation,
|
||||
geom
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import java.util.concurrent.Executors;
|
||||
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.ode4j.ode.DBody;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
import electrosphere.client.block.BlockChunkData;
|
||||
import electrosphere.client.block.cells.BlockDrawCell;
|
||||
@ -78,7 +78,7 @@ public class BlockChunkEntity {
|
||||
}));
|
||||
EntityCreationUtils.makeEntityDrawablePreexistingModel(solidsEnt, modelPath);
|
||||
if(levelOfDetail == BlockChunkData.LOD_FULL_RES){
|
||||
PhysicsEntityUtils.clientAttachMultiShapeTriGeomRigidBody(solidsEnt, data);
|
||||
PhysicsEntityUtils.clientAttachMultiShapeTriGeomCollider(solidsEnt, data);
|
||||
CollisionObjUtils.clientPositionCharacter(solidsEnt, new Vector3d(EntityUtils.getPosition(solidsEnt)), new Quaterniond());
|
||||
} else {
|
||||
EntityCreationUtils.bypassShadowPass(solidsEnt);
|
||||
@ -129,7 +129,7 @@ public class BlockChunkEntity {
|
||||
}));
|
||||
EntityCreationUtils.makeEntityDrawablePreexistingModel(transparentEnt, modelPath);
|
||||
if(levelOfDetail == BlockChunkData.LOD_FULL_RES){
|
||||
PhysicsEntityUtils.clientAttachMultiShapeTriGeomRigidBody(transparentEnt, data);
|
||||
PhysicsEntityUtils.clientAttachMultiShapeTriGeomCollider(transparentEnt, data);
|
||||
CollisionObjUtils.clientPositionCharacter(transparentEnt, new Vector3d(EntityUtils.getPosition(transparentEnt)), new Quaterniond());
|
||||
} else {
|
||||
EntityCreationUtils.bypassShadowPass(transparentEnt);
|
||||
@ -182,12 +182,12 @@ public class BlockChunkEntity {
|
||||
*/
|
||||
public static void serverCreateBlockChunkEntity(Entity entity, BlockMeshData blockChunkData){
|
||||
if(blockChunkData.getVertices().length > 0){
|
||||
PhysicsEntityUtils.serverAttachMultiShapeTriGeomRigidBody(entity, blockChunkData);
|
||||
PhysicsEntityUtils.serverAttachMultiShapeTriGeomCollider(entity, blockChunkData);
|
||||
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
|
||||
DBody terrainBody = PhysicsEntityUtils.getDBody(entity);
|
||||
DGeom terrainCollider = PhysicsEntityUtils.getDGeom(entity);
|
||||
Vector3d entityPos = EntityUtils.getPosition(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);
|
||||
CommonEntityUtils.setEntityType(entity, EntityType.ENGINE);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import java.util.concurrent.Executors;
|
||||
import org.joml.Quaterniond;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3i;
|
||||
import org.ode4j.ode.DBody;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
import electrosphere.client.block.BlockChunkData;
|
||||
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
||||
@ -73,7 +73,7 @@ public class TerrainChunk {
|
||||
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data, atlas, notifyTarget, toDelete);
|
||||
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
|
||||
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));
|
||||
CollisionObjUtils.clientPositionCharacter(rVal, finalPos, new Quaterniond());
|
||||
} else {
|
||||
@ -131,11 +131,11 @@ public class TerrainChunk {
|
||||
if(data.getVertices().length > 0){
|
||||
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
|
||||
if(realm != null){
|
||||
PhysicsEntityUtils.serverAttachTriGeomRigidBody(entity, data);
|
||||
DBody terrainBody = PhysicsEntityUtils.getDBody(entity);
|
||||
PhysicsEntityUtils.serverAttachTriGeomCollider(entity, data);
|
||||
DGeom terrainGeom = PhysicsEntityUtils.getDGeom(entity);
|
||||
Vector3d entityPos = EntityUtils.getPosition(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);
|
||||
CommonEntityUtils.setEntityType(entity, EntityType.ENGINE);
|
||||
}
|
||||
|
||||
@ -94,10 +94,12 @@ public class PhysicsDataCell {
|
||||
return;
|
||||
}
|
||||
|
||||
//generate
|
||||
//generate terrain
|
||||
this.terrainChunkData = TerrainChunk.serverGenerateTerrainChunkData(weights, types);
|
||||
TerrainChunk.serverCreateTerrainChunkEntity(localPhysicsEnt, this.terrainChunkData);
|
||||
localPhysicsEnt.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
||||
|
||||
//generate blocks
|
||||
this.blockData = BlockMeshgen.rasterize(this.blockChunk);
|
||||
BlockChunkEntity.serverCreateBlockChunkEntity(localBlockPhysicsEntity, this.blockData);
|
||||
localBlockPhysicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user