Bugfix: (hopefully) final fixes to armature applying to models without applied transformations (+ removing unused pieces of code)
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10529 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
e282db0f7f
commit
4f104e4200
@ -85,17 +85,15 @@ public class ArmatureHelper extends AbstractBlenderHelper {
|
|||||||
* the parent bone
|
* the parent bone
|
||||||
* @param result
|
* @param result
|
||||||
* the list where the newly created bone will be added
|
* the list where the newly created bone will be added
|
||||||
* @param bonesPoseChannels
|
|
||||||
* a map of bones poses channels
|
|
||||||
* @param blenderContext
|
* @param blenderContext
|
||||||
* the blender context
|
* the blender context
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception is thrown when there is problem with the blender
|
* an exception is thrown when there is problem with the blender
|
||||||
* file
|
* file
|
||||||
*/
|
*/
|
||||||
public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Matrix4f arbt, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
|
public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Matrix4f objectToArmatureTransformation, BlenderContext blenderContext) throws BlenderFileException {
|
||||||
BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, arbt, bonesPoseChannels, blenderContext);
|
BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, blenderContext);
|
||||||
bc.buildBone(result, bonesOMAs, blenderContext);
|
bc.buildBone(result, bonesOMAs, objectToArmatureTransformation, blenderContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,8 +37,6 @@ public class BoneContext {
|
|||||||
private Matrix4f restMatrix;
|
private Matrix4f restMatrix;
|
||||||
/** Bone's total inverse transformation. */
|
/** Bone's total inverse transformation. */
|
||||||
private Matrix4f inverseTotalTransformation;
|
private Matrix4f inverseTotalTransformation;
|
||||||
/** Bone's parent inverse matrix. */
|
|
||||||
private Matrix4f inverseParentMatrix;
|
|
||||||
/** The length of the bone. */
|
/** The length of the bone. */
|
||||||
private float length;
|
private float length;
|
||||||
|
|
||||||
@ -49,18 +47,14 @@ public class BoneContext {
|
|||||||
* the OMA of the bone's armature object
|
* the OMA of the bone's armature object
|
||||||
* @param boneStructure
|
* @param boneStructure
|
||||||
* the bone's structure
|
* the bone's structure
|
||||||
* @param objectToArmatureMatrix
|
|
||||||
* object-to-armature transformation matrix
|
|
||||||
* @param bonesPoseChannels
|
|
||||||
* a map of pose channels for each bone OMA
|
|
||||||
* @param blenderContext
|
* @param blenderContext
|
||||||
* the blender context
|
* the blender context
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception is thrown when problem with blender data reading
|
* an exception is thrown when problem with blender data reading
|
||||||
* occurs
|
* occurs
|
||||||
*/
|
*/
|
||||||
public BoneContext(Long armatureObjectOMA, Structure boneStructure, Matrix4f objectToArmatureMatrix, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
|
public BoneContext(Long armatureObjectOMA, Structure boneStructure, BlenderContext blenderContext) throws BlenderFileException {
|
||||||
this(boneStructure, armatureObjectOMA, null, objectToArmatureMatrix, bonesPoseChannels, blenderContext);
|
this(boneStructure, armatureObjectOMA, null, blenderContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,17 +66,13 @@ public class BoneContext {
|
|||||||
* the OMA of the bone's armature object
|
* the OMA of the bone's armature object
|
||||||
* @param parent
|
* @param parent
|
||||||
* bone's parent (null if the bone is the root bone)
|
* bone's parent (null if the bone is the root bone)
|
||||||
* @param objectToArmatureMatrix
|
|
||||||
* object-to-armature transformation matrix
|
|
||||||
* @param bonesPoseChannels
|
|
||||||
* a map of pose channels for each bone OMA
|
|
||||||
* @param blenderContext
|
* @param blenderContext
|
||||||
* the blender context
|
* the blender context
|
||||||
* @throws BlenderFileException
|
* @throws BlenderFileException
|
||||||
* an exception is thrown when problem with blender data reading
|
* an exception is thrown when problem with blender data reading
|
||||||
* occurs
|
* occurs
|
||||||
*/
|
*/
|
||||||
private BoneContext(Structure boneStructure, Long armatureObjectOMA, BoneContext parent, Matrix4f objectToArmatureMatrix, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
|
private BoneContext(Structure boneStructure, Long armatureObjectOMA, BoneContext parent, BlenderContext blenderContext) throws BlenderFileException {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.boneStructure = boneStructure;
|
this.boneStructure = boneStructure;
|
||||||
this.armatureObjectOMA = armatureObjectOMA;
|
this.armatureObjectOMA = armatureObjectOMA;
|
||||||
@ -91,33 +81,22 @@ public class BoneContext {
|
|||||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||||
armatureMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", blenderContext.getBlenderKey().isFixUpAxis());
|
armatureMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", blenderContext.getBlenderKey().isFixUpAxis());
|
||||||
|
|
||||||
this.computeRestMatrix(objectToArmatureMatrix);
|
//compute the bone's rest matrix
|
||||||
|
restMatrix = armatureMatrix.clone();
|
||||||
|
inverseTotalTransformation = restMatrix.invert();
|
||||||
|
if(parent != null) {
|
||||||
|
restMatrix = parent.inverseTotalTransformation.mult(restMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
//create the children
|
||||||
List<Structure> childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase(blenderContext);
|
List<Structure> childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase(blenderContext);
|
||||||
for (Structure child : childbase) {
|
for (Structure child : childbase) {
|
||||||
this.children.add(new BoneContext(child, armatureObjectOMA, this, objectToArmatureMatrix, bonesPoseChannels, blenderContext));
|
this.children.add(new BoneContext(child, armatureObjectOMA, this, blenderContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
blenderContext.setBoneContext(boneStructure.getOldMemoryAddress(), this);
|
blenderContext.setBoneContext(boneStructure.getOldMemoryAddress(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method computes the rest matrix for the bone.
|
|
||||||
*
|
|
||||||
* @param objectToArmatureMatrix
|
|
||||||
* object-to-armature transformation matrix
|
|
||||||
*/
|
|
||||||
private void computeRestMatrix(Matrix4f objectToArmatureMatrix) {
|
|
||||||
if (parent != null) {
|
|
||||||
inverseParentMatrix = parent.inverseTotalTransformation.clone();
|
|
||||||
} else {
|
|
||||||
inverseParentMatrix = objectToArmatureMatrix.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
restMatrix = armatureMatrix.clone();
|
|
||||||
inverseTotalTransformation = restMatrix.invert();
|
|
||||||
|
|
||||||
restMatrix = inverseParentMatrix.mult(restMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method builds the bone. It recursively builds the bone's children.
|
* This method builds the bone. It recursively builds the bone's children.
|
||||||
@ -126,27 +105,34 @@ public class BoneContext {
|
|||||||
* a list of bones where the newly created bone will be added
|
* a list of bones where the newly created bone will be added
|
||||||
* @param boneOMAs
|
* @param boneOMAs
|
||||||
* the map between bone and its old memory address
|
* the map between bone and its old memory address
|
||||||
|
* @param objectToArmatureMatrix
|
||||||
|
* object to armature transformation matrix
|
||||||
* @param blenderContext
|
* @param blenderContext
|
||||||
* the blender context
|
* the blender context
|
||||||
* @return newly created bone
|
* @return newly created bone
|
||||||
*/
|
*/
|
||||||
public Bone buildBone(List<Bone> bones, Map<Bone, Long> boneOMAs, BlenderContext blenderContext) {
|
public Bone buildBone(List<Bone> bones, Map<Bone, Long> boneOMAs, Matrix4f objectToArmatureMatrix, BlenderContext blenderContext) {
|
||||||
Long boneOMA = boneStructure.getOldMemoryAddress();
|
Long boneOMA = boneStructure.getOldMemoryAddress();
|
||||||
bone = new Bone(boneName);
|
bone = new Bone(boneName);
|
||||||
bones.add(bone);
|
bones.add(bone);
|
||||||
boneOMAs.put(bone, boneOMA);
|
boneOMAs.put(bone, boneOMA);
|
||||||
blenderContext.addLoadedFeatures(boneOMA, boneName, boneStructure, bone);
|
blenderContext.addLoadedFeatures(boneOMA, boneName, boneStructure, bone);
|
||||||
|
|
||||||
Matrix4f pose = this.restMatrix.clone();
|
|
||||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||||
|
|
||||||
Vector3f poseLocation = pose.toTranslationVector();
|
Vector3f poseLocation = restMatrix.toTranslationVector();
|
||||||
Quaternion rotation = pose.toRotationQuat();
|
Quaternion rotation = restMatrix.toRotationQuat().normalizeLocal();
|
||||||
Vector3f scale = objectHelper.getScale(pose);
|
Vector3f scale = objectHelper.getScale(restMatrix);
|
||||||
|
if(parent == null) {
|
||||||
|
Quaternion rotationQuaternion = objectToArmatureMatrix.toRotationQuat().normalizeLocal();
|
||||||
|
scale.multLocal(objectHelper.getScale(objectToArmatureMatrix));
|
||||||
|
rotationQuaternion.multLocal(poseLocation.addLocal(objectToArmatureMatrix.toTranslationVector()));
|
||||||
|
rotation.multLocal(rotationQuaternion);
|
||||||
|
}
|
||||||
|
|
||||||
bone.setBindTransforms(poseLocation, rotation, scale);
|
bone.setBindTransforms(poseLocation, rotation, scale);
|
||||||
for (BoneContext child : children) {
|
for (BoneContext child : children) {
|
||||||
bone.addChild(child.buildBone(bones, boneOMAs, blenderContext));
|
bone.addChild(child.buildBone(bones, boneOMAs, objectToArmatureMatrix, blenderContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
return bone;
|
return bone;
|
||||||
|
@ -17,9 +17,7 @@ import com.jme3.animation.Bone;
|
|||||||
import com.jme3.animation.BoneTrack;
|
import com.jme3.animation.BoneTrack;
|
||||||
import com.jme3.animation.Skeleton;
|
import com.jme3.animation.Skeleton;
|
||||||
import com.jme3.animation.SkeletonControl;
|
import com.jme3.animation.SkeletonControl;
|
||||||
import com.jme3.math.Matrix3f;
|
|
||||||
import com.jme3.math.Matrix4f;
|
import com.jme3.math.Matrix4f;
|
||||||
import com.jme3.math.Quaternion;
|
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Mesh;
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
@ -87,32 +85,16 @@ import com.jme3.util.BufferUtils;
|
|||||||
// load skeleton
|
// load skeleton
|
||||||
Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0);
|
Structure armatureStructure = ((Pointer) armatureObject.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0);
|
||||||
|
|
||||||
Structure pose = ((Pointer) armatureObject.getFieldValue("pose")).fetchData(blenderContext.getInputStream()).get(0);
|
|
||||||
List<Structure> chanbase = ((Structure) pose.getFieldValue("chanbase")).evaluateListBase(blenderContext);
|
|
||||||
|
|
||||||
Map<Long, Structure> bonesPoseChannels = new HashMap<Long, Structure>(chanbase.size());
|
|
||||||
for (Structure poseChannel : chanbase) {
|
|
||||||
Pointer pBone = (Pointer) poseChannel.getFieldValue("bone");
|
|
||||||
bonesPoseChannels.put(pBone.getOldMemoryAddress(), poseChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4f objectToArmatureTransformation = Matrix4f.IDENTITY;
|
|
||||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||||
|
boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
|
||||||
if(objectHelper.isLineage(armatureObject, objectStructure, blenderContext)) {
|
Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis);
|
||||||
boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
|
Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis);
|
||||||
Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis);
|
Matrix4f objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix);
|
||||||
Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis);
|
|
||||||
objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix);
|
|
||||||
Matrix3f rot = objectToArmatureTransformation.toRotationMatrix();
|
|
||||||
objectToArmatureTransformation = new Matrix4f();
|
|
||||||
objectToArmatureTransformation.setRotationQuaternion(new Quaternion().fromRotationMatrix(rot));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Structure> bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext);
|
List<Structure> bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext);
|
||||||
List<Bone> bonesList = new ArrayList<Bone>();
|
List<Bone> bonesList = new ArrayList<Bone>();
|
||||||
for (int i = 0; i < bonebase.size(); ++i) {
|
for (int i = 0; i < bonebase.size(); ++i) {
|
||||||
armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectToArmatureTransformation, bonesPoseChannels, blenderContext);
|
armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectToArmatureTransformation, blenderContext);
|
||||||
}
|
}
|
||||||
bonesList.add(0, new Bone(""));
|
bonesList.add(0, new Bone(""));
|
||||||
Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]);
|
Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]);
|
||||||
|
@ -251,31 +251,6 @@ public class ObjectHelper extends AbstractBlenderHelper {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method tells if the structure1 is a lineage of structure2.
|
|
||||||
*
|
|
||||||
* @param structure1
|
|
||||||
* the first structure
|
|
||||||
* @param structure2
|
|
||||||
* the second structure
|
|
||||||
* @return <b>true</b> if the first structure is a lineage of the second
|
|
||||||
* structure and <b>false</b> otherwise
|
|
||||||
* @throws BlenderFileException
|
|
||||||
* thrown when problems with reading the blend file occur
|
|
||||||
*/
|
|
||||||
public boolean isLineage(Structure structure1, Structure structure2, BlenderContext blenderContext) throws BlenderFileException {
|
|
||||||
Pointer pParent = (Pointer) structure2.getFieldValue("parent");
|
|
||||||
while (pParent.isNotNull()) {
|
|
||||||
long oma = pParent.getOldMemoryAddress();
|
|
||||||
if (structure1.getOldMemoryAddress().longValue() == oma) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
structure2 = blenderContext.getFileBlock(oma).getStructure(blenderContext);
|
|
||||||
pParent = (Pointer) structure2.getFieldValue("parent");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method calculates local transformation for the object. Parentage is taken under consideration.
|
* This method calculates local transformation for the object. Parentage is taken under consideration.
|
||||||
* @param objectStructure
|
* @param objectStructure
|
||||||
|
Loading…
x
Reference in New Issue
Block a user