From 3c10c0bf85c1c6e95ed3600ef8c328aa8f19250d Mon Sep 17 00:00:00 2001 From: austin Date: Tue, 29 Mar 2022 20:27:54 -0400 Subject: [PATCH] Stab at rigid body rotations --- .../electrosphere/engine/LoadingThread.java | 15 +++-- .../entity/EntityDataStrings.java | 2 + .../state/collidable/CollidableTree.java | 66 +++++++++++++++++-- .../entity/state/collidable/Impulse.java | 8 ++- .../entity/state/gravity/GravityTree.java | 2 +- .../state/movement/GroundMovementTree.java | 12 ++-- .../types/collision/CollisionObjUtils.java | 61 ++++++++++++++++- .../entity/types/creature/CreatureUtils.java | 47 +++++++++++-- .../entity/types/item/ItemUtils.java | 23 +++++++ .../game/collision/CollisionEngine.java | 30 +++++---- .../game/collision/PhysicsUtils.java | 4 +- .../game/collision/collidable/Collidable.java | 4 +- .../renderer/RenderingEngine.java | 1 + 13 files changed, 237 insertions(+), 38 deletions(-) diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index a44680a1..6e6fa1e1 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -675,19 +675,24 @@ public class LoadingThread extends Thread { // MindlessAttacker.attachToCreature(goblin); // OpportunisticAttacker.attachToCreature(goblin); + //sword Entity sword = ItemUtils.spawnBasicItem("Katana"); EntityUtils.getPosition(sword).set(new Vector3f(1,0.4f,2)); + EntityUtils.getRotation(sword).set(new Quaternionf().rotationY(0.6f)); + // Entity shorts = ItemUtils.spawnBasicItem("boots1"); // EntityUtils.getPosition(shorts).set(new Vector3f(2,0.1f,2)); // // Entity hair = ItemUtils.spawnBasicItem("hairshort1"); // // EntityUtils.getPosition(hair).set(new Vector3f(2,0.1f,1)); - Entity bow = ItemUtils.spawnBasicItem("bow1"); - EntityUtils.getPosition(bow).set(new Vector3f(2,0.1f,1)); + + + // Entity bow = ItemUtils.spawnBasicItem("bow1"); + // EntityUtils.getPosition(bow).set(new Vector3f(2,0.1f,1)); //crate - Entity crate = EntityUtils.spawnDrawableEntity("Models/crate2.fbx"); - EntityUtils.getPosition(crate).set(5,0.5,5); - EntityUtils.getScale(crate).set(new Vector3f(0.5f)); + // Entity crate = EntityUtils.spawnDrawableEntity("Models/crate2.fbx"); + // EntityUtils.getPosition(crate).set(5,0.5,5); + // EntityUtils.getScale(crate).set(new Vector3f(0.5f)); // //center flame // Entity fire = ParticleUtils.spawnStaticBillboardParticle(); diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java index bce356b9..192be680 100644 --- a/src/main/java/electrosphere/entity/EntityDataStrings.java +++ b/src/main/java/electrosphere/entity/EntityDataStrings.java @@ -100,6 +100,8 @@ public class EntityDataStrings { public static final String PHYSICS_COLLISION_BODY_OFFSET = "physicsRigidBodyOffset"; public static final String PHYSICS_COLLIDABLE = "physicsCollidable"; public static final String PHYSICS_MODEL_TEMPLATE = "physicsModelTemplate"; + public static final String PHYSICS_MASS = "physicsMass"; + public static final String PHYSICS_INVERSE_INERTIA_TENSOR = "physicsInverseInertiaTensor"; /* Gravity Entity diff --git a/src/main/java/electrosphere/entity/state/collidable/CollidableTree.java b/src/main/java/electrosphere/entity/state/collidable/CollidableTree.java index 0fe28b2a..1e7f6997 100644 --- a/src/main/java/electrosphere/entity/state/collidable/CollidableTree.java +++ b/src/main/java/electrosphere/entity/state/collidable/CollidableTree.java @@ -5,13 +5,20 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.gravity.GravityTree; +import electrosphere.entity.types.collision.CollisionObjUtils; +import electrosphere.entity.types.creature.CreatureUtils; +import electrosphere.entity.types.item.ItemUtils; import electrosphere.game.collision.PhysicsUtils; import electrosphere.game.collision.collidable.Collidable; import electrosphere.game.data.creature.type.CollidableTemplate; import electrosphere.main.Globals; + +import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3d; import org.joml.Vector3f; +import org.joml.Vector4d; +import org.joml.Vector4f; /** * @@ -22,6 +29,8 @@ public class CollidableTree { Entity parent; CollisionObject body; Collidable collidable; + // Quaternionf angularVelocity = new Quaternionf(0,0,0,1); + Vector4d cumulativeTorque = new Vector4d(0,0,0,0); @@ -35,6 +44,7 @@ public class CollidableTree { public void simulate(){ Vector3d position = EntityUtils.getPosition(parent); Quaternionf rotation = EntityUtils.getRotation(parent); + Matrix4f inverseInertiaTensor = CollisionObjUtils.getInverseInertiaTensor(parent); Vector3d offsetVector = new Vector3d(); Vector3d newPosition = new Vector3d(position); javax.vecmath.Matrix4f bodyTransformMatrix; @@ -60,12 +70,60 @@ public class CollidableTree { ((GravityTree)parent.getData(EntityDataStrings.GRAVITY_TREE)).start(); } } - -// if(impulse.type.matches("movement")){ -// System.out.println("Impulse force: " + impulseForce); -// } + if( + impulse.getCollisionPoint().length() > 0 && + !Double.isNaN(impulse.getCollisionPoint().x) && + !Double.isNaN(impulse.getCollisionPoint().y) && + !Double.isNaN(impulse.getCollisionPoint().z) && + !Double.isNaN(impulse.getDirection().x) && + !Double.isNaN(impulse.getDirection().y) && + !Double.isNaN(impulse.getDirection().z) + ){ + Vector3d collisionPoint = new Vector3d(impulse.getCollisionPoint()).normalize(); + Vector3d forceDir = new Vector3d(impulse.getDirection()).normalize(); + Vector3d torqueVec = new Vector3d(collisionPoint).cross(forceDir).normalize(); + double torqueMag = Math.abs(impulse.force); + // double torqueMag = impulse.getCollisionPoint().length() * impulse.getDirection().length(); + // if(impulse.type.matches(Collidable.TYPE_ITEM) && ItemUtils.isItem(parent)){ + // // System.out.println(rotation); + // if(impulse.collisionPoint.x < 0){ + // // System.out.println("Impulse collision point: " + impulse.getCollisionPoint() + " direction: " + impulse.getDirection() + " => " + new Vector3d(impulse.getCollisionPoint()).cross(impulse.getDirection())); + // cumulativeTorque.add(new Vector3d(impulse.getCollisionPoint()).cross(impulse.getDirection())); + // } + // } else { + // // angularVelocity.add(new Vector3d(impulse.getCollisionPoint()).cross(impulse.getDirection()),1.0); + // cumulativeTorque.add(new Vector3d(impulse.getCollisionPoint()).cross(impulse.getDirection())); + // } + // if(impulse.type.matches(Collidable.TYPE_ITEM)){ + // System.out.println("Impulse: " + torqueVec + " " + torqueMag); + // } + cumulativeTorque.add(new Vector4d(torqueVec.x,torqueVec.y,torqueVec.z,torqueMag)); + } offsetVector.add(impulseForce); } + // if(ItemUtils.isItem(parent) && cumulativeTorque.w > 0.001){ + // System.out.println(cumulativeTorque); + // } + //friction + // if(cumulativeTorque.w > 0.001){ + // Vector3d normalizedTorqueDir = new Vector3d(cumulativeTorque.x,cumulativeTorque.y,cumulativeTorque.z).normalize(); + // double newMag = cumulativeTorque.w * 0.9; + // cumulativeTorque.set(normalizedTorqueDir.x,normalizedTorqueDir.y,normalizedTorqueDir.z,newMag); + // } + if(inverseInertiaTensor != null && cumulativeTorque.w > 0.01){ + Vector4f angularMomentum = inverseInertiaTensor.transform(new Vector4f((float)cumulativeTorque.x,(float)cumulativeTorque.x,(float)cumulativeTorque.x,(float)cumulativeTorque.w)); + // Quaternionf nextRotation = new Quaternionf(rotation).mul(new Quaternionf(angularMomentum.x,angularMomentum.y,angularMomentum.z,angularMomentum.w).scale(0.001f)).normalize(); + // rotation = nextRotation; + // rotation.mul(new Quaternionf((float)angularMomentum.x,(float)angularMomentum.y,(float)angularMomentum.z,(float)angularMomentum.w / 0.01f)); + if(ItemUtils.isItem(parent)){ + System.out.println("cumulative quat: " + cumulativeTorque); + } + rotation.x = rotation.x + rotation.x * (float)cumulativeTorque.x * 0.001f; + rotation.y = rotation.y + rotation.y * (float)cumulativeTorque.y * 0.001f; + rotation.z = rotation.z + rotation.z * (float)cumulativeTorque.z * 0.001f; + rotation.w = rotation.w + rotation.w * (float)cumulativeTorque.w * 0.001f; + rotation.normalize(); + } //the reasoning here is that if we have something above something else and it's pushing it into the terrain, //we should instead just not push into terrain and push along terrain diff --git a/src/main/java/electrosphere/entity/state/collidable/Impulse.java b/src/main/java/electrosphere/entity/state/collidable/Impulse.java index 3ab508de..4adae026 100644 --- a/src/main/java/electrosphere/entity/state/collidable/Impulse.java +++ b/src/main/java/electrosphere/entity/state/collidable/Impulse.java @@ -10,12 +10,14 @@ import org.joml.Vector3f; public class Impulse { Vector3d direction; + Vector3d collisionPoint; double force; String type; - public Impulse(Vector3d dir, double force, String type){ + public Impulse(Vector3d dir, Vector3d collisionPoint, double force, String type){ this.force = force; this.direction = dir; + this.collisionPoint = collisionPoint; this.type = type; } @@ -30,6 +32,10 @@ public class Impulse { public String getType() { return type; } + + public Vector3d getCollisionPoint() { + return collisionPoint; + } } diff --git a/src/main/java/electrosphere/entity/state/gravity/GravityTree.java b/src/main/java/electrosphere/entity/state/gravity/GravityTree.java index 4faecbcc..bda6aa6b 100644 --- a/src/main/java/electrosphere/entity/state/gravity/GravityTree.java +++ b/src/main/java/electrosphere/entity/state/gravity/GravityTree.java @@ -130,7 +130,7 @@ public class GravityTree { if(hitFraction < 0){ hitFraction = 1; } - collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity")); + collidable.addImpulse(new Impulse(new Vector3d(0,-1,0), new Vector3d(0,0,0), gravityDif * hitFraction,"gravity")); // System.out.println(hitFraction); // bodyTransformMatrix = new javax.vecmath.Matrix4f(PhysicsUtils.jomlToVecmathQuaternionf(rotation),PhysicsUtils.jomlToVecmathVector3f(new Vector3f((float)position.x,(float)position.y,(float)position.z)),1.0f); // body.setWorldTransform(new electrosphere.linearmath.Transform(bodyTransformMatrix)); diff --git a/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java b/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java index bc2e9576..7597e149 100644 --- a/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java +++ b/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java @@ -235,7 +235,7 @@ public class GroundMovementTree { } CreatureUtils.setVelocity(parent, velocity); // body.applyCentralForce(PhysicsUtils.jomlToVecmathVector3f(new Vector3f(movementVector.x,0,movementVector.z).normalize().mul(velocity))); - EntityUtils.getRotation(parent).set(movementQuaternion); + // EntityUtils.getRotation(parent).set(movementQuaternion); // //move the entity // newPosition = new Vector3d(position).add(new Vector3d(movementVector).mul(velocity).mul(Main.deltaTime)); // //check/update if collision @@ -243,7 +243,7 @@ public class GroundMovementTree { // newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.commonWorldData, parent, newPosition); // } // //actually update - collidable.addImpulse(new Impulse(new Vector3d(movementVector), velocity * Main.deltaTime, "movement")); + collidable.addImpulse(new Impulse(new Vector3d(movementVector), new Vector3d(0,0,0), velocity * Main.deltaTime, "movement")); // position.set(newPosition); rotation.set(movementQuaternion); @@ -312,14 +312,14 @@ public class GroundMovementTree { CreatureUtils.setVelocity(parent, velocity); } // body.applyCentralForce(PhysicsUtils.jomlToVecmathVector3f(force)); - EntityUtils.getRotation(parent).set(movementQuaternion); + // EntityUtils.getRotation(parent).set(movementQuaternion); //check if can move forward (collision engine) //if can, move forward by entity movement stats // newPosition = new Vector3d(position).add(new Vector3d(movementVector).mul(velocity).mul(Main.deltaTime)); // if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.commonWorldData, parent, newPosition)){ // newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.commonWorldData, parent, newPosition); // } - collidable.addImpulse(new Impulse(new Vector3d(movementVector), velocity * Main.deltaTime, "movement")); + collidable.addImpulse(new Impulse(new Vector3d(movementVector), new Vector3d(0,0,0), velocity * Main.deltaTime, "movement")); // position.set(newPosition); rotation.set(movementQuaternion); @@ -397,13 +397,13 @@ public class GroundMovementTree { } CreatureUtils.setVelocity(parent, velocity); // body.applyCentralForce(PhysicsUtils.jomlToVecmathVector3f(new Vector3f(movementVector).mul(-1.0f).normalize().mul(velocity))); - EntityUtils.getRotation(parent).rotationTo(new Vector3f(0,0,1), new Vector3f((float)movementVector.x,(float)movementVector.y,(float)movementVector.z)); + // EntityUtils.getRotation(parent).rotationTo(new Vector3f(0,0,1), new Vector3f((float)movementVector.x,(float)movementVector.y,(float)movementVector.z)); //move the entity // newPosition = new Vector3d(position).add(new Vector3d(movementVector).mul(velocity).mul(Main.deltaTime)); // if(!Globals.collisionEngine.checkCanOccupyPosition(Globals.commonWorldData, parent, newPosition)){ // newPosition = Globals.collisionEngine.suggestMovementPosition(Globals.commonWorldData, parent, newPosition); // } - collidable.addImpulse(new Impulse(new Vector3d(movementVector), velocity * Main.deltaTime, "movement")); + collidable.addImpulse(new Impulse(new Vector3d(movementVector), new Vector3d(0,0,0), velocity * Main.deltaTime, "movement")); // position.set(newPosition); rotation.set(movementQuaternion); diff --git a/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java b/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java index f596ddf3..ba28d4da 100644 --- a/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java +++ b/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java @@ -9,6 +9,8 @@ import electrosphere.entity.types.attach.AttachUtils; import electrosphere.game.collision.PhysicsUtils; import electrosphere.game.collision.collidable.Collidable; import electrosphere.main.Globals; + +import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3d; import org.joml.Vector3f; @@ -18,9 +20,11 @@ import org.joml.Vector3f; * @author amaterasu */ public class CollisionObjUtils { - + public static Entity spawnCollisionPlane(Vector3f scale, Vector3f position, Quaternionf rotation){ Entity rVal = new Entity(); + + float mass = 1.0f; CollisionObject planeObject = PhysicsUtils.getPlaneObject(scale); javax.vecmath.Matrix4f planeTransform = new javax.vecmath.Matrix4f( @@ -38,6 +42,11 @@ public class CollisionObjUtils { rVal.putData(EntityDataStrings.DATA_STRING_SCALE, scale); rVal.putData(EntityDataStrings.COLLISION_ENTITY_COLLISION_OBJECT, planeObject); rVal.putData(EntityDataStrings.COLLISION_ENTITY_COLLIDABLE, collidable); + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://scienceworld.wolfram.com/physics/MomentofInertiaCylinder.html + Matrix4f inertiaTensor = new Matrix4f().zero(); + rVal.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor); rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); Globals.entityManager.registerEntity(rVal); @@ -47,6 +56,8 @@ public class CollisionObjUtils { public static Entity spawnCollisionCube(Vector3f scale, Vector3f position, Quaternionf rotation){ Entity rVal = new Entity(); + + float mass = 1.0f; CollisionObject cubeObject = PhysicsUtils.getCubeObject(scale); javax.vecmath.Matrix4f planeTransform = new javax.vecmath.Matrix4f( @@ -64,6 +75,11 @@ public class CollisionObjUtils { rVal.putData(EntityDataStrings.DATA_STRING_SCALE, scale); rVal.putData(EntityDataStrings.COLLISION_ENTITY_COLLISION_OBJECT, cubeObject); rVal.putData(EntityDataStrings.COLLISION_ENTITY_COLLIDABLE, collidable); + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://hepweb.ucsd.edu/ph110b/110b_notes/node26.html + Matrix4f inertiaTensor = new Matrix4f().identity().scale(mass * scale.x * scale.x / 6.0f).m33(1); + rVal.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); Globals.entityManager.registerEntity(rVal); @@ -72,6 +88,8 @@ public class CollisionObjUtils { public static Entity spawnCollisionCylinder(Vector3f scale, Vector3f position, Quaternionf rotation){ Entity rVal = new Entity(); + + float mass = 1.0f; CollisionObject cubeObject = PhysicsUtils.getCylinderObject(scale); javax.vecmath.Matrix4f planeTransform = new javax.vecmath.Matrix4f( @@ -89,6 +107,14 @@ public class CollisionObjUtils { rVal.putData(EntityDataStrings.DATA_STRING_SCALE, scale); rVal.putData(EntityDataStrings.COLLISION_ENTITY_COLLISION_OBJECT, cubeObject); rVal.putData(EntityDataStrings.COLLISION_ENTITY_COLLIDABLE, collidable); + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://scienceworld.wolfram.com/physics/MomentofInertiaCylinder.html + Matrix4f inertiaTensor = new Matrix4f(); + inertiaTensor.m00(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m11(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m22(mass * scale.x * scale.x / 2.0f); + rVal.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); Globals.entityManager.registerEntity(rVal); @@ -100,6 +126,13 @@ public class CollisionObjUtils { Entity rVal = spawnCollisionPlane(scale, position, rotation); AttachUtils.attachEntityToEntity(parent, rVal); + + float mass = 1.0f; + parent.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://scienceworld.wolfram.com/physics/MomentofInertiaCylinder.html + Matrix4f inertiaTensor = new Matrix4f().zero(); + parent.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor); return rVal; } @@ -108,6 +141,13 @@ public class CollisionObjUtils { Entity rVal = spawnCollisionCube(scale, position, rotation); AttachUtils.attachEntityToEntity(parent, rVal); + + float mass = 1.0f; + parent.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://hepweb.ucsd.edu/ph110b/110b_notes/node26.html + Matrix4f inertiaTensor = new Matrix4f().identity().scale(mass * scale.x * scale.x / 6.0f).m33(1); + parent.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); return rVal; } @@ -116,6 +156,16 @@ public class CollisionObjUtils { Entity rVal = spawnCollisionCylinder(scale, position, rotation); AttachUtils.attachEntityToEntity(parent, rVal); + + float mass = 1.0f; + parent.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://scienceworld.wolfram.com/physics/MomentofInertiaCylinder.html + Matrix4f inertiaTensor = new Matrix4f(); + inertiaTensor.m00(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m11(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m22(mass * scale.x * scale.x / 2.0f); + parent.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); return rVal; } @@ -134,5 +184,14 @@ public class CollisionObjUtils { public static Collidable getCollidable(Entity e){ return (Collidable)e.getData(EntityDataStrings.PHYSICS_COLLIDABLE); } + + public static float getMass(Entity e){ + return (float)e.getData(EntityDataStrings.PHYSICS_MASS); + } + + public static Matrix4f getInverseInertiaTensor(Entity e){ + return (Matrix4f)e.getData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR); + } + } diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java index 0ebad6a4..0e3986c9 100644 --- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java +++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java @@ -47,6 +47,7 @@ import electrosphere.util.ModelLoader; import java.util.LinkedList; import java.util.List; +import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3d; import org.joml.Vector3f; @@ -97,22 +98,56 @@ public class CreatureUtils { } if(rawType.getCollidable() != null){ CollidableTemplate physicsTemplate = rawType.getCollidable(); + CollisionObject rigidBody; + Collidable collidable; + float mass = 1.0f; + Matrix4f inertiaTensor; + Vector3f scale; switch(physicsTemplate.getType()){ case "CYLINDER": - CollisionObject rigidBody = PhysicsUtils.getCylinderObject(new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3())); - Collidable collidable = new Collidable(rVal, Collidable.TYPE_CREATURE); + rigidBody = PhysicsUtils.getCylinderObject(new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3())); + collidable = new Collidable(rVal, Collidable.TYPE_ITEM); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(physicsTemplate.getOffsetX(),physicsTemplate.getOffsetY(),physicsTemplate.getOffsetZ())); rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); - rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE,collidable); + rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.COLLIDABLE_TREE, new CollidableTree(rVal,collidable,rigidBody)); + + scale = new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()); + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://scienceworld.wolfram.com/physics/MomentofInertiaCylinder.html + inertiaTensor = new Matrix4f(); + inertiaTensor.m00(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m11(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m22(mass * scale.x * scale.x / 2.0f); + rVal.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); + + Globals.collisionEngine.registerPhysicsEntity(rVal); + Globals.collisionEngine.registerDynamicPhysicsEntity(rVal); + Globals.collisionEngine.registerCollisionObject(rigidBody, collidable); + Globals.entityManager.registerCollidableEntity(rVal); + break; + case "CUBE": + rigidBody = PhysicsUtils.getCubeObject(new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3())); + collidable = new Collidable(rVal, Collidable.TYPE_ITEM); + rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody); + rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(physicsTemplate.getOffsetX(),physicsTemplate.getOffsetY(),physicsTemplate.getOffsetZ())); + rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); + rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); + rVal.putData(EntityDataStrings.COLLIDABLE_TREE, new CollidableTree(rVal,collidable,rigidBody)); + + scale = new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()); + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://hepweb.ucsd.edu/ph110b/110b_notes/node26.html + inertiaTensor = new Matrix4f().identity().scale(mass * scale.x * scale.x / 6.0f).m33(1); + rVal.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); + Globals.collisionEngine.registerPhysicsEntity(rVal); Globals.collisionEngine.registerDynamicPhysicsEntity(rVal); Globals.collisionEngine.registerCollisionObject(rigidBody, collidable); Globals.entityManager.registerCollidableEntity(rVal); -// if(rVal.getDataKeys().contains(EntityDataStrings.DATA_STRING_MOVEMENT_BT)){ -// CreatureUtils.getEntityMovementTree(rVal).setCollisionObject(rigidBody, collidable); -// } break; } } diff --git a/src/main/java/electrosphere/entity/types/item/ItemUtils.java b/src/main/java/electrosphere/entity/types/item/ItemUtils.java index 65758f90..f2c95677 100644 --- a/src/main/java/electrosphere/entity/types/item/ItemUtils.java +++ b/src/main/java/electrosphere/entity/types/item/ItemUtils.java @@ -29,6 +29,7 @@ import electrosphere.renderer.actor.ActorUtils; import java.util.LinkedList; import java.util.List; +import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3d; import org.joml.Vector3f; @@ -63,6 +64,9 @@ public class ItemUtils { CollidableTemplate physicsTemplate = item.getCollidable(); CollisionObject rigidBody; Collidable collidable; + float mass = 1.0f; + Matrix4f inertiaTensor; + Vector3f scale; switch(physicsTemplate.getType()){ case "CYLINDER": rigidBody = PhysicsUtils.getCylinderObject(new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3())); @@ -72,6 +76,17 @@ public class ItemUtils { rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.COLLIDABLE_TREE, new CollidableTree(rVal,collidable,rigidBody)); + + scale = new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()); + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://scienceworld.wolfram.com/physics/MomentofInertiaCylinder.html + inertiaTensor = new Matrix4f(); + inertiaTensor.m00(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m11(mass * scale.y * scale.y / 12.0f + mass * scale.x * scale.x / 4.0f); + inertiaTensor.m22(mass * scale.x * scale.x / 2.0f); + rVal.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); + Globals.collisionEngine.registerPhysicsEntity(rVal); Globals.collisionEngine.registerDynamicPhysicsEntity(rVal); Globals.collisionEngine.registerCollisionObject(rigidBody, collidable); @@ -85,6 +100,14 @@ public class ItemUtils { rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate); rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable); rVal.putData(EntityDataStrings.COLLIDABLE_TREE, new CollidableTree(rVal,collidable,rigidBody)); + + scale = new Vector3f(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()); + rVal.putData(EntityDataStrings.PHYSICS_MASS, mass); + //inertia tensor + //https://hepweb.ucsd.edu/ph110b/110b_notes/node26.html + inertiaTensor = new Matrix4f().identity().scale(mass * scale.x * scale.x / 6.0f).m33(1); + rVal.putData(EntityDataStrings.PHYSICS_INVERSE_INERTIA_TENSOR, inertiaTensor.invert()); + Globals.collisionEngine.registerPhysicsEntity(rVal); Globals.collisionEngine.registerDynamicPhysicsEntity(rVal); Globals.collisionEngine.registerCollisionObject(rigidBody, collidable); diff --git a/src/main/java/electrosphere/game/collision/CollisionEngine.java b/src/main/java/electrosphere/game/collision/CollisionEngine.java index 4b9c8c25..495a1b12 100644 --- a/src/main/java/electrosphere/game/collision/CollisionEngine.java +++ b/src/main/java/electrosphere/game/collision/CollisionEngine.java @@ -32,6 +32,8 @@ import electrosphere.game.collision.collidable.Collidable; import static electrosphere.main.Main.deltaTime; import java.util.ArrayList; import java.util.List; + +import org.joml.Quaternionf; import org.joml.Vector3d; import org.joml.Vector3f; @@ -86,6 +88,8 @@ public class CollisionEngine { Collidable physicsObject2 = (Collidable)object2.getUserPointer(); boolean hit = false; Vector3d normal = null; + Vector3d localPosition1 = null; + Vector3d localPosition2 = null; float magnitude = 0.0f; for (int j = 0; j < manifold.getNumContacts(); j++) { ManifoldPoint contactPoint = manifold.getContactPoint(j); @@ -96,12 +100,14 @@ public class CollisionEngine { hit = true; // System.out.println(contactPoint.positionWorldOnA + " " + contactPoint.positionWorldOnB); normal = new Vector3d(contactPoint.normalWorldOnB.x,contactPoint.normalWorldOnB.y,contactPoint.normalWorldOnB.z); + localPosition1 = new Vector3d(contactPoint.localPointA.x,contactPoint.localPointA.y,contactPoint.localPointA.z); + localPosition2 = new Vector3d(contactPoint.localPointB.x,contactPoint.localPointB.y,contactPoint.localPointB.z); break; } } if (hit) { - resolveCollision(physicsObject1,physicsObject2, normal, magnitude); - resolveCollision(physicsObject2,physicsObject1, new Vector3d(normal).mul(-1.0), magnitude); + resolveCollision(physicsObject1,physicsObject2, normal, localPosition1, magnitude); + resolveCollision(physicsObject2,physicsObject1, new Vector3d(normal).mul(-1.0), localPosition2, magnitude); // System.out.println("HIT + " + normal); // Collision happened between physicsObject1 and physicsObject2. Collision normal is in variable 'normal'. } @@ -116,7 +122,7 @@ public class CollisionEngine { } - public static void resolveCollision(Collidable impactor, Collidable receiver, Vector3d normal, float magnitude){ + public static void resolveCollision(Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, float magnitude){ switch(receiver.getType()){ case Collidable.TYPE_CREATURE: switch(impactor.getType()){ @@ -128,19 +134,19 @@ public class CollisionEngine { normal.x = 0; normal.z = 0; } - receiver.addImpulse(new Impulse(normal, magnitude * 2, Collidable.TYPE_TERRAIN)); + receiver.addImpulse(new Impulse(normal, localPosition, magnitude * 2, Collidable.TYPE_TERRAIN)); break; case Collidable.TYPE_CREATURE: - receiver.addImpulse(new Impulse(normal, magnitude, Collidable.TYPE_CREATURE)); + receiver.addImpulse(new Impulse(normal, localPosition, magnitude, Collidable.TYPE_CREATURE)); break; case Collidable.TYPE_STRUCTURE: // float realMag = 1f/(float)Math.pow(0.1, magnitude); // System.out.println(normal + " - " + realMag); - receiver.addImpulse(new Impulse(normal, magnitude, Collidable.TYPE_STRUCTURE)); + receiver.addImpulse(new Impulse(normal, localPosition, magnitude, Collidable.TYPE_STRUCTURE)); // System.out.println("Structure-creature collision"); break; case Collidable.TYPE_ITEM: - receiver.addImpulse(new Impulse(normal, magnitude * 0.5, Collidable.TYPE_ITEM)); + receiver.addImpulse(new Impulse(normal, localPosition, magnitude * 0.5, Collidable.TYPE_ITEM)); break; } break; @@ -154,19 +160,19 @@ public class CollisionEngine { normal.x = 0; normal.z = 0; } - receiver.addImpulse(new Impulse(normal, magnitude * 2, Collidable.TYPE_TERRAIN)); + receiver.addImpulse(new Impulse(normal, localPosition, magnitude * 2, Collidable.TYPE_TERRAIN)); break; case Collidable.TYPE_CREATURE: - receiver.addImpulse(new Impulse(normal, Math.min(magnitude * 0.5,0.5), Collidable.TYPE_CREATURE)); + receiver.addImpulse(new Impulse(normal, localPosition, Math.min(magnitude * 0.5,0.5), Collidable.TYPE_CREATURE)); break; case Collidable.TYPE_STRUCTURE: // float realMag = 1f/(float)Math.pow(0.1, magnitude); // System.out.println(normal + " - " + realMag); - receiver.addImpulse(new Impulse(normal, magnitude, Collidable.TYPE_STRUCTURE)); + receiver.addImpulse(new Impulse(normal, localPosition, magnitude, Collidable.TYPE_STRUCTURE)); // System.out.println("Structure-creature collision"); break; case Collidable.TYPE_ITEM: - receiver.addImpulse(new Impulse(normal, magnitude * 0.5, Collidable.TYPE_ITEM)); + receiver.addImpulse(new Impulse(normal, localPosition, magnitude * 0.5, Collidable.TYPE_ITEM)); break; } break; @@ -305,9 +311,11 @@ public class CollisionEngine { CollisionObject rigidBody = (CollisionObject)dynamicEntity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); Vector3f offset = (Vector3f)dynamicEntity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET); Vector3f newPosition = PhysicsUtils.getRigidBodyPosition(rigidBody).sub(offset); + Quaternionf newRotation = PhysicsUtils.getRigidBodyRotation(rigidBody); // System.out.println(rigidBody + " position " + newPosition); // System.out.println("Linear velocity: " + rigidBody.getLinearVelocity(new javax.vecmath.Vector3f())); EntityUtils.getPosition(dynamicEntity).set(newPosition); + EntityUtils.getRotation(dynamicEntity).set(newRotation); } } diff --git a/src/main/java/electrosphere/game/collision/PhysicsUtils.java b/src/main/java/electrosphere/game/collision/PhysicsUtils.java index 33067d61..99efc867 100644 --- a/src/main/java/electrosphere/game/collision/PhysicsUtils.java +++ b/src/main/java/electrosphere/game/collision/PhysicsUtils.java @@ -250,8 +250,8 @@ public class PhysicsUtils { return vecmathToJomlVector3f(transform); } - public static Quaternionf getRigidBodyRotation(RigidBody body){ - return vecmathtoJomlQuaternionf(body.getMotionState().getWorldTransform(new electrosphere.linearmath.Transform()).getRotation(new javax.vecmath.Quat4f())); + public static Quaternionf getRigidBodyRotation(CollisionObject body){ + return vecmathtoJomlQuaternionf(body.getWorldTransform(new electrosphere.linearmath.Transform()).getRotation(new javax.vecmath.Quat4f())); } public static Vector3f vecmathToJomlVector3f(javax.vecmath.Vector3f vector){ diff --git a/src/main/java/electrosphere/game/collision/collidable/Collidable.java b/src/main/java/electrosphere/game/collision/collidable/Collidable.java index 252f1e8d..f2809317 100644 --- a/src/main/java/electrosphere/game/collision/collidable/Collidable.java +++ b/src/main/java/electrosphere/game/collision/collidable/Collidable.java @@ -7,6 +7,8 @@ import electrosphere.entity.state.collidable.Impulse; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; + +import org.joml.Matrix4f; import org.joml.Vector3f; @@ -19,7 +21,7 @@ public class Collidable { Entity parent; String type; - List impulses = new CopyOnWriteArrayList(); + List impulses = new CopyOnWriteArrayList(); public static final String TYPE_TERRAIN = "terrain"; public static final String TYPE_CREATURE = "creature"; diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index 26a84c85..9a39d81f 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -766,6 +766,7 @@ public class RenderingEngine { Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)); modelTransformMatrix.identity(); modelTransformMatrix.translate(cameraModifiedPosition); + modelTransformMatrix.rotate(EntityUtils.getRotation(physicsEntity)); // modelTransformMatrix.translate(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()); //center sphere modelTransformMatrix.scale(template.getDimension1(),template.getDimension2(),template.getDimension3()); physicsGraphicsModel.modelMatrix = modelTransformMatrix;