diff --git a/assets/Data/creatures.json b/assets/Data/creatures.json index 6263514e..decc10da 100644 --- a/assets/Data/creatures.json +++ b/assets/Data/creatures.json @@ -103,6 +103,10 @@ "dimension1" : 0.1, "dimension2" : 0.2, "dimension3" : 0.1, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.2, "offsetZ" : 0 @@ -159,6 +163,10 @@ "dimension1" : 0.1, "dimension2" : 0.45, "dimension3" : 0.1, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.45, "offsetZ" : 0 @@ -208,6 +216,10 @@ "dimension1" : 0.1, "dimension2" : 0.2, "dimension3" : 0.1, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.2, "offsetZ" : 0 diff --git a/assets/Data/creatures/elf.json b/assets/Data/creatures/elf.json index df8a1dc0..12ea52e0 100644 --- a/assets/Data/creatures/elf.json +++ b/assets/Data/creatures/elf.json @@ -269,6 +269,10 @@ "dimension1" : 0.1, "dimension2" : 0.45, "dimension3" : 0.1, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.45, "offsetZ" : 0 diff --git a/assets/Data/creatures/human.json b/assets/Data/creatures/human.json index 98b358b9..a46324d5 100644 --- a/assets/Data/creatures/human.json +++ b/assets/Data/creatures/human.json @@ -269,6 +269,10 @@ "dimension1" : 0.1, "dimension2" : 0.9, "dimension3" : 0.1, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.45, "offsetZ" : 0 diff --git a/assets/Data/creatures/test.json b/assets/Data/creatures/test.json index f97422a4..ee26ffea 100644 --- a/assets/Data/creatures/test.json +++ b/assets/Data/creatures/test.json @@ -75,6 +75,10 @@ "dimension1" : 0.1, "dimension2" : 0.45, "dimension3" : 0.1, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.45, "offsetZ" : 0 diff --git a/assets/Data/foliage.json b/assets/Data/foliage.json index 06e5fcfd..6943fe0b 100644 --- a/assets/Data/foliage.json +++ b/assets/Data/foliage.json @@ -76,6 +76,10 @@ "dimension1" : 0.5, "dimension2" : 3, "dimension3" : 0.5, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 1.5, "offsetZ" : 0 diff --git a/assets/Data/items.json b/assets/Data/items.json index 1e898846..9037fbad 100644 --- a/assets/Data/items.json +++ b/assets/Data/items.json @@ -41,6 +41,10 @@ "dimension1" : 0.03, "dimension2" : 0.03, "dimension3" : 0.2, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0.0, "offsetY" : 0.05, "offsetZ" : 0.0 @@ -67,6 +71,10 @@ "dimension1" : 0.1, "dimension2" : 0.1, "dimension3" : 0.35, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.05, "offsetZ" : 0 @@ -87,6 +95,10 @@ "dimension1" : 0.1, "dimension2" : 0.1, "dimension3" : 0.35, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.05, "offsetZ" : 0 @@ -120,6 +132,10 @@ "dimension1" : 0.1, "dimension2" : 0.1, "dimension3" : 0.35, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.05, "offsetZ" : 0 @@ -151,6 +167,10 @@ "dimension1" : 0.1, "dimension2" : 0.1, "dimension3" : 0.35, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.05, "offsetZ" : 0 @@ -188,6 +208,10 @@ "dimension1" : 0.1, "dimension2" : 0.1, "dimension3" : 0.35, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.05, "offsetZ" : 0 diff --git a/assets/Data/objects.json b/assets/Data/objects.json index c9365121..cfd614b3 100644 --- a/assets/Data/objects.json +++ b/assets/Data/objects.json @@ -13,6 +13,10 @@ "dimension1" : 0.1, "dimension2" : 0.1, "dimension3" : 0.35, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : 0.05, "offsetZ" : 0 diff --git a/assets/Data/objects/floatingisland.json b/assets/Data/objects/floatingisland.json index 8709f854..85e7c667 100644 --- a/assets/Data/objects/floatingisland.json +++ b/assets/Data/objects/floatingisland.json @@ -13,6 +13,10 @@ "dimension1" : 1.7, "dimension2" : 1.7, "dimension3" : 1.7, + "rotX": 0, + "rotY": 0, + "rotZ": 0, + "rotW": 1, "offsetX" : 0, "offsetY" : -1.7, "offsetZ" : 0 diff --git a/assets/Models/modelPretransforms.json b/assets/Models/modelPretransforms.json index ba0ac8d1..541f22ff 100644 --- a/assets/Models/modelPretransforms.json +++ b/assets/Models/modelPretransforms.json @@ -54,6 +54,16 @@ "scale" : [1.0, 1.0, 1.0] } ] + }, + { + "path" : "Models/baseman5.fbx", + "globalTransform": { + "rotation" : [0,0,0,1], + "offset" : [0.0, 0.0, 0.0], + "scale" : [0.005, 0.005, 0.005] + }, + "meshes" : [ + ] } ] } \ No newline at end of file diff --git a/docs/src/physics/collision.md b/docs/src/physics/collision.md index dea41589..4782c660 100644 --- a/docs/src/physics/collision.md +++ b/docs/src/physics/collision.md @@ -25,6 +25,7 @@ The big case for this engine is the main physics system. The goal is to provide ## Major Usage Notes - All geometries are aligned along z by default in the library (ie your cylinders will be on their sides) + - All functions that transform the scale of a DBody only transform the first shape within the rigid body. This should likely eventually be updated to support multiple shapes in a body. diff --git a/docs/src/resources/modelLoading.md b/docs/src/resources/modelLoading.md new file mode 100644 index 00000000..979a7eed --- /dev/null +++ b/docs/src/resources/modelLoading.md @@ -0,0 +1,79 @@ +# Model Loading + +TODO + + +## High Level Overview + + + + + +## Major Usage Notes + + + + + + + + + + + + + +## Main Classes + +[CollisionEngine.java](@ref #electrosphere.collision.CollisionEngine) - Represents a specific collision system. It may be helpful to think of it as viewing the world through a specific lens. Keeps track of all entities that do its type of collisions and fires callbacks on collision. Should be updated each tick. + + + + + + + + + +## Library Explanation + + + + + + + + + +## Code Organization and Best Practices + +#### Startup + + +#### Usage + + + + + + + + + + + +## Terminology + + + + + + + + + + + + + +## Future Goals diff --git a/src/main/java/electrosphere/collision/CollisionEngine.java b/src/main/java/electrosphere/collision/CollisionEngine.java index 6c26c724..b13b5daf 100644 --- a/src/main/java/electrosphere/collision/CollisionEngine.java +++ b/src/main/java/electrosphere/collision/CollisionEngine.java @@ -16,9 +16,12 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Semaphore; +import org.joml.Matrix4d; +import org.joml.Matrix4f; import org.joml.Quaterniond; import org.joml.Vector3d; import org.joml.Vector3f; +import org.joml.Vector4d; import org.ode4j.math.DMatrix3; import org.ode4j.math.DVector3; import org.ode4j.math.DVector4; @@ -356,13 +359,17 @@ public class CollisionEngine { */ public void updateDynamicObjectTransforms(){ for(Collidable collidable : collidableList){ - Entity physicsEntity = collidable.getParent(); - DBody rigidBody = (DBody)physicsEntity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); - Vector3d offset = (Vector3d)physicsEntity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET); - Vector3d newPosition = PhysicsUtils.getRigidBodyPosition(rigidBody).sub(offset); - Quaterniond newRotation = PhysicsUtils.getRigidBodyRotation(rigidBody); - EntityUtils.getPosition(physicsEntity).set(newPosition); - EntityUtils.getRotation(physicsEntity).set(newRotation); + if(collidable.getParentTracksCollidable()){ + Entity physicsEntity = collidable.getParent(); + DBody rigidBody = (DBody)physicsEntity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); + Matrix4d transform = PhysicsEntityUtils.getEntityCollidableTransform(physicsEntity); + Matrix4d inverseTransform = transform.invert(); + Vector4d rawPos = inverseTransform.transform(new Vector4d(PhysicsUtils.getRigidBodyPosition(rigidBody),1)); + Vector3d newPosition = new Vector3d(rawPos.x,rawPos.y,rawPos.z); + Quaterniond newRotation = PhysicsUtils.getRigidBodyRotation(rigidBody); + EntityUtils.getPosition(physicsEntity).set(newPosition); + EntityUtils.getRotation(physicsEntity).set(newRotation); + } } } @@ -633,6 +640,28 @@ public class CollisionEngine { spaceLock.release(); } + /** + * Sets the transform on a body + * @param body The body + * @param position The position + * @param rotation The rotation + * @param scale The scale + */ + protected void setBodyTransform(DBody body, Vector3d position, Quaterniond rotation, Vector3d scale){ + spaceLock.acquireUninterruptibly(); + body.setPosition(position.x, position.y, position.z); + body.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation)); + DGeom firstGeom = body.getFirstGeom(); + if(firstGeom instanceof DCylinder){ + ((DCylinder)firstGeom).setParams(scale.x,scale.y); + } else if(firstGeom instanceof DBox){ + ((DBox)firstGeom).setLengths(scale.x,scale.y,scale.z); + } else if(firstGeom instanceof DCapsule){ + ((DCapsule)firstGeom).setParams(scale.x,scale.y); + } + spaceLock.release(); + } + /** * Gets the position of the body in a thread-safe way * @param body The body to get the position of diff --git a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java index 89081b73..8d8c8c85 100644 --- a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java @@ -1,5 +1,6 @@ package electrosphere.collision; +import org.joml.Matrix4d; import org.joml.Matrix4f; import org.joml.Vector3d; import org.joml.Vector3f; @@ -45,7 +46,13 @@ public class PhysicsEntityUtils { collidable = new Collidable(rVal, Collidable.TYPE_CREATURE); ClientCollidableTree tree = new ClientCollidableTree(rVal,collidable,rigidBody); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody); + Matrix4d offsetTransform = new Matrix4d().translationRotateScale( + physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate + physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate + 1, 1, 1 //scale + ); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(physicsTemplate.getOffsetX(),physicsTemplate.getOffsetY(),physicsTemplate.getOffsetZ())); + 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); @@ -71,7 +78,13 @@ public class PhysicsEntityUtils { collidable = new Collidable(rVal, Collidable.TYPE_CREATURE); ClientCollidableTree tree = new ClientCollidableTree(rVal,collidable,rigidBody); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody); + Matrix4d offsetTransform = new Matrix4d().translationRotateScale( + physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate + physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate + 1, 1, 1 //scale + ); rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_OFFSET, new Vector3f(physicsTemplate.getOffsetX(),physicsTemplate.getOffsetY(),physicsTemplate.getOffsetZ())); + 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); @@ -266,5 +279,14 @@ public class PhysicsEntityUtils { return terrainBody; } + + /** + * Gets the transform from parent entity position to rigid body + * @param entity The entity + * @return The transform + */ + public static Matrix4d getEntityCollidableTransform(Entity entity){ + return (Matrix4d) entity.getData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM); + } } diff --git a/src/main/java/electrosphere/collision/PhysicsUtils.java b/src/main/java/electrosphere/collision/PhysicsUtils.java index 031630d8..133745b5 100644 --- a/src/main/java/electrosphere/collision/PhysicsUtils.java +++ b/src/main/java/electrosphere/collision/PhysicsUtils.java @@ -68,6 +68,18 @@ public class PhysicsUtils { collisionEngine.setBodyTransform(body, position, rotation); } + + /** + * Sets the position + rotation + scale of a body + * @param position The position + * @param rotation The rotation + * @param scale The scale + * @param body The body + */ + public static void setRigidBodyTransform(CollisionEngine collisionEngine, Vector3d position, Quaterniond rotation, Vector3d scale, DBody body){ + collisionEngine.setBodyTransform(body, 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 diff --git a/src/main/java/electrosphere/collision/collidable/Collidable.java b/src/main/java/electrosphere/collision/collidable/Collidable.java index 9ccda361..59754852 100644 --- a/src/main/java/electrosphere/collision/collidable/Collidable.java +++ b/src/main/java/electrosphere/collision/collidable/Collidable.java @@ -15,9 +15,15 @@ import org.joml.Vector3f; */ public class Collidable { + //The entity this collidable is attached to Entity parent; + //The type of collidable String type; + + //If true, once impulses are applied to the collidable, have the parent entity resynchronize its position with the collidable + boolean parentTracksCollidable = true; + //The impulses to be applied to this collidable List impulses = new CopyOnWriteArrayList(); public static final String TYPE_TERRAIN = "terrain"; @@ -49,6 +55,14 @@ public class Collidable { return type; } + /** + * Gets whether the parent tracks the collidable's position + * @return True if the parent tracks the collidable's position, false otherwise + */ + public boolean getParentTracksCollidable(){ + return parentTracksCollidable; + } + public void overrideType(String type){ this.type = type; } diff --git a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java index ce95ae58..1004c811 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java @@ -242,10 +242,10 @@ public class ClientLoading { }); Random rand = new Random(0); - { - Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong()); - EntityUtils.getPosition(tree).set(5,0,5); - } + // { + // Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong()); + // EntityUtils.getPosition(tree).set(5,0,5); + // } // for(int i = 0; i < 6; i++){ // Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong()); // // EntityUtils.getPosition(tree).set(5,0,5); @@ -258,6 +258,7 @@ public class ClientLoading { for(int z = 0; z < 5; z++){ Entity tree = ProceduralTree.clientGenerateProceduralTree("oak", rand.nextLong()); ClientEntityUtils.initiallyPositionEntity(tree, new Vector3d(5 + x * 5,0,5 + z * 5)); + EntityUtils.getScale(tree).set(0.5f); } } diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java index b6a5b74f..43000cf7 100644 --- a/src/main/java/electrosphere/entity/EntityDataStrings.java +++ b/src/main/java/electrosphere/entity/EntityDataStrings.java @@ -118,6 +118,7 @@ public class EntityDataStrings { */ public static final String PHYSICS_COLLISION_BODY = "physicsRigidBody"; public static final String PHYSICS_COLLISION_BODY_OFFSET = "physicsRigidBodyOffset"; + public static final String PHYSICS_COLLISION_BODY_TRANSFORM = "physicsRigidBodyTransform"; // the transform matrix from origin of entity to origin of physics body public static final String PHYSICS_COLLIDABLE = "physicsCollidable"; public static final String PHYSICS_MODEL_TEMPLATE = "physicsModelTemplate"; public static final String PHYSICS_MASS = "physicsMass"; diff --git a/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java b/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java index 278144bb..6313563d 100644 --- a/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java +++ b/src/main/java/electrosphere/entity/state/collidable/ClientCollidableTree.java @@ -1,11 +1,14 @@ package electrosphere.entity.state.collidable; +import org.joml.Matrix4d; import org.joml.Matrix4f; import org.joml.Quaterniond; import org.joml.Vector3d; +import org.joml.Vector3f; import org.joml.Vector4d; import org.ode4j.ode.DBody; +import electrosphere.collision.PhysicsEntityUtils; import electrosphere.collision.PhysicsUtils; import electrosphere.collision.collidable.Collidable; import electrosphere.engine.Globals; @@ -201,10 +204,26 @@ public class ClientCollidableTree implements BehaviorTree { //update collision engine of this thing's position CollidableTemplate template = (CollidableTemplate)parent.getData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE); + Matrix4d physicsBodyTransform = PhysicsEntityUtils.getEntityCollidableTransform(parent); + Vector3f parentScale = EntityUtils.getScale(parent); + Matrix4d parentTransform = new Matrix4d(); + // calculate new transform for current entity + parentTransform.identity() + .translate(position) + .rotate(rotation) + .scale(parentScale.x,parentScale.y,parentScale.z) + .mul(physicsBodyTransform); + //transform bone space + Vector4d rigidBodyPositionRaw = parentTransform.transform(new Vector4d(0,0,0,1)); + Vector3d rigidBodyPosition = new Vector3d(rigidBodyPositionRaw.x,rigidBodyPositionRaw.y,rigidBodyPositionRaw.z); + Quaterniond rigidBodyRotation = parentTransform.getUnnormalizedRotation(new Quaterniond()).normalize(); + Vector3d rigidBodyScaleRaw = parentTransform.getScale(new Vector3d()); + Vector3d rigidBodyScale = new Vector3d(rigidBodyScaleRaw.x,rigidBodyScaleRaw.y,rigidBodyScaleRaw.z); PhysicsUtils.setRigidBodyTransform( Globals.clientSceneWrapper.getCollisionEngine(), - new Vector3d(position.x + template.getOffsetX(),position.y + template.getOffsetY(),position.z + template.getOffsetZ()), - rotation, + rigidBodyPosition, + rigidBodyRotation, + rigidBodyScale, body ); } diff --git a/src/main/java/electrosphere/game/data/collidable/CollidableTemplate.java b/src/main/java/electrosphere/game/data/collidable/CollidableTemplate.java index d835badb..2a6e1d71 100644 --- a/src/main/java/electrosphere/game/data/collidable/CollidableTemplate.java +++ b/src/main/java/electrosphere/game/data/collidable/CollidableTemplate.java @@ -10,6 +10,11 @@ public class CollidableTemplate { float dimension1; float dimension2; float dimension3; + + float rotX; + float rotY; + float rotZ; + float rotW; float offsetX; float offsetY; @@ -31,6 +36,22 @@ public class CollidableTemplate { return dimension3; } + public float getRotX(){ + return rotX; + } + + public float getRotY(){ + return rotY; + } + + public float getRotZ(){ + return rotZ; + } + + public float getRotW(){ + return rotW; + } + public float getOffsetX() { return offsetX; } diff --git a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java index cc78044a..bfee84f9 100644 --- a/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java +++ b/src/main/java/electrosphere/net/client/protocol/EntityProtocol.java @@ -44,7 +44,6 @@ public class EntityProtocol { LoggerInterface.loggerNetworking.DEBUG("Spawn Creature " + message.getentityID() + " at " + message.getpositionX() + " " + message.getpositionY() + " " + message.getpositionZ()); CreatureTemplate template = Utilities.deserialize(message.getcreatureTemplate(), CreatureTemplate.class); newlySpawnedEntity = CreatureUtils.clientSpawnBasicCreature(template.getCreatureType(),template); - EntityUtils.getScale(newlySpawnedEntity).set(0.005f); EntityUtils.getPosition(newlySpawnedEntity).set(message.getpositionX(),message.getpositionY(),message.getpositionZ()); Globals.clientSceneWrapper.mapIdToId(newlySpawnedEntity.getId(), message.getentityID()); break; diff --git a/src/main/java/electrosphere/renderer/Bone.java b/src/main/java/electrosphere/renderer/Bone.java index 54007a70..64ba5650 100644 --- a/src/main/java/electrosphere/renderer/Bone.java +++ b/src/main/java/electrosphere/renderer/Bone.java @@ -7,6 +7,8 @@ import org.joml.Matrix4d; import org.joml.Matrix4f; import org.lwjgl.assimp.AIBone; +import electrosphere.renderer.loading.ModelPretransforms; + /** * * @author satellite @@ -15,22 +17,22 @@ public class Bone { public String boneID; int numWeights; HashMap weights; - public Matrix4f inverseBindPoseMatrix; + public Matrix4d inverseBindPoseMatrix; public Matrix4d deform; - public Matrix4f transform; - public Matrix4f final_transform; + public Matrix4d transform; + public Matrix4d final_transform; public AIBone raw_data; public Bone(){ - transform = new Matrix4f(); + transform = new Matrix4d(); deform = new Matrix4d(); - final_transform = new Matrix4f(); + final_transform = new Matrix4d(); } public Bone(AIBone raw_data){ - transform = new Matrix4f(); + transform = new Matrix4d(); deform = new Matrix4d(); - final_transform = new Matrix4f(); + final_transform = new Matrix4d(); boneID = raw_data.mName().dataString(); - inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrix(raw_data.mOffsetMatrix()); + inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrixd(raw_data.mOffsetMatrix()); this.raw_data = raw_data; } } diff --git a/src/main/java/electrosphere/renderer/Mesh.java b/src/main/java/electrosphere/renderer/Mesh.java index 30fc0f12..688004ff 100644 --- a/src/main/java/electrosphere/renderer/Mesh.java +++ b/src/main/java/electrosphere/renderer/Mesh.java @@ -25,6 +25,7 @@ import java.util.Map; import org.joml.Matrix4d; import org.joml.Matrix4f; import org.joml.Quaternionf; +import org.joml.Vector3d; import org.joml.Vector3f; import org.joml.Vector4d; import org.lwjgl.BufferUtils; @@ -161,8 +162,6 @@ public class Mesh { - - Matrix4d vertexPretransform = new Matrix4d().identity(); if(metadata != null){ System.out.println("Pretransforming"); @@ -199,6 +198,7 @@ public class Mesh { minZ = maxZ = z; } Vector4d transformedVertex = vertexPretransform.transform(new Vector4d(x,y,z,1.0)); + transformedVertex.w = 1.0; temp[0] = (float)transformedVertex.x; temp[1] = (float)transformedVertex.y; temp[2] = (float)transformedVertex.z; @@ -313,7 +313,7 @@ public class Mesh { // System.out.println("Num weights: " + currentBoneData.mNumWeights()); Bone currentBone = new Bone(); currentBone.boneID = currentBoneData.mName().dataString(); - currentBone.inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrix(currentBoneData.mOffsetMatrix()); + currentBone.inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrixd(currentBoneData.mOffsetMatrix()); currentBone.numWeights = currentBoneData.mNumWeights(); currentBone.weights = new HashMap(); Iterator weightIterator = currentBoneData.mWeights().iterator(); diff --git a/src/main/java/electrosphere/renderer/Model.java b/src/main/java/electrosphere/renderer/Model.java index 54fa31c3..5dcf5396 100644 --- a/src/main/java/electrosphere/renderer/Model.java +++ b/src/main/java/electrosphere/renderer/Model.java @@ -65,7 +65,7 @@ public class Model { public ArrayList materials; public Matrix4d modelMatrix = new Matrix4d(); ShaderProgram program; - Matrix4f globalInverseTransform; + Matrix4d globalInverseTransform; AnimNode root_anim_node; ActorMeshMask meshMask; @@ -80,6 +80,10 @@ public class Model { rVal.scene = s; ModelPretransforms.ModelMetadata modelMetadata = Globals.modelPretransforms.getModel(path); + ModelPretransforms.GlobalTransform globalTransform = null; + if(modelMetadata != null){ + globalTransform = modelMetadata.getGlobalTransform(); + } // //load meshes @@ -146,7 +150,10 @@ public class Model { //parse animation nodes and form hierarchy // AINode rootNode = s.mRootNode(); - rVal.globalInverseTransform = electrosphere.util.Utilities.convertAIMatrix(rootNode.mTransformation()); + rVal.globalInverseTransform = electrosphere.util.Utilities.convertAIMatrixd(rootNode.mTransformation()); + if(globalTransform != null){ + rVal.globalInverseTransform.scale(globalTransform.getScale()); + } // System.out.println("Global inverse transform"); // System.out.println(globalInverseTransform); rVal.root_anim_node = rVal.build_anim_node_map(s.mRootNode(),null); @@ -406,18 +413,24 @@ public class Model { boneMatrix = new Matrix4f(rootTransformation).mul(boneMatrix); frame.setMatrix(j, boneMatrix); */ + // + //bone rotators (turrets, hair, etc) Bone target_bone = boneMap.get(n.id); n.transform = n.transform.mul(target_bone.deform); if(boneRotators.containsKey(target_bone.boneID)){ n.transform.rotate(boneRotators.get(target_bone.boneID).getRotation()); } - Matrix4f bone_matrix = new Matrix4f(n.transform); + // + //static morph (changing nose size, eye distance, etc) + Matrix4d bone_matrix = new Matrix4d(n.transform); if(staticMorph != null && staticMorph.getBoneTransforms(n.id) != null){ bone_matrix.mul(staticMorph.getBoneTransforms(n.id).getTransform()); n.transform.mul(staticMorph.getBoneTransforms(n.id).getTransform()); } + // + //Calculate final offset from initial bone bone_matrix.mul(target_bone.inverseBindPoseMatrix); - bone_matrix = new Matrix4f(globalInverseTransform).mul(bone_matrix); + bone_matrix = new Matrix4d(globalInverseTransform).mul(bone_matrix); target_bone.final_transform = bone_matrix; // if(!toggled){ // System.out.println(n.id); diff --git a/src/main/java/electrosphere/renderer/actor/Actor.java b/src/main/java/electrosphere/renderer/actor/Actor.java index b3777709..b07e7670 100644 --- a/src/main/java/electrosphere/renderer/actor/Actor.java +++ b/src/main/java/electrosphere/renderer/actor/Actor.java @@ -18,6 +18,7 @@ import org.joml.Matrix4f; import org.joml.Quaterniond; import org.joml.Quaternionf; import org.joml.Vector3f; +import org.joml.Vector4d; import org.joml.Vector4f; /** @@ -247,11 +248,11 @@ public class Actor { // model.updateNodeTransform(); Bone currentBone = model.boneMap.get(boneName); if(currentBone != null){ - Vector4f result = currentBone.final_transform.transform(new Matrix4f(currentBone.inverseBindPoseMatrix).invert().transform(new Vector4f(rVal.x,rVal.y,rVal.z,1))); + Vector4d result = currentBone.final_transform.transform(new Matrix4d(currentBone.inverseBindPoseMatrix).invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1))); // currentBone.inverseBindPoseMatrix - rVal.x = result.x; - rVal.y = result.y; - rVal.z = result.z; + rVal.x = (float)result.x; + rVal.y = (float)result.y; + rVal.z = (float)result.z; } // } } @@ -270,7 +271,7 @@ public class Actor { Bone currentBone = model.boneMap.get(boneName); if(currentBone != null){ AxisAngle4f axisAngle = new AxisAngle4f(); - currentBone.final_transform.getRotation(axisAngle); + new Matrix4f(currentBone.final_transform).getRotation(axisAngle); Quaterniond rotation = new Quaterniond(axisAngle); rVal.set(rotation); } @@ -279,8 +280,8 @@ public class Actor { return rVal; } - public Matrix4f getBoneTransform(String boneName){ - Matrix4f rVal = new Matrix4f(); + public Matrix4d getBoneTransform(String boneName){ + Matrix4d rVal = new Matrix4d(); Model model = Globals.assetManager.fetchModel(modelPath); if(model != null){ applyAnimationMasks(model); diff --git a/src/main/java/electrosphere/renderer/actor/ActorUtils.java b/src/main/java/electrosphere/renderer/actor/ActorUtils.java index 73531ff1..fb6ef612 100644 --- a/src/main/java/electrosphere/renderer/actor/ActorUtils.java +++ b/src/main/java/electrosphere/renderer/actor/ActorUtils.java @@ -25,7 +25,6 @@ public class ActorUtils { public static void applyBlenderTransformer(Entity actorEntity){ Actor entityActor = EntityUtils.getActor(actorEntity); entityActor.setAnimationScalar(60f); //should be the value of the fps i think - EntityUtils.getScale(actorEntity).set(0.005f); } public static void applyBlenderRotation(Entity actorEntity){ diff --git a/src/main/java/electrosphere/renderer/anim/Animation.java b/src/main/java/electrosphere/renderer/anim/Animation.java index 826e9e92..ba4e1b6a 100644 --- a/src/main/java/electrosphere/renderer/anim/Animation.java +++ b/src/main/java/electrosphere/renderer/anim/Animation.java @@ -6,9 +6,11 @@ import java.util.Iterator; import java.util.Map; import java.util.PriorityQueue; +import org.joml.Matrix4d; import org.joml.Quaterniond; import org.joml.Quaternionf; import org.joml.Vector3f; +import org.joml.Vector4d; import org.lwjgl.PointerBuffer; import org.lwjgl.assimp.AIAnimation; import org.lwjgl.assimp.AIMeshAnim; @@ -17,6 +19,8 @@ import org.lwjgl.assimp.AINodeAnim; import org.lwjgl.assimp.AIQuatKey; import org.lwjgl.assimp.AIVectorKey; +import electrosphere.renderer.loading.ModelPretransforms; + /** * * @author satellite @@ -69,22 +73,19 @@ public class Animation { // System.out.println("Ticks per second: " + ticksPerSecond); // System.out.println("Anim sizeof: " + animData.sizeof()); // System.out.println("Duration: " + duration); + + // //Read in anim channels (bone modifications) // int channelCount = animData.mNumChannels(); channels = new ArrayList(); if(channelCount > 0){ -// System.out.println("Channel count: " + channelCount); for(int i = 0; i < channelCount; i++){ AINodeAnim currentChannelData = AINodeAnim.create(animData.mChannels().get(i)); -// System.out.println("Channel[" + (i + 1) + "]: " + currentChannelData.mNodeName().dataString()); //Create channel AnimChannel currentChannel = new AnimChannel(duration); - // currentChannel.positionFrame = new ArrayList(); - // currentChannel.rotationFrame = new ArrayList(); - // currentChannel.scaleFrame = new ArrayList(); currentChannel.nodeID = currentChannelData.mNodeName().dataString(); channels.add(currentChannel); @@ -95,20 +96,17 @@ public class Animation { if(currentChannelData.mNumPositionKeys() > 0){ org.lwjgl.assimp.AIVectorKey.Buffer buff = currentChannelData.mPositionKeys(); -// Iterator keyIterator = buff.iterator(); -// while (keyIterator.hasNext()) { -// AIVectorKey key = keyIterator.next(); -// Keyframe currentFrame = new Keyframe(key.mTime()); -// currentFrame.position = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); -// currentChannel.positionFrame.add(currentFrame); -// } if(buff != null && buff.hasRemaining()){ -// System.out.println("Position vectors: "); AIVectorKey key = buff.get(); Keyframe currentFrame = new Keyframe(key.mTime()); - currentFrame.position = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); + Vector4d positionRaw = new Vector4d( + key.mValue().x(), + key.mValue().y(), + key.mValue().z(), + 1 + ); + currentFrame.position = new Vector3f((float)positionRaw.x,(float)positionRaw.y,(float)positionRaw.z); currentChannel.addPositionFrame(key.mTime(),currentFrame); -// System.out.println(currentFrame.position); currentChannel.startingPosition = currentFrame.position; Keyframe previousFrame; @@ -116,10 +114,14 @@ public class Animation { previousFrame = currentFrame; key = buff.get(); currentFrame = new Keyframe(key.mTime()); - currentFrame.position = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); -// System.out.println(currentFrame.position); + positionRaw = new Vector4d( + key.mValue().x(), + key.mValue().y(), + key.mValue().z(), + 1 + ); + currentFrame.position = new Vector3f((float)positionRaw.x,(float)positionRaw.y,(float)positionRaw.z); //check if duplicate -// Keyframe previousFrame = currentChannel.positionFrame.get(currentChannel.positionFrame.size() - 1); if( previousFrame.position.x == currentFrame.position.x && previousFrame.position.y == currentFrame.position.y && previousFrame.position.z == currentFrame.position.z @@ -138,7 +140,6 @@ public class Animation { Keyframe currentFrame = new Keyframe(key.mTime()); currentFrame.rotation = new Quaterniond(); currentFrame.rotation.set(key.mValue().x(), key.mValue().y(), key.mValue().z(), key.mValue().w()); -// currentFrame.rotation = new Quaternionf(key.mValue().x(),key.mValue().y(),key.mValue().z(),key.mValue().w()); currentChannel.addRotationFrame(key.mTime(),currentFrame); currentChannel.startingRotation = currentFrame.rotation; @@ -150,9 +151,7 @@ public class Animation { currentFrame = new Keyframe(key.mTime()); currentFrame.rotation = new Quaterniond(); currentFrame.rotation.set(key.mValue().x(), key.mValue().y(), key.mValue().z(), key.mValue().w()); -// currentFrame.rotation = new Quaternionf(key.mValue().x(),key.mValue().y(),key.mValue().z(),key.mValue().w()); //check for duplicate -// Keyframe previousFrame = currentChannel.rotationFrame.get(currentChannel.rotationFrame.size() - 1); if( previousFrame.rotation.w == currentFrame.rotation.w && previousFrame.rotation.x == currentFrame.rotation.x && previousFrame.rotation.y == currentFrame.rotation.y && @@ -163,35 +162,29 @@ public class Animation { } } } -// Iterator keyIterator = buff.iterator(); -// while(keyIterator.hasNext()){ -// AIQuatKey key = keyIterator.next(); -// Keyframe currentFrame = new Keyframe(key.mTime()); -// currentFrame.rotation = new Quaternionf(key.mValue().w(),key.mValue().x(),key.mValue().y(),key.mValue().z()); -// currentChannel.rotationFrame.add(currentFrame); -// } } if(currentChannelData.mNumScalingKeys() > 0){ org.lwjgl.assimp.AIVectorKey.Buffer buff = currentChannelData.mScalingKeys(); -// Iterator keyIterator = buff.iterator(); -// while (keyIterator.hasNext()) { -// AIVectorKey key = keyIterator.next(); -// Keyframe currentFrame = new Keyframe(key.mTime()); -// currentFrame.scale = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); -// currentChannel.scaleFrame.add(currentFrame); -// } if(buff != null && buff.hasRemaining()){ AIVectorKey key = buff.get(); Keyframe currentFrame = new Keyframe(key.mTime()); - currentFrame.scale = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); + currentFrame.scale = new Vector3f( + (float)(key.mValue().x()), + (float)(key.mValue().y()), + (float)(key.mValue().z()) + ); currentChannel.addScaleFrame(key.mTime(),currentFrame); Keyframe previousFrame; while(buff.hasRemaining()){ previousFrame = currentFrame; key = buff.get(); currentFrame = new Keyframe(key.mTime()); - currentFrame.scale = new Vector3f(key.mValue().x(), key.mValue().y(), key.mValue().z()); + currentFrame.scale = new Vector3f( + (float)(key.mValue().x()), + (float)(key.mValue().y()), + (float)(key.mValue().z()) + ); if( currentFrame.scale.x == previousFrame.scale.x && currentFrame.scale.y == previousFrame.scale.y && currentFrame.scale.z == previousFrame.scale.z @@ -204,33 +197,8 @@ public class Animation { } -// System.out.println("end times"); -// for(int j = 0; j < currentChannelData.mNumPositionKeys(); j++){ -// org.lwjgl.assimp.AIVectorKey.Buffer buff = currentChannelData.mPositionKeys(); -// Iterator keyIterator = buff.iterator(); -// AIVectorKey posKey = currentChannelData.mPositionKeys().get(i); -// Keyframe currentFrame = new Keyframe(posKey.mTime()); -// currentFrame.position = new Vector3f(posKey.mValue().x(),posKey.mValue().y(),posKey.mValue().z()); -// } -// for(int j = 0; j < currentChannelData.mNumRotationKeys(); j++){ -// AIQuatKey rotKey = currentChannelData.mRotationKeys().get(i); -// HashMap test = new HashMap(); -// System.out.println(new Quaternionf(rotKey.mValue().w(),rotKey.mValue().x(),rotKey.mValue().y(),rotKey.mValue().z())); -// } -// for(int j = 0; j < currentChannelData.mNumScalingKeys(); j++){ -// AIVectorKey scaleKey = currentChannelData.mScalingKeys().get(i); -//// scaleKey.mValue(). -// System.out.println(new Vector3f(scaleKey.mValue().x(),scaleKey.mValue().y(),scaleKey.mValue().z())); -// } } } -// int meshChannelCount = animData.mNumMeshChannels(); -// meshChannelData = new ArrayList(); -// if(meshChannelCount > 0){ -// for(int i = 0; i < meshChannelCount; i++){ -// AIMeshAnim test = AIMeshAnim.create(animData.mMeshChannels().get(i)); -// } -// } //gotta free things nodeChannelData = null; meshChannelData = null; diff --git a/src/main/java/electrosphere/renderer/loading/ModelLoader.java b/src/main/java/electrosphere/renderer/loading/ModelLoader.java index 64174d2c..cca666ca 100644 --- a/src/main/java/electrosphere/renderer/loading/ModelLoader.java +++ b/src/main/java/electrosphere/renderer/loading/ModelLoader.java @@ -38,7 +38,9 @@ public class ModelLoader { aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_FixInfacingNormals | - aiProcess_LimitBoneWeights); + aiProcess_LimitBoneWeights | + aiProcess_GlobalScale + ); if(rVal == null){ throw new IllegalStateException(aiGetErrorString()); } diff --git a/src/main/java/electrosphere/renderer/loading/ModelPretransforms.java b/src/main/java/electrosphere/renderer/loading/ModelPretransforms.java index 45394470..422753c8 100644 --- a/src/main/java/electrosphere/renderer/loading/ModelPretransforms.java +++ b/src/main/java/electrosphere/renderer/loading/ModelPretransforms.java @@ -49,6 +49,8 @@ public class ModelPretransforms { List meshes; //Map relating path->mesh metadata Map meshDataMap; + //Optional global transform + GlobalTransform globalTransform; /** * Initializes the ModelMetadata object @@ -76,6 +78,14 @@ public class ModelPretransforms { public String getPath(){ return path; } + + /** + * Gets the global transform metadata + * @return The global transform metadata + */ + public GlobalTransform getGlobalTransform(){ + return globalTransform; + } } /** @@ -122,4 +132,50 @@ public class ModelPretransforms { return new Vector3d(scale.get(0),scale.get(1),scale.get(2)); } } + + + /** + * Holds metadata for pretransforming all meshes and potentially all animations + */ + public class GlobalTransform { + List rotation; + List offset; + List scale; + boolean applyToAnimations; + + /** + * gets the rotation of the transform as a JOML Quaterniond + * !!WARNING!! unsafe: If there aren't at least 4 doubles in the array it out of bounds + * @return The rotation of the transform + */ + public Quaterniond getRotation(){ + return new Quaterniond(rotation.get(0),rotation.get(1),rotation.get(2),rotation.get(3)); + } + + /** + * gets the offset of the transform as a JOML vector3d + * !!WARNING!! unsafe: If there aren't at least 3 doubles in the array it out of bounds + * @return The offset of the transform + */ + public Vector3d getOffset(){ + return new Vector3d(offset.get(0),offset.get(1),offset.get(2)); + } + + /** + * gets the scale of the transform as a JOML vector3d + * !!WARNING!! unsafe: If there aren't at least 3 doubles in the array it out of bounds + * @return The scale of the transform + */ + public Vector3d getScale(){ + return new Vector3d(scale.get(0),scale.get(1),scale.get(2)); + } + + /** + * Gets whether the global transform should be applied to animations + * @return True if should apply to animations, false otherwise + */ + public boolean getApplyToAnimations(){ + return applyToAnimations; + } + } } diff --git a/src/main/java/electrosphere/server/poseactor/PoseActor.java b/src/main/java/electrosphere/server/poseactor/PoseActor.java index 4fc35710..1c5123b6 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseActor.java +++ b/src/main/java/electrosphere/server/poseactor/PoseActor.java @@ -7,9 +7,11 @@ import java.util.Map; import java.util.PriorityQueue; import org.joml.AxisAngle4f; +import org.joml.Matrix4d; import org.joml.Matrix4f; import org.joml.Quaterniond; import org.joml.Vector3f; +import org.joml.Vector4d; import org.joml.Vector4f; import electrosphere.engine.Globals; @@ -243,7 +245,7 @@ public class PoseActor { Bone currentBone = model.boneMap.get(boneName); if(currentBone != null){ AxisAngle4f axisAngle = new AxisAngle4f(); - currentBone.final_transform.getRotation(axisAngle); + new Matrix4f(currentBone.final_transform).getRotation(axisAngle); Quaterniond rotation = new Quaterniond(axisAngle); rVal.set(rotation); } @@ -268,11 +270,11 @@ public class PoseActor { // model.updateNodeTransform(); Bone currentBone = model.boneMap.get(boneName); if(currentBone != null){ - Vector4f result = currentBone.final_transform.transform(new Matrix4f(currentBone.inverseBindPoseMatrix).invert().transform(new Vector4f(rVal.x,rVal.y,rVal.z,1))); + Vector4d result = currentBone.final_transform.transform(new Matrix4d(currentBone.inverseBindPoseMatrix).invert().transform(new Vector4d(rVal.x,rVal.y,rVal.z,1))); // currentBone.inverseBindPoseMatrix - rVal.x = result.x; - rVal.y = result.y; - rVal.z = result.z; + rVal.x = (float)result.x; + rVal.y = (float)result.y; + rVal.z = (float)result.z; } // } } diff --git a/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java b/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java index aa492359..cff07636 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java +++ b/src/main/java/electrosphere/server/poseactor/PoseActorUtils.java @@ -9,7 +9,6 @@ public class PoseActorUtils { public static void applyBlenderTransformer(Entity actorEntity){ PoseActor entityActor = EntityUtils.getPoseActor(actorEntity); entityActor.setAnimationScalar(60f); //should be the value of the fps i think - EntityUtils.getScale(actorEntity).set(0.005f); } public static void applyBlenderRotation(Entity actorEntity){ diff --git a/src/main/java/electrosphere/server/poseactor/PoseModel.java b/src/main/java/electrosphere/server/poseactor/PoseModel.java index b96ebdae..4436b81d 100644 --- a/src/main/java/electrosphere/server/poseactor/PoseModel.java +++ b/src/main/java/electrosphere/server/poseactor/PoseModel.java @@ -33,7 +33,7 @@ public class PoseModel { List bones; Map boneMap; - Matrix4f globalInverseTransform; + Matrix4d globalInverseTransform; Map nodeMap; AnimNode rootAnimNode; List animations; @@ -47,6 +47,10 @@ public class PoseModel { */ public PoseModel(String path, AIScene scene){ ModelPretransforms.ModelMetadata modelMetadata = Globals.modelPretransforms.getModel(path); + ModelPretransforms.GlobalTransform globalTransform = null; + if(modelMetadata != null){ + globalTransform = modelMetadata.getGlobalTransform(); + } bones = new ArrayList(); boneMap = new HashMap(); @@ -77,7 +81,10 @@ public class PoseModel { //parse animation nodes and form hierarchy // AINode rootNode = scene.mRootNode(); - globalInverseTransform = electrosphere.util.Utilities.convertAIMatrix(rootNode.mTransformation()); + globalInverseTransform = electrosphere.util.Utilities.convertAIMatrixd(rootNode.mTransformation()); + if(globalTransform != null){ + globalInverseTransform.scale(globalTransform.getScale()); + } rootAnimNode = buildAnimNodeMap(scene.mRootNode(),null); // @@ -173,13 +180,13 @@ public class PoseModel { if(boneRotators.containsKey(target_bone.boneID)){ n.transform.rotate(boneRotators.get(target_bone.boneID).getRotation()); } - Matrix4f bone_matrix = new Matrix4f(n.transform); + Matrix4d bone_matrix = new Matrix4d(n.transform); if(staticMorph != null && staticMorph.getBoneTransforms(n.id) != null){ bone_matrix.mul(staticMorph.getBoneTransforms(n.id).getTransform()); n.transform.mul(staticMorph.getBoneTransforms(n.id).getTransform()); } bone_matrix.mul(target_bone.inverseBindPoseMatrix); - bone_matrix = new Matrix4f(globalInverseTransform).mul(bone_matrix); + bone_matrix = new Matrix4d(globalInverseTransform).mul(bone_matrix); target_bone.final_transform = bone_matrix; } else { //not a bone, so use transform directly from data diff --git a/src/main/java/electrosphere/util/Utilities.java b/src/main/java/electrosphere/util/Utilities.java index 94862ea6..22f6dde6 100644 --- a/src/main/java/electrosphere/util/Utilities.java +++ b/src/main/java/electrosphere/util/Utilities.java @@ -25,6 +25,8 @@ import java.util.ArrayList; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; + +import org.joml.Matrix4d; import org.joml.Matrix4f; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -84,6 +86,47 @@ public class Utilities { rVal.m33(mat.d4()); return rVal; } + + public static Matrix4d convertAIMatrixd(AIMatrix4x4 mat){ + Matrix4d rVal = new Matrix4d(); + //Old, wrong approach: +// mat.set( +// mat.a1(), +// mat.b1(), +// mat.c1(), +// mat.d1(), +// mat.a2(), +// mat.b2(), +// mat.c2(), +// mat.d2(), +// mat.a3(), +// mat.b3(), +// mat.c3(), +// mat.d3(), +// mat.a4(), +// mat.b4(), +// mat.c4(), +// mat.d4() +// ); + //as demo'd in https://github.com/lwjglgamedev/lwjglbook/blob/master/chapter27/c27-p2/src/main/java/org/lwjglb/engine/loaders/assimp/AnimMeshesLoader.java + rVal.m00(mat.a1()); + rVal.m10(mat.a2()); + rVal.m20(mat.a3()); + rVal.m30(mat.a4()); + rVal.m01(mat.b1()); + rVal.m11(mat.b2()); + rVal.m21(mat.b3()); + rVal.m31(mat.b4()); + rVal.m02(mat.c1()); + rVal.m12(mat.c2()); + rVal.m22(mat.c3()); + rVal.m32(mat.c4()); + rVal.m03(mat.d1()); + rVal.m13(mat.d2()); + rVal.m23(mat.d3()); + rVal.m33(mat.d4()); + return rVal; + }