physics work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-09-13 09:30:21 -04:00
parent 90793154ed
commit b761299c29
20 changed files with 670 additions and 199 deletions

View File

@ -12,6 +12,9 @@
],
"collidable": {
"type" : "CUBE",
"mass": 10.0,
"rollingFriction": 100.0,
"linearFriction": 100.0,
"dimension1" : 2.0,
"dimension2" : 2.0,
"dimension3" : 2.0,

View File

@ -744,6 +744,8 @@ Move AttachUtils package
Move Scene package
Crate object
Data cleanup
Delete Structure entity type
Physics work
# TODO

View File

@ -64,9 +64,12 @@ public class ClientSceneWrapper {
/**
* Resolves a client ID to the equivalent ID on the server
* @param clientId The id provided by the client
* @return The equivalent id on the server
* @return The equivalent id on the server, or -1 if no equivalent is found
*/
public int mapClientToServerId(int clientId){
if(clientToServerIdMap.get(clientId) == null){
return -1;
}
return clientToServerIdMap.get(clientId);
}

View File

@ -2,6 +2,7 @@ package electrosphere.collision;
import java.nio.IntBuffer;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIFace;
@ -14,6 +15,7 @@ import org.ode4j.ode.DBox;
import org.ode4j.ode.DCapsule;
import org.ode4j.ode.DCylinder;
import org.ode4j.ode.DGeom;
import org.ode4j.ode.DMass;
import org.ode4j.ode.DSphere;
import org.ode4j.ode.DTriMesh;
@ -83,6 +85,18 @@ public class CollisionBodyCreation {
return collisionEngine.createDBody(geom);
}
/**
* Creates a capsule body in the collision engine
* @param collisionEngine The collision engine
* @param length The length of the capsule (not including round part at ends)
* @param radius The radius of the sphere
* @return The DBody
*/
public static DBody createCapsuleBody(CollisionEngine collisionEngine, double length, double radius, long categoryBits){
DCapsule geom = collisionEngine.createCapsuleGeom(radius,length,categoryBits);
return collisionEngine.createDBody(geom);
}
/**
* Creates a dbody with existing shapes that are provided
* @param collisionEngine the collision engine to create it in
@ -116,6 +130,42 @@ public class CollisionBodyCreation {
return collisionEngine.createCapsuleGeom(radius, length, categoryBits);
}
/**
* Sets the mass on the dbody
* @param collisionEngine The collision engine
* @param body The body
* @param mass The mass value
* @param radius The radius of the cylinder
* @param length The length of the cylinder
* @return The DMass object
*/
public static DMass setCylinderMass(CollisionEngine collisionEngine, DBody body, double mass, double radius, double length, Vector3d offset, Quaterniond rotation){
return collisionEngine.createCylinderMass(mass, radius, length, body, offset, rotation);
}
/**
* Sets the mass on the dbody
* @param collisionEngine The collision engine
* @param body The body
* @param mass The mass value
* @param dims The dimensions of the box
* @return The DMass object
*/
public static DMass setBoxMass(CollisionEngine collisionEngine, DBody body, double mass, Vector3d dims, Vector3d offset, Quaterniond rotation){
return collisionEngine.createBoxMass(mass, dims, body, offset, rotation);
}
/**
* Sets the damping for the body
* @param collisionEngine The collision engine
* @param body The body
* @param linearDamping The linear damping
* @param angularDamping The angular damping
*/
public static void setDamping(CollisionEngine collisionEngine, DBody body, double linearDamping, double angularDamping){
collisionEngine.setDamping(body, linearDamping, angularDamping);
}
/**
* Sets the provided body to be a kinematic body (no gravity applied)
* @param collisionEngine The collision engine

View File

@ -19,7 +19,6 @@ import org.joml.Matrix4d;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.joml.Vector4d;
import org.ode4j.math.DMatrix3;
import org.ode4j.math.DVector3;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DBox;
@ -40,11 +39,11 @@ import org.ode4j.ode.DSphere;
import org.ode4j.ode.DTriMesh;
import org.ode4j.ode.DTriMeshData;
import org.ode4j.ode.DWorld;
import org.ode4j.ode.OdeConstants;
import org.ode4j.ode.OdeHelper;
import electrosphere.collision.RayCastCallback.RayCastCallbackData;
import electrosphere.collision.collidable.Collidable;
import electrosphere.collision.collidable.SurfaceParams;
import electrosphere.engine.Globals;
import electrosphere.engine.time.Timekeeper;
import electrosphere.entity.Entity;
@ -63,6 +62,21 @@ public class CollisionEngine {
//gravity constant
public static final float GRAVITY_MAGNITUDE = 9.8f * 2;
/**
* The damping applied to angular velocity
*/
public static final double DEFAULT_ANGULAR_DAMPING = 0.01;
/**
* The damping applied to linear velocity
*/
public static final double DEFAULT_LINEAR_DAMPING = 0.01;
/**
* Default max angular speed
*/
public static final double DEFAULT_MAX_ANGULAR_SPEED = 100;
//world data that the collision engine leverages for position correction and the like
CollisionWorldData collisionWorldData;
@ -103,6 +117,15 @@ public class CollisionEngine {
world = OdeHelper.createWorld();
space = OdeHelper.createBHVSpace(Collidable.TYPE_STATIC_BIT);
world.setGravity(0,-GRAVITY_MAGNITUDE,0);
world.setAutoDisableFlag(true);
// world.setContactMaxCorrectingVel(0.1);
world.setContactSurfaceLayer(0.001);
world.setCFM(0.00000001);
//base plane
OdeHelper.createPlane(space, 0, 1, 0, 0);
contactgroup = OdeHelper.createJointGroup();
this.nearCallback = new DNearCallback() {
@Override
@ -296,33 +319,52 @@ public class CollisionEngine {
return;
}
//creates a buffer to store potential collisions
DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); // up to MAX_CONTACTS contacts per box-box
for (int i=0; i<MAX_CONTACTS; i++) {
DContact contact = contacts.get(i);
contact.surface.mode = OdeConstants.dContactApprox1 & OdeConstants.dContactRolling;//dContactBounce | dContactSoftCFM;
contact.surface.mu = 10;
// contact.surface.mu = dInfinity;
// contact.surface.mu2 = 0;
// contact.surface.bounce = 0.1;
// contact.surface.bounce_vel = 0.1;
// contact.surface.soft_cfm = 0.01;
}
Collidable c1 = bodyPointerMap.get(b1);
Collidable c2 = bodyPointerMap.get(b2);
if(c1 == null || c2 == null){
return;
}
if(
bodyPointerMap.get(b1) != null &&
bodyPointerMap.get(b2) != null &&
!(bodyPointerMap.get(b1).getType() == Collidable.TYPE_TERRAIN && bodyPointerMap.get(b2).getType() == Collidable.TYPE_TERRAIN) &&
!(bodyPointerMap.get(b1).getType() == Collidable.TYPE_FOLIAGE_STATIC && bodyPointerMap.get(b2).getType() == Collidable.TYPE_FOLIAGE_STATIC)
){
try {
//creates a buffer to store potential collisions
DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); // up to MAX_CONTACTS contacts per box-box
SurfaceParams surfaceParams = c1.getSurfaceParams();
for (int i=0; i<MAX_CONTACTS; i++) {
DContact contact = contacts.get(i);
contact.surface.mode = surfaceParams.getMode();
contact.surface.mu = surfaceParams.getMu();
if(surfaceParams.getRho() != null){
contact.surface.rho = surfaceParams.getRho();
}
if(surfaceParams.getRho2() != null){
contact.surface.rho2 = surfaceParams.getRho2();
}
if(surfaceParams.getRhoN() != null){
contact.surface.rhoN = surfaceParams.getRhoN();
}
if(surfaceParams.getBounce() != null){
contact.surface.bounce = surfaceParams.getBounce();
}
if(surfaceParams.getBounceVel() != null){
contact.surface.bounce_vel = surfaceParams.getBounceVel();
}
}
//calculate collisions
int numc = OdeHelper.collide(o1,o2,MAX_CONTACTS,contacts.getGeomBuffer());
//create DContacts based on each collision that occurs
if (numc != 0) {
DMatrix3 RI = new DMatrix3();
RI.setIdentity ();
for (int i=0; i<numc; i++) {
DContact contact = contacts.get(i);
//
//add contact to contact group
DJoint c = OdeHelper.createContactJoint(world,contactgroup,contact);
c.attach(b1,b2);
//special code for ray casting
if (o1 instanceof DRay || o2 instanceof DRay){
DVector3 end = new DVector3();
@ -374,10 +416,6 @@ public class CollisionEngine {
(float)contact.geom.depth
);
}
//add contact to contact group
DJoint c = OdeHelper.createContactJoint (world,contactgroup,contact );
c.attach (b1,b2);
}
}
} catch(ArrayIndexOutOfBoundsException ex){
@ -727,6 +765,8 @@ public class CollisionEngine {
protected DBody createDBody(DGeom ...geom){
spaceLock.acquireUninterruptibly();
DBody body = OdeHelper.createBody(world);
body.setDamping(DEFAULT_LINEAR_DAMPING, DEFAULT_ANGULAR_DAMPING);
body.setMaxAngularSpeed(DEFAULT_MAX_ANGULAR_SPEED);
if(geom != null){
for(int i = 0; i < geom.length; i++){
if(geom != null){
@ -741,17 +781,54 @@ public class CollisionEngine {
/**
* Creates a DMass and attaches a body to it
* @param massValue The amount of mass for the object
* @param radius The radius of the cylinder
* @param length The length of the cylinder
* @param body The DBody to attach the mass to
* @return The DMass
*/
protected DMass createDMass(double massValue, DBody body){
protected DMass createCylinderMass(double massValue, double radius, double length, DBody body, Vector3d offset, Quaterniond rotation){
spaceLock.acquireUninterruptibly();
DMass mass = OdeHelper.createMass();
mass.setMass(massValue);
mass.setCylinder(massValue, 2, radius, length);
// mass.setCylinderTotal(massValue, 2, radius, length);
// mass.translate(offset.x, offset.y, offset.z);
// mass.rotate(PhysicsUtils.jomlQuatToOdeMat(rotation));
body.setMass(mass);
spaceLock.release();
return mass;
}
/**
* Creates a DMass and attaches a body to it
* @param massValue The amount of mass for the object
* @param dims The dimensions of the box
* @param body The DBody to attach the mass to
* @return The DMass
*/
protected DMass createBoxMass(double massValue, Vector3d dims, DBody body, Vector3d offset, Quaterniond rotation){
spaceLock.acquireUninterruptibly();
DMass mass = OdeHelper.createMass();
mass.setBox(massValue, dims.x, dims.y, dims.z);
// mass.setBoxTotal(massValue, dims.x, dims.y, dims.z);
// mass.translate(offset.x, offset.y, offset.z);
// mass.rotate(PhysicsUtils.jomlQuatToOdeMat(rotation));
body.setMass(mass);
spaceLock.release();
return mass;
}
/**
* Sets the damping of the body
* @param body The body
* @param linearDamping The linear damping
* @param angularDamping The angular damping
*/
protected void setDamping(DBody body, double linearDamping, double angularDamping){
spaceLock.acquireUninterruptibly();
body.setDamping(linearDamping, angularDamping);
spaceLock.release();
}
/**
* Sets the transform on a body
* @param body The body
@ -899,7 +976,7 @@ public class CollisionEngine {
if(angularlyStatic){
body.setMaxAngularSpeed(0);
} else {
body.setMaxAngularSpeed(1000);
body.setMaxAngularSpeed(DEFAULT_MAX_ANGULAR_SPEED);
}
spaceLock.release();
}

View File

@ -34,23 +34,55 @@ public class PhysicsEntityUtils {
public static void clientAttachCollidableTemplate(Entity rVal, CollidableTemplate physicsTemplate){
DBody rigidBody = null;
Collidable collidable;
float mass = 1.0f;
double mass = 1.0f;
if(physicsTemplate.getMass() != null){
mass = physicsTemplate.getMass();
}
switch(physicsTemplate.getType()){
case "CYLINDER": {
//
//create dbody
rigidBody = CollisionBodyCreation.createCylinderBody(
Globals.clientSceneWrapper.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
Collidable.TYPE_CREATURE_BIT
);
if(physicsTemplate.getMass() != null){
CollisionBodyCreation.setCylinderMass(
Globals.clientSceneWrapper.getCollisionEngine(),
rigidBody,
mass,
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
);
}
//
//set offset from center of entity position
CollisionBodyCreation.setOffsetPosition(
Globals.clientSceneWrapper.getCollisionEngine(),
rigidBody,
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
if(physicsTemplate.getLinearFriction() != null){
collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
}
if(physicsTemplate.getRollingFriction() != null){
collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
}
ClientCollidableTree tree = new ClientCollidableTree(rVal,collidable,rigidBody);
PhysicsEntityUtils.setDBody(rVal,rigidBody);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotate(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW() //rotate
@ -69,14 +101,99 @@ public class PhysicsEntityUtils {
Globals.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
} break;
case "CUBE": {
//
//create dbody
rigidBody = CollisionBodyCreation.createCubeBody(
Globals.clientSceneWrapper.getCollisionEngine(),
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
Collidable.TYPE_CREATURE_BIT
);
if(physicsTemplate.getMass() != null){
CollisionBodyCreation.setBoxMass(
Globals.clientSceneWrapper.getCollisionEngine(),
rigidBody,
mass,
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
);
}
//
//set offset from center of entity position
CollisionBodyCreation.setOffsetPosition(
Globals.clientSceneWrapper.getCollisionEngine(),
rigidBody,
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
if(physicsTemplate.getLinearFriction() != null){
collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
}
if(physicsTemplate.getRollingFriction() != null){
collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
}
ClientCollidableTree tree = new ClientCollidableTree(rVal,collidable,rigidBody);
PhysicsEntityUtils.setDBody(rVal,rigidBody);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
if(physicsTemplate.isAngularlyStatic()){
Globals.clientSceneWrapper.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.CLIENT_COLLIDABLE_TREE, tree);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
Globals.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
} break;
case "CAPSULE": {
//
//create dbody
rigidBody = CollisionBodyCreation.createCapsuleBody(
Globals.clientSceneWrapper.getCollisionEngine(),
physicsTemplate.getDimension2(),
physicsTemplate.getDimension2() - physicsTemplate.getDimension1() - physicsTemplate.getDimension1(),
Collidable.TYPE_CREATURE_BIT
);
if(physicsTemplate.getMass() != null){
throw new UnsupportedOperationException("todo");
}
//
//set offset from center of entity position
CollisionBodyCreation.setOffsetPosition(
Globals.clientSceneWrapper.getCollisionEngine(),
rigidBody,
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
if(physicsTemplate.getLinearFriction() != null){
collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
}
if(physicsTemplate.getRollingFriction() != null){
collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
}
ClientCollidableTree tree = new ClientCollidableTree(rVal,collidable,rigidBody);
PhysicsEntityUtils.setDBody(rVal,rigidBody);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
@ -112,23 +229,55 @@ public class PhysicsEntityUtils {
public static void serverAttachCollidableTemplate(Realm realm, Entity rVal, CollidableTemplate physicsTemplate){
DBody rigidBody = null;
Collidable collidable;
float mass = 1.0f;
double mass = 1.0f;
if(physicsTemplate.getMass() != null){
mass = physicsTemplate.getMass();
}
switch(physicsTemplate.getType()){
case "CYLINDER": {
//
//create dbody
rigidBody = CollisionBodyCreation.createCylinderBody(
realm.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
Collidable.TYPE_CREATURE_BIT
);
if(physicsTemplate.getMass() != null){
CollisionBodyCreation.setCylinderMass(
realm.getCollisionEngine(),
rigidBody,
mass,
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
);
}
//
//set offset from entity center
CollisionBodyCreation.setOffsetPosition(
realm.getCollisionEngine(),
rigidBody,
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
if(physicsTemplate.getLinearFriction() != null){
collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
}
if(physicsTemplate.getRollingFriction() != null){
collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
}
ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
PhysicsEntityUtils.setDBody(rVal,rigidBody);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
@ -148,10 +297,99 @@ public class PhysicsEntityUtils {
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
} break;
case "CUBE": {
rigidBody = CollisionBodyCreation.createCubeBody(realm.getCollisionEngine(),new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),Collidable.TYPE_CREATURE_BIT);
//
//create dbody
rigidBody = CollisionBodyCreation.createCubeBody(
realm.getCollisionEngine(),
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
Collidable.TYPE_CREATURE_BIT
);
if(physicsTemplate.getMass() != null){
CollisionBodyCreation.setBoxMass(
realm.getCollisionEngine(),
rigidBody,
mass,
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
);
}
//
//set offset from entity center
CollisionBodyCreation.setOffsetPosition(
realm.getCollisionEngine(),
rigidBody,
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
if(physicsTemplate.getLinearFriction() != null){
collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
}
if(physicsTemplate.getRollingFriction() != null){
collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
}
ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
PhysicsEntityUtils.setDBody(rVal,rigidBody);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
if(physicsTemplate.isAngularlyStatic()){
realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
}
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
} break;
case "CAPSULE": {
//
//create dbody
rigidBody = CollisionBodyCreation.createCapsuleBody(
realm.getCollisionEngine(),
physicsTemplate.getDimension2(),
physicsTemplate.getDimension2() - physicsTemplate.getDimension1() - physicsTemplate.getDimension1(),
Collidable.TYPE_CREATURE_BIT
);
if(physicsTemplate.getMass() != null){
throw new UnsupportedOperationException("todo");
}
//
//set offset from entity center
CollisionBodyCreation.setOffsetPosition(
realm.getCollisionEngine(),
rigidBody,
new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
);
//
//create collidable and attach tracking
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
if(physicsTemplate.getLinearFriction() != null){
collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
}
if(physicsTemplate.getRollingFriction() != null){
collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
}
ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
PhysicsEntityUtils.setDBody(rVal,rigidBody);
//
//store data
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate

View File

@ -1,11 +1,12 @@
package electrosphere.collision;
import org.joml.Matrix3d;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.ode4j.math.DMatrix3;
import org.ode4j.math.DQuaternion;
import org.ode4j.math.DQuaternionC;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DMass;
import electrosphere.game.data.collidable.CollidableTemplate;
@ -67,6 +68,21 @@ public class PhysicsUtils {
public static DQuaternion jomlQuatToOdeQuat(Quaterniond quaternion){
return new DQuaternion(quaternion.w, quaternion.x, quaternion.y, quaternion.z);
}
/**
* Converts a joml quat to an ode quat
* @param quaternion The joml quat
* @return The ode quata
*/
public static DMatrix3 jomlQuatToOdeMat(Quaterniond quaternion){
Matrix3d rotMat = quaternion.get(new Matrix3d());
DMatrix3 mat = new DMatrix3(
rotMat.m00, rotMat.m10, rotMat.m20,
rotMat.m01, rotMat.m11, rotMat.m21,
rotMat.m02, rotMat.m12, rotMat.m22
);
return mat;
}
/**
* Sets the position + rotation of a body
@ -104,16 +120,5 @@ public class PhysicsUtils {
collisionEngine.setBodyTransform(body, template, position, rotation, scale);
}
/**
* Creates a mass in the physics space from the body and mass value input
* @param collisionEngine The collision engine to create the mass in
* @param body The DBody to give mass to
* @param mass The amount of mass to give to the DBody
* @return THe DMass wrapping the DBody with a given mass value
*/
public static DMass createMassFromBody(CollisionEngine collisionEngine, DBody body, double mass){
return collisionEngine.createDMass(mass, body);
}
}

View File

@ -21,6 +21,11 @@ public class Collidable {
//The impulses to be applied to this collidable
List<Impulse> impulses = new CopyOnWriteArrayList<Impulse>();
/**
* The params for the surface of this collidable when a collision occurs
*/
SurfaceParams surfaceParams;
//these should have corresponding category bits along with them
public static final String TYPE_STATIC = "static";
@ -61,6 +66,23 @@ public class Collidable {
this.parent = parent;
this.type = type;
this.parentTracksCollidable = parentTracksCollidable;
this.surfaceParams = new SurfaceParams();
}
/**
* Sets the surface params for the collidable
* @param surfaceParams The surface params
*/
public void setSurfaceParams(SurfaceParams surfaceParams){
this.surfaceParams = surfaceParams;
}
/**
* Gets the surface params for the collidable
* @return The surface params
*/
public SurfaceParams getSurfaceParams(){
return this.surfaceParams;
}
public List<Impulse> getImpulses() {

View File

@ -0,0 +1,160 @@
package electrosphere.collision.collidable;
import org.ode4j.ode.OdeConstants;
/**
* The surface params for the collidable
*/
public class SurfaceParams {
/**
* <p> The mode flags for the surface </p>
* <p> This must always be set. This is a combination of one or more of the following flags. </p>
* <p>
* Possible values:
* <ul>
* <li> dContactMu2 - If not set, use mu for both friction directions. If set, use mu for friction direction 1, use mu2 for friction direction 2. </li>
* <li> dContactFDir1 - If set, take fdir1 as friction direction 1, otherwise automatically compute friction direction 1 to be perpendicular to the contact normal (in which case its resulting orientation is unpredictable). </li>
* <li> dContactBounce - If set, the contact surface is bouncy, in other words the bodies will bounce off each other. The exact amount of bouncyness is controlled by the bounce parameter. </li>
* <li> dContactSoftERP - If set, the error reduction parameter of the contact normal can be set with the soft_erp parameter. This is useful to make surfaces soft. </li>
* <li> dContactSoftCFM - If set, the constraint force mixing parameter of the contact normal can be set with the soft_cfm parameter. This is useful to make surfaces soft. </li>
* <li> dContactMotion1 - If set, the contact surface is assumed to be moving independently of the motion of the bodies. This is kind of like a conveyor belt running over the surface. When this flag is set, motion1 defines the surface velocity in friction direction 1. </li>
* <li> dContactMotion2 - The same thing as above, but for friction direction 2. </li>
* <li> dContactMotionN - The same thing as above, but along the contact normal. </li>
* <li> dContactSlip1 - Force-dependent-slip (FDS) in friction direction 1. </li>
* <li> dContactSlip2 - Force-dependent-slip (FDS) in friction direction 2. </li>
* <li> dContactRolling - Enables rolling/spinning friction. </li>
* <li> dContactApprox1_1 - Use the friction pyramid approximation for friction direction 1. If this is not specified then the constant-force-limit approximation is used (and mu is a force limit). </li>
* <li> dContactApprox1_2 - Use the friction pyramid approximation for friction direction 2. If this is not specified then the constant-force-limit approximation is used (and mu is a force limit). </li>
* <li> dContactApprox1_N - Use the friction pyramid approximation for spinning (rolling around normal). </li>
* <li> dContactApprox1 - Equivalent to dContactApprox1_1, dContactApprox1_2 and dContactApprox1_N. </li>
* </ul>
* </p>
*/
int mode;
/**
* <p> Coulomb friction coefficient </p>
* <p> Ranges [0,infinity) </p>
* <p> 0 is a frictionless contact, dInfinity results in a contact that never slips. </p>
* <p> Note that frictionless contacts are less time consume to compute than ones with friction. </p>
* <p> <b> This must always be set. </b> </p>
*/
Double mu;
/**
* <p> Rolling friction coefficient around direction 1. </p>
*/
Double rho;
/**
* <p> Rolling friction coefficient around direction 2. </p>
*/
Double rho2;
/**
* <p> Rolling friction coefficient around the normal direction. </p>
*/
Double rhoN;
/**
* <p> Restitution parameter </p>
* <p> Ranges (0,1) </p>
* <p> 0 means the surfaces are not bouncy at all. 1 is maximum bounciness. </p>
* <p> <b> Note that mode must be set with dContactBounce. </b> </p>
*/
Double bounce;
/**
* <p> Minimum velocity to trigger a bounce </p>
* <p> All velocities below this threshold will effectively have bounce parameter of 0. </p>
* <p> <b> Note that mode must be set with ??put flat here??. </b> </p>
*/
Double bounceVel;
/**
* Constructor
*/
public SurfaceParams(){
mode = OdeConstants.dContactApprox1 & OdeConstants.dContactRolling & OdeConstants.dContactBounce;
mu = 10.0;
rho = 10.0;
rho2 = 10.0;
rhoN = 10.0;
bounce = 0.001;
bounceVel = 100.0;
}
/**
* Gets the mode for the surface
* @return The mode
*/
public int getMode(){
return mode;
}
/**
* Gets the mu for the surface
* @return The mu
*/
public Double getMu(){
return mu;
}
/**
* Gets the rho for the surface;
* @return The rho
*/
public Double getRho(){
return rho;
}
/**
* Gets the rho2 for the surface;
* @return The rho2
*/
public Double getRho2(){
return rho2;
}
/**
* Gets the rhoN for the surface;
* @return The rhoN
*/
public Double getRhoN(){
return rhoN;
}
/**
* Gets the bounce for the surface;
* @return The bounce
*/
public Double getBounce(){
return bounce;
}
/**
* Gets the bounce minimum velocity for the surface;
* @return The bounce minimum velocity
*/
public Double getBounceVel(){
return bounceVel;
}
/**
* Sets the rolling friction of the surface params
* @param friction The rolling friction
*/
public void setRollingFriction(double friction){
this.rho = this.rho2 = this.rhoN = friction;
}
/**
* Sets the lienar friction
* @param linearFriction The linear friction
*/
public void setLinearFriction(double linearFriction){
this.mu = linearFriction;
}
}

View File

@ -5,7 +5,6 @@ import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import java.util.concurrent.TimeUnit;
import org.graalvm.polyglot.HostAccess.Export;
import org.ode4j.ode.OdeHelper;
import electrosphere.audio.AudioEngine;

View File

@ -322,6 +322,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
}
CreatureUtils.setVelocity(parent, velocity);
//actually update
PhysicsEntityUtils.getDBody(parent).enable();
body.setLinearVel(
movementVector.x * velocity * Globals.timekeeper.getSimFrameTime(),
linearVelocity.get1(),
@ -353,6 +354,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
this.updateVelocity();
float velocity = this.getModifiedVelocity();
PhysicsEntityUtils.getDBody(parent).enable();
body.setLinearVel(
movementVector.x * velocity * Globals.timekeeper.getSimFrameTime(),
linearVelocity.get1(),
@ -400,6 +402,7 @@ public class ClientGroundMovementTree implements BehaviorTree {
}
CreatureUtils.setVelocity(parent, velocity);
}
PhysicsEntityUtils.getDBody(parent).enable();
body.setLinearVel(
movementVector.x * velocity * Globals.timekeeper.getSimFrameTime(),
linearVelocity.get1(),

View File

@ -272,6 +272,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
state = MovementTreeState.MOVE;
CreatureUtils.setVelocity(parent, velocity);
}
PhysicsEntityUtils.getDBody(parent).enable();
PhysicsEntityUtils.getDBody(parent).setLinearVel(
movementVector.x * velocity * Globals.timekeeper.getSimFrameTime(),
linearVelocity.get1(),
@ -317,6 +318,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
}
this.updateVelocity();
float velocity = this.getModifiedVelocity();
PhysicsEntityUtils.getDBody(parent).enable();
PhysicsEntityUtils.getDBody(parent).setLinearVel(
movementVector.x * velocity * Globals.timekeeper.getSimFrameTime(),
linearVelocity.get1(),
@ -383,6 +385,7 @@ public class ServerGroundMovementTree implements BehaviorTree {
// linearVelocity.get1(),
// movementVector.z * velocity * Globals.timekeeper.getSimFrameTime()
// );
PhysicsEntityUtils.getDBody(parent).enable();
PhysicsEntityUtils.getDBody(parent).setLinearVel(
movementVector.x * velocity * Globals.timekeeper.getSimFrameTime(),
linearVelocity.get1(),

View File

@ -332,6 +332,9 @@ public class CreatureUtils {
}
public static float getVelocity(Entity e){
if(!e.containsKey(EntityDataStrings.DATA_STRING_VELOCITY)){
return 0;
}
return (float)e.getData(EntityDataStrings.DATA_STRING_VELOCITY);
}

View File

@ -15,7 +15,6 @@ import electrosphere.game.data.foliage.type.model.FoliageTypeMap;
import electrosphere.game.data.item.type.model.ItemTypeMap;
import electrosphere.game.data.particle.ParticleDefinition;
import electrosphere.game.data.projectile.ProjectileTypeHolder;
import electrosphere.game.data.structure.type.model.StructureTypeMap;
import electrosphere.game.data.tutorial.HintDefinition;
import electrosphere.game.data.units.UnitDefinitionFile;
import electrosphere.game.data.units.UnitLoader;
@ -30,7 +29,6 @@ import electrosphere.util.FileUtils;
public class Config {
CreatureTypeLoader creatureTypeLoader;
StructureTypeMap structureTypeMap;
ItemTypeMap itemMap;
FoliageTypeMap foliageMap;
CommonEntityMap objectTypeLoader;
@ -67,7 +65,6 @@ public class Config {
Config config = new Config();
config.creatureTypeLoader = loadCreatureTypes("Data/entity/creatures.json");
config.itemMap = FileUtils.loadObjectFromAssetPath("Data/entity/items.json", ItemTypeMap.class);
config.structureTypeMap = FileUtils.loadObjectFromAssetPath("Data/entity/structures.json", StructureTypeMap.class);
config.foliageMap = FileUtils.loadObjectFromAssetPath("Data/entity/foliage.json", FoliageTypeMap.class);
config.objectTypeLoader = loadCommonEntityTypes("Data/entity/objects.json");
config.symbolMap = FileUtils.loadObjectFromAssetPath("Data/game/symbolism.json", SymbolMap.class);
@ -176,14 +173,6 @@ public class Config {
return creatureTypeLoader;
}
/**
* Gets the data on all structure entities in memory
* @return The structure definitions
*/
public StructureTypeMap getStructureTypeMap() {
return structureTypeMap;
}
/**
* Gets the data on all item types in memory
* @return the data on all items

View File

@ -5,6 +5,9 @@ package electrosphere.game.data.collidable;
*/
public class CollidableTemplate {
/**
* The primitive shape type
*/
String type;
float dimension1;
@ -20,11 +23,30 @@ public class CollidableTemplate {
float offsetY;
float offsetZ;
/**
* The mass of the body
*/
Double mass;
/**
* The linear friction of the body
*/
Double linearFriction;
/**
* The rolling friction of the body (ie if it's a sphere, what's the friction keeping it from spinning)
*/
Double rollingFriction;
/**
* Controls whether the body can rotate or not
*/
boolean angularlyStatic;
/**
* The primitive shape type
* @return The primitive shape
*/
public String getType() {
return type;
}
@ -69,6 +91,30 @@ public class CollidableTemplate {
return offsetZ;
}
/**
* Gets the mass of the body
* @return The mass
*/
public Double getMass(){
return mass;
}
/**
* Gets the linear friction
* @return The linear friction
*/
public Double getLinearFriction(){
return linearFriction;
}
/**
* Gets the rolling friction (ie if it's a sphere, what's the friction keeping it from spinning)
* @return The rolling friction
*/
public Double getRollingFriction(){
return rollingFriction;
}
/**
* Gets if the body should always be allowed to rotate or not
* @return true if should always be allowed to rotate, false otherwise

View File

@ -1,73 +0,0 @@
package electrosphere.game.data.structure.type.model;
/**
* Collidable data
*/
public class CollisionObjectTemplate {
String type;
public static final String TYPE_CUBE = "CUBE";
public static final String TYPE_PLANE = "PLANE";
float positionX;
float positionY;
float positionZ;
float scaleX;
float scaleY;
float scaleZ;
float rotationW;
float rotationX;
float rotationY;
float rotationZ;
public String getType() {
return type;
}
public float getPositionX() {
return positionX;
}
public float getPositionY() {
return positionY;
}
public float getPositionZ() {
return positionZ;
}
public float getScaleX() {
return scaleX;
}
public float getScaleY() {
return scaleY;
}
public float getScaleZ() {
return scaleZ;
}
public float getRotationW() {
return rotationW;
}
public float getRotationX() {
return rotationX;
}
public float getRotationY() {
return rotationY;
}
public float getRotationZ() {
return rotationZ;
}
}

View File

@ -1,34 +0,0 @@
package electrosphere.game.data.structure.type.model;
import java.util.List;
/**
* Structure data
*/
public class StructureType {
String modelPath;
String name;
float radius;
List<CollisionObjectTemplate> collision;
public String getModelPath() {
return modelPath;
}
public List<CollisionObjectTemplate> getCollision() {
return collision;
}
public String getName() {
return name;
}
public float getRadius() {
return radius;
}
}

View File

@ -1,27 +0,0 @@
package electrosphere.game.data.structure.type.model;
import java.util.List;
/**
* Map of name of structure to data about said structure
*/
public class StructureTypeMap {
List<StructureType> structures;
public List<StructureType> getStructures() {
return structures;
}
public StructureType getType(String name){
StructureType rVal = null;
for(StructureType type : structures){
if(type.getName().equals(name)){
rVal = type;
break;
}
}
return rVal;
}
}

View File

@ -1,7 +1,6 @@
package electrosphere.game.server.structure.virtual;
import electrosphere.engine.Globals;
import electrosphere.game.data.structure.type.model.StructureType;
import electrosphere.game.server.character.Character;
import electrosphere.server.datacell.Realm;
@ -41,15 +40,15 @@ public class VirtualStructureUtils {
}
public static boolean validStructurePlacementPosition(float posX, float posY, String type){
StructureType toPlaceType = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);
Vector2f toPlacePos = new Vector2f(posX, posY);
for(Structure virtualStruct : Globals.macroData.getStructures()){
StructureType existantType = Globals.gameConfigCurrent.getStructureTypeMap().getType(virtualStruct.getType());
Vector2f existantPos = new Vector2f(virtualStruct.getLocationX(),virtualStruct.getLocationY());
if(existantPos.distance(toPlacePos) < toPlaceType.getRadius() + existantType.getRadius()){
return false;
}
}
// StructureType toPlaceType = Globals.gameConfigCurrent.getStructureTypeMap().getType(type);
// Vector2f toPlacePos = new Vector2f(posX, posY);
// for(Structure virtualStruct : Globals.macroData.getStructures()){
// StructureType existantType = Globals.gameConfigCurrent.getStructureTypeMap().getType(virtualStruct.getType());
// Vector2f existantPos = new Vector2f(virtualStruct.getLocationX(),virtualStruct.getLocationY());
// if(existantPos.distance(toPlacePos) < toPlaceType.getRadius() + existantType.getRadius()){
// return false;
// }
// }
return true;
}

View File

@ -562,10 +562,13 @@ public class ImGuiEntityMacros {
ImGui.text("Velocity: " + CreatureUtils.getVelocity(detailViewEntity));
}
//synchronized data
if(Globals.clientSceneWrapper.getScene().getEntityFromId(detailViewEntity.getId()) != null){
if(
Globals.clientSceneWrapper.getScene().getEntityFromId(detailViewEntity.getId()) != null &&
Globals.clientSceneWrapper.mapClientToServerId(detailViewEntity.getId()) != -1
){
//detailViewEntity is a client entity
//get server entity
int serverIdForClientEntity = Globals .clientSceneWrapper.mapClientToServerId(detailViewEntity.getId());
int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(detailViewEntity.getId());
Entity serverEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity);
DBody serverPhysicsBody = PhysicsEntityUtils.getDBody(serverEntity);
if(serverPhysicsBody != null){