diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java index a59af46e5..53a3f0f87 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java @@ -41,6 +41,7 @@ import java.util.Stack; import java.util.logging.Level; import java.util.logging.Logger; +import com.jme3.animation.Skeleton; import com.jme3.asset.AssetManager; import com.jme3.asset.BlenderKey; import com.jme3.material.Material; @@ -107,6 +108,8 @@ public class BlenderContext { protected Map> constraints = new HashMap>(); /** Anim data loaded for features. */ private Map animData = new HashMap(); + /** Loaded skeletons. */ + private Map skeletons = new HashMap(); /** A map of mesh contexts. */ protected Map meshContexts = new HashMap(); /** A map of material contexts. */ @@ -494,6 +497,29 @@ public class BlenderContext { public AnimData getAnimData(Long ownerOMA) { return this.animData.get(ownerOMA); } + + /** + * This method sets the skeleton for the specified OMA of its owner. + * + * @param skeletonOMA + * the skeleton's old memory address + * @param animData + * the skeleton specified by the given OMA + */ + public void setSkeleton(Long skeletonOMA, Skeleton skeleton) { + this.skeletons.put(skeletonOMA, skeleton); + } + + /** + * This method returns the skeleton for the specified OMA of its owner. + * + * @param skeletonOMA + * the skeleton's old memory address + * @return the skeleton specified by the given OMA + */ + public Skeleton getSkeleton(Long skeletonOMA) { + return this.skeletons.get(skeletonOMA); + } /** * This method sets the mesh context for the given mesh old memory address. diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java index df78da710..5324971e4 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java @@ -11,11 +11,9 @@ import java.util.logging.Logger; import com.jme3.animation.AnimControl; import com.jme3.animation.Animation; -import com.jme3.animation.Bone; import com.jme3.animation.BoneTrack; import com.jme3.animation.Skeleton; import com.jme3.animation.SkeletonControl; -import com.jme3.math.Matrix4f; import com.jme3.scene.Geometry; import com.jme3.scene.Mesh; import com.jme3.scene.Node; @@ -27,7 +25,6 @@ import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType; import com.jme3.scene.plugins.blender.animations.ArmatureHelper; import com.jme3.scene.plugins.blender.constraints.Constraint; -import com.jme3.scene.plugins.blender.constraints.ConstraintHelper; import com.jme3.scene.plugins.blender.exceptions.BlenderFileException; import com.jme3.scene.plugins.blender.file.FileBlockHeader; import com.jme3.scene.plugins.blender.file.Pointer; @@ -91,34 +88,17 @@ import com.jme3.util.BufferUtils; Pointer pArmatureObject = (Pointer) modifierStructure.getFieldValue("object"); if (pArmatureObject.isNotNull()) { ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); - + ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); + Structure armatureObject = pArmatureObject.fetchData(blenderContext.getInputStream()).get(0); // 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 chanbase = ((Structure) pose.getFieldValue("chanbase")).evaluateListBase(blenderContext); - - Map bonesPoseChannels = new HashMap(chanbase.size()); - for (Structure poseChannel : chanbase) { - Pointer pBone = (Pointer) poseChannel.getFieldValue("bone"); - bonesPoseChannels.put(pBone.getOldMemoryAddress(), poseChannel); - } - - ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class); - Matrix4f armatureObjectMatrix = objectHelper.getMatrix(armatureObject, "obmat", true); - Matrix4f inverseMeshObjectMatrix = objectHelper.getMatrix(objectStructure, "obmat", true).invertLocal(); - Matrix4f objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix); - List bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext); - List bonesList = new ArrayList(); - for (int i = 0; i < bonebase.size(); ++i) { - armatureHelper.buildBones(bonebase.get(i), null, bonesList, objectToArmatureTransformation, bonesPoseChannels, blenderContext); - } - bonesList.add(0, new Bone("")); - Skeleton skeleton = new Skeleton(bonesList.toArray(new Bone[bonesList.size()])); - + //load the skeleton and its bones first + objectHelper.toObject(armatureObject, blenderContext); + Skeleton skeleton = blenderContext.getSkeleton(armatureObject.getOldMemoryAddress()); + // read mesh indexes this.meshOMA = meshStructure.getOldMemoryAddress(); this.readVerticesWeightsData(objectStructure, meshStructure, skeleton, blenderContext); @@ -153,10 +133,6 @@ import com.jme3.util.BufferUtils; for (Structure boneStructure : bonebase) { blenderContext.setAnimData(boneStructure.getOldMemoryAddress(), animData); } - - // loading constraints connected with this object - ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class); - constraintHelper.loadConstraints(armatureObject, blenderContext); } } } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java index d883b7f40..1dee924b4 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java @@ -31,11 +31,16 @@ */ package com.jme3.scene.plugins.blender.objects; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import com.jme3.animation.Bone; +import com.jme3.animation.Skeleton; import com.jme3.asset.BlenderKey.FeaturesToLoad; import com.jme3.light.DirectionalLight; import com.jme3.light.Light; @@ -53,6 +58,7 @@ import com.jme3.scene.Spatial.CullHint; import com.jme3.scene.plugins.blender.AbstractBlenderHelper; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext.LoadedFeatureDataType; +import com.jme3.scene.plugins.blender.animations.ArmatureHelper; import com.jme3.scene.plugins.blender.cameras.CameraHelper; import com.jme3.scene.plugins.blender.constraints.Constraint; import com.jme3.scene.plugins.blender.constraints.ConstraintHelper; @@ -233,6 +239,31 @@ public class ObjectHelper extends AbstractBlenderHelper { } break; case OBJECT_TYPE_ARMATURE: + //load the skeleton first and store it in the blender context + Structure armatureStructure = ((Pointer) objectStructure.getFieldValue("data")).fetchData(blenderContext.getInputStream()).get(0); + Structure pose = ((Pointer) objectStructure.getFieldValue("pose")).fetchData(blenderContext.getInputStream()).get(0); + List chanbase = ((Structure) pose.getFieldValue("chanbase")).evaluateListBase(blenderContext); + + Map bonesPoseChannels = new HashMap(chanbase.size()); + for (Structure poseChannel : chanbase) { + Pointer pBone = (Pointer) poseChannel.getFieldValue("bone"); + bonesPoseChannels.put(pBone.getOldMemoryAddress(), poseChannel); + } + + Matrix4f armatureObjectMatrix = this.getMatrix(objectStructure, "obmat", true); + Matrix4f inverseMeshObjectMatrix = this.getMatrix(objectStructure, "obmat", true).invertLocal(); + Matrix4f objectToArmatureTransformation = armatureObjectMatrix.multLocal(inverseMeshObjectMatrix); + + List bonebase = ((Structure) armatureStructure.getFieldValue("bonebase")).evaluateListBase(blenderContext); + ArmatureHelper armatureHelper = blenderContext.getHelper(ArmatureHelper.class); + List bonesList = new ArrayList(); + for (int i = 0; i < bonebase.size(); ++i) { + armatureHelper.buildBones(bonebase.get(i), null, bonesList, objectToArmatureTransformation, bonesPoseChannels, blenderContext); + } + bonesList.add(0, new Bone("")); + Skeleton skeleton = new Skeleton(bonesList.toArray(new Bone[bonesList.size()])); + blenderContext.setSkeleton(objectStructure.getOldMemoryAddress(), skeleton); + //need to create an empty node to properly create parent-children relationships between nodes Node armature = new Node(name); armature.setLocalTransform(t);