Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

import com.jme3.app.SimpleApplication;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.effect.ParticleTriMesh;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
Expand All @@ -60,7 +60,7 @@ public static void main(String[] args) {

@Override
public void simpleInitApp() {
emit = new ParticleEmitter("Emitter", Type.Triangle, 300);
emit = new ParticleEmitter("Emitter", new ParticleTriMesh(), 300);
emit.setGravity(0, 0, 0);
emit.setVelocityVariation(1);
emit.setLowLife(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.math.Matrix4f;
import com.jme3.math.Matrix;
import com.jme3.math.Matrixable;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
Expand Down Expand Up @@ -36,7 +37,8 @@ public class BoneContext {
* The bones' matrices have, unlike objects', the coordinate system identical to JME's (Y axis is UP, X to the right and Z toward us).
* So in order to have them loaded properly we need to transform their armature matrix (which blender sees as rotated) to make sure we get identical results.
*/
public static final Matrix4f BONE_ARMATURE_TRANSFORMATION_MATRIX = new Matrix4f(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);
public static final float[] data = {1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1};
public static final Matrixable BONE_ARMATURE_TRANSFORMATION_MATRIX = new Matrix(data);

private static final int IKFLAG_LOCK_X = 0x01;
private static final int IKFLAG_LOCK_Y = 0x02;
Expand All @@ -57,9 +59,9 @@ public class BoneContext {
/** The bone's flag. */
private int flag;
/** The bone's matrix in world space. */
private Matrix4f globalBoneMatrix;
private Matrixable globalBoneMatrix;
/** The bone's matrix in the model space. */
private Matrix4f boneMatrixInModelSpace;
private Matrixable boneMatrixInModelSpace;
/** The parent context. */
private BoneContext parent;
/** The children of this context. */
Expand Down Expand Up @@ -139,7 +141,7 @@ private BoneContext(Structure boneStructure, Long armatureObjectOMA, BoneContext
Structure armatureStructure = blenderContext.getFileBlock(armatureObjectOMA).getStructure(blenderContext);
Spatial armature = (Spatial) objectHelper.toObject(armatureStructure, blenderContext);
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
Matrix4f armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform(), new Matrix4f());
Matrixable armatureWorldMatrix = constraintHelper.toMatrix(armature.getWorldTransform(), new Matrix(4));

// and now compute the final bone matrix in world space
globalBoneMatrix = armatureWorldMatrix.mult(globalBoneMatrix);
Expand Down Expand Up @@ -207,14 +209,14 @@ public Bone buildBone(List<Bone> bones, Long skeletonOwnerOma, BlenderContext bl
Structure skeletonOwnerObjectStructure = (Structure) blenderContext.getLoadedFeature(skeletonOwnerOma, LoadedDataType.STRUCTURE);
// I could load 'imat' here, but apparently in some older blenders there were bugs or unfinished functionalities that stored ZERO matrix in imat field
// loading 'obmat' and inverting it makes us avoid errors in such cases
Matrix4f invertedObjectOwnerGlobalMatrix = objectHelper.getMatrix(skeletonOwnerObjectStructure, "obmat", blenderContext.getBlenderKey().isFixUpAxis()).invertLocal();
Matrixable invertedObjectOwnerGlobalMatrix = objectHelper.getMatrix(skeletonOwnerObjectStructure, "obmat", blenderContext.getBlenderKey().isFixUpAxis()).invertLocal();
if (objectHelper.isParent(skeletonOwnerOma, armatureObjectOMA)) {
boneMatrixInModelSpace = globalBoneMatrix.mult(invertedObjectOwnerGlobalMatrix);
} else {
boneMatrixInModelSpace = invertedObjectOwnerGlobalMatrix.mult(globalBoneMatrix);
}

Matrix4f boneLocalMatrix = parent == null ? boneMatrixInModelSpace : parent.boneMatrixInModelSpace.invert().multLocal(boneMatrixInModelSpace);
Matrixable boneLocalMatrix = parent == null ? boneMatrixInModelSpace : parent.boneMatrixInModelSpace.invert().multLocal(boneMatrixInModelSpace);

Vector3f poseLocation = parent == null || !this.is(CONNECTED_TO_PARENT) ? boneLocalMatrix.toTranslationVector() : new Vector3f(0, parent.length, 0);
Quaternion rotation = boneLocalMatrix.toRotationQuat().normalizeLocal();
Expand Down Expand Up @@ -278,7 +280,7 @@ public Skeleton getSkeleton() {
/**
* @return the initial bone's matrix in model space
*/
public Matrix4f getBoneMatrixInModelSpace() {
public Matrixable getBoneMatrixInModelSpace() {
return boneMatrixInModelSpace;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.jme3.scene.plugins.blender.animations;

import com.jme3.math.Matrix4f;
import com.jme3.math.Matrixable;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.file.DynamicArray;
import com.jme3.scene.plugins.blender.file.Structure;
Expand Down Expand Up @@ -36,7 +36,7 @@ public class BoneEnvelope {
* a variable that tells if we use the Y-is up axis orientation
*/
@SuppressWarnings("unchecked")
public BoneEnvelope(Structure boneStructure, Matrix4f armatureWorldMatrix, boolean fixUpAxis) {
public BoneEnvelope(Structure boneStructure, Matrixable armatureWorldMatrix, boolean fixUpAxis) {
distance = ((Number) boneStructure.getFieldValue("dist")).floatValue();
weight = ((Number) boneStructure.getFieldValue("weight")).floatValue();
boneHeadRadius = ((Number) boneStructure.getFieldValue("rad_head")).floatValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.math.Matrix4f;
import com.jme3.math.Matrixable;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
Expand Down Expand Up @@ -224,26 +224,26 @@ public Transform getTransform(Long oma, String subtargetName, Space space) {
switch (space) {
case CONSTRAINT_SPACE_WORLD:
Spatial model = (Spatial) blenderContext.getLoadedFeature(targetBoneContext.getSkeletonOwnerOma(), LoadedDataType.FEATURE);
Matrix4f boneModelMatrix = this.toMatrix(bone.getModelSpacePosition(), bone.getModelSpaceRotation(), bone.getModelSpaceScale(), tempVars.tempMat4);
Matrix4f modelWorldMatrix = this.toMatrix(model.getWorldTransform(), tempVars.tempMat42);
Matrix4f boneMatrixInWorldSpace = modelWorldMatrix.multLocal(boneModelMatrix);
Matrixable boneModelMatrix = this.toMatrix(bone.getModelSpacePosition(), bone.getModelSpaceRotation(), bone.getModelSpaceScale(), tempVars.tempMat4);
Matrixable modelWorldMatrix = this.toMatrix(model.getWorldTransform(), tempVars.tempMat42);
Matrixable boneMatrixInWorldSpace = modelWorldMatrix.multLocal(boneModelMatrix);
result = new Transform(boneMatrixInWorldSpace.toTranslationVector(), boneMatrixInWorldSpace.toRotationQuat(), boneMatrixInWorldSpace.toScaleVector());
break;
case CONSTRAINT_SPACE_LOCAL:
assert bone.getParent() != null : "CONSTRAINT_SPACE_LOCAL should be evaluated as CONSTRAINT_SPACE_POSE if the bone has no parent!";
result = new Transform(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale());
break;
case CONSTRAINT_SPACE_POSE: {
Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
Matrixable boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
Matrixable armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
Matrixable bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
break;
}
case CONSTRAINT_SPACE_PARLOCAL: {
Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
Matrixable boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
Matrixable armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
Matrixable bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
Bone parent = bone.getParent();
if(parent != null) {
Expand Down Expand Up @@ -308,48 +308,48 @@ public void applyTransform(Long oma, String subtargetName, Space space, Transfor
bone.setBindTransforms(transform.getTranslation(), transform.getRotation(), transform.getScale());
break;
case CONSTRAINT_SPACE_WORLD: {
Matrix4f boneMatrixInWorldSpace = this.toMatrix(transform, tempVars.tempMat4);
Matrix4f modelWorldMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42);
Matrix4f boneMatrixInModelSpace = modelWorldMatrix.invertLocal().multLocal(boneMatrixInWorldSpace);
Matrixable boneMatrixInWorldSpace = this.toMatrix(transform, tempVars.tempMat4);
Matrixable modelWorldMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42);
Matrixable boneMatrixInModelSpace = modelWorldMatrix.invertLocal().multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent();
if (parent != null) {
Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
Matrixable parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
}
bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
break;
}
case CONSTRAINT_SPACE_POSE: {
Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
Matrixable armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
Matrixable boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
Matrixable invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
Matrixable boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent();
if (parent != null) {
Matrix4f parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
Matrixable parentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
boneMatrixInModelSpace = parentMatrixInModelSpace.invertLocal().multLocal(boneMatrixInModelSpace);
}
bone.setBindTransforms(boneMatrixInModelSpace.toTranslationVector(), boneMatrixInModelSpace.toRotationQuat(), boneMatrixInModelSpace.toScaleVector());
break;
}
case CONSTRAINT_SPACE_PARLOCAL:
Matrix4f armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
Matrix4f boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
Matrix4f invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
Matrix4f boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
Matrixable armatureWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat4);
Matrixable boneMatrixInWorldSpace = armatureWorldMatrix.multLocal(this.toMatrix(transform, tempVars.tempMat42));
Matrixable invertedModelMatrix = this.toMatrix(this.getTransform(targetBoneContext.getSkeletonOwnerOma(), null, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat42).invertLocal();
Matrixable boneMatrixInModelSpace = invertedModelMatrix.multLocal(boneMatrixInWorldSpace);
Bone parent = bone.getParent();
if (parent != null) {
//first add the initial parent matrix to the bone's model matrix
BoneContext parentContext = blenderContext.getBoneContext(parent);

Matrix4f initialParentMatrixInModelSpace = parentContext.getBoneMatrixInModelSpace();
Matrix4f currentParentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
Matrixable initialParentMatrixInModelSpace = parentContext.getBoneMatrixInModelSpace();
Matrixable currentParentMatrixInModelSpace = this.toMatrix(parent.getModelSpacePosition(), parent.getModelSpaceRotation(), parent.getModelSpaceScale(), tempVars.tempMat4);
//the bone will now move with its parent in model space

//now we need to subtract the difference between current parent's model matrix and its initial model matrix
boneMatrixInModelSpace = initialParentMatrixInModelSpace.mult(boneMatrixInModelSpace);

Matrix4f diffMatrix = initialParentMatrixInModelSpace.mult(currentParentMatrixInModelSpace.invert());
Matrixable diffMatrix = initialParentMatrixInModelSpace.mult(currentParentMatrixInModelSpace.invert());
boneMatrixInModelSpace.multLocal(diffMatrix);
//now the bone will have its position in model space with initial parent's model matrix added
}
Expand All @@ -373,8 +373,8 @@ public void applyTransform(Long oma, String subtargetName, Space space, Transfor
Transform parentWorldTransform = feature.getParent().getWorldTransform();

TempVars tempVars = TempVars.get();
Matrix4f parentInverseMatrix = this.toMatrix(parentWorldTransform, tempVars.tempMat4).invertLocal();
Matrix4f m = this.toMatrix(transform, tempVars.tempMat42);
Matrixable parentInverseMatrix = this.toMatrix(parentWorldTransform, tempVars.tempMat4).invertLocal();
Matrixable m = this.toMatrix(transform, tempVars.tempMat42);
m = m.multLocal(parentInverseMatrix);
tempVars.release();

Expand All @@ -400,7 +400,7 @@ public void applyTransform(Long oma, String subtargetName, Space space, Transfor
* the matrix where the result will be stored
* @return the store matrix
*/
public Matrix4f toMatrix(Transform transform, Matrix4f store) {
public Matrixable toMatrix(Transform transform, Matrixable store) {
if (transform != null) {
return this.toMatrix(transform.getTranslation(), transform.getRotation(), transform.getScale(), store);
}
Expand All @@ -421,7 +421,7 @@ public Matrix4f toMatrix(Transform transform, Matrix4f store) {
* the matrix where the result will be stored
* @return the store matrix
*/
private Matrix4f toMatrix(Vector3f position, Quaternion rotation, Vector3f scale, Matrix4f store) {
private Matrixable toMatrix(Vector3f position, Quaternion rotation, Vector3f scale, Matrixable store) {
store.loadIdentity();
store.setTranslation(position);
store.setRotationQuaternion(rotation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.math.Matrix4f;
import com.jme3.math.Matrixable;
import com.jme3.math.Transform;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
Expand Down Expand Up @@ -44,7 +44,7 @@ public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform,
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);

TempVars tempVars = TempVars.get();
Matrix4f m = constraintHelper.toMatrix(targetTransform, tempVars.tempMat4);
Matrixable m = constraintHelper.toMatrix(targetTransform, tempVars.tempMat4);
tempVars.tempMat42.set(BoneContext.BONE_ARMATURE_TRANSFORMATION_MATRIX);
if (target instanceof Bone) {
tempVars.tempMat42.invertLocal();
Expand Down
Loading