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
|
||||
* @param result
|
||||
* the list where the newly created bone will be added
|
||||
* @param bonesPoseChannels
|
||||
* a map of bones poses channels
|
||||
* @param blenderContext
|
||||
* the blender context
|
||||
* @throws BlenderFileException
|
||||
* an exception is thrown when there is problem with the blender
|
||||
* file
|
||||
*/
|
||||
public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Matrix4f arbt, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
|
||||
BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, arbt, bonesPoseChannels, blenderContext);
|
||||
bc.buildBone(result, bonesOMAs, blenderContext);
|
||||
public void buildBones(Long armatureObjectOMA, Structure boneStructure, Bone parent, List<Bone> result, Matrix4f objectToArmatureTransformation, BlenderContext blenderContext) throws BlenderFileException {
|
||||
BoneContext bc = new BoneContext(armatureObjectOMA, boneStructure, blenderContext);
|
||||
bc.buildBone(result, bonesOMAs, objectToArmatureTransformation, blenderContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,8 +37,6 @@ public class BoneContext {
|
||||
private Matrix4f restMatrix;
|
||||
/** Bone's total inverse transformation. */
|
||||
private Matrix4f inverseTotalTransformation;
|
||||
/** Bone's parent inverse matrix. */
|
||||
private Matrix4f inverseParentMatrix;
|
||||
/** The length of the bone. */
|
||||
private float length;
|
||||
|
||||
@ -49,18 +47,14 @@ public class BoneContext {
|
||||
* the OMA of the bone's armature object
|
||||
* @param boneStructure
|
||||
* the bone's structure
|
||||
* @param objectToArmatureMatrix
|
||||
* object-to-armature transformation matrix
|
||||
* @param bonesPoseChannels
|
||||
* a map of pose channels for each bone OMA
|
||||
* @param blenderContext
|
||||
* the blender context
|
||||
* @throws BlenderFileException
|
||||
* an exception is thrown when problem with blender data reading
|
||||
* occurs
|
||||
*/
|
||||
public BoneContext(Long armatureObjectOMA, Structure boneStructure, Matrix4f objectToArmatureMatrix, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
|
||||
this(boneStructure, armatureObjectOMA, null, objectToArmatureMatrix, bonesPoseChannels, blenderContext);
|
||||
public BoneContext(Long armatureObjectOMA, Structure boneStructure, BlenderContext blenderContext) throws BlenderFileException {
|
||||
this(boneStructure, armatureObjectOMA, null, blenderContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,17 +66,13 @@ public class BoneContext {
|
||||
* the OMA of the bone's armature object
|
||||
* @param parent
|
||||
* 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
|
||||
* the blender context
|
||||
* @throws BlenderFileException
|
||||
* an exception is thrown when problem with blender data reading
|
||||
* 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.boneStructure = boneStructure;
|
||||
this.armatureObjectOMA = armatureObjectOMA;
|
||||
@ -90,34 +80,23 @@ public class BoneContext {
|
||||
length = ((Number) boneStructure.getFieldValue("length")).floatValue();
|
||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -126,27 +105,34 @@ public class BoneContext {
|
||||
* a list of bones where the newly created bone will be added
|
||||
* @param boneOMAs
|
||||
* the map between bone and its old memory address
|
||||
* @param objectToArmatureMatrix
|
||||
* object to armature transformation matrix
|
||||
* @param blenderContext
|
||||
* the blender context
|
||||
* @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();
|
||||
bone = new Bone(boneName);
|
||||
bones.add(bone);
|
||||
boneOMAs.put(bone, boneOMA);
|
||||
blenderContext.addLoadedFeatures(boneOMA, boneName, boneStructure, bone);
|
||||
|
||||
Matrix4f pose = this.restMatrix.clone();
|
||||
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
|
||||
|
||||
Vector3f poseLocation = pose.toTranslationVector();
|
||||
Quaternion rotation = pose.toRotationQuat();
|
||||
Vector3f scale = objectHelper.getScale(pose);
|
||||
Vector3f poseLocation = restMatrix.toTranslationVector();
|
||||
Quaternion rotation = restMatrix.toRotationQuat().normalizeLocal();
|
||||
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);
|
||||
for (BoneContext child : children) {
|
||||
bone.addChild(child.buildBone(bones, boneOMAs, blenderContext));
|
||||
bone.addChild(child.buildBone(bones, boneOMAs, objectToArmatureMatrix, blenderContext));
|
||||
}
|
||||
|
||||
return bone;
|
||||
|
@ -17,9 +17,7 @@ import com.jme3.animation.Bone;
|
||||
import com.jme3.animation.BoneTrack;
|
||||
import com.jme3.animation.Skeleton;
|
||||
import com.jme3.animation.SkeletonControl;
|
||||
import com.jme3.math.Matrix3f;
|
||||
import com.jme3.math.Matrix4f;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
@ -87,32 +85,16 @@ import com.jme3.util.BufferUtils;
|
||||
// load skeleton
|
||||
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);
|
||||
|
||||
if(objectHelper.isLineage(armatureObject, objectStructure, blenderContext)) {
|
||||
boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
|
||||
Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis);
|
||||
Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis);
|
||||
objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix);
|
||||
Matrix3f rot = objectToArmatureTransformation.toRotationMatrix();
|
||||
objectToArmatureTransformation = new Matrix4f();
|
||||
objectToArmatureTransformation.setRotationQuaternion(new Quaternion().fromRotationMatrix(rot));
|
||||
}
|
||||
boolean fixUpAxis = blenderContext.getBlenderKey().isFixUpAxis();
|
||||
Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", fixUpAxis);
|
||||
Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "imat", fixUpAxis);
|
||||
Matrix4f objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix);
|
||||
|
||||
List<Structure> bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext);
|
||||
List<Bone> bonesList = new ArrayList<Bone>();
|
||||
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(""));
|
||||
Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]);
|
||||
@ -244,7 +226,7 @@ import com.jme3.util.BufferUtils;
|
||||
}
|
||||
node.addControl(control);
|
||||
node.addControl(new SkeletonControl(animData.skeleton));
|
||||
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -250,31 +250,6 @@ public class ObjectHelper extends AbstractBlenderHelper {
|
||||
}
|
||||
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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user