소스 검색

Making sure that bone constraint will target either object or bone in its own armature. Allowing bone to target object (and not only bone as it was until now).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10397 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl 12 년 전
부모
커밋
dcd5fd5b4e

+ 3 - 2
engine/src/blender/com/jme3/scene/plugins/blender/animations/ArmatureHelper.java

@@ -35,6 +35,7 @@ import com.jme3.animation.Bone;
 import com.jme3.animation.BoneTrack;
 import com.jme3.animation.Skeleton;
 import com.jme3.math.Matrix4f;
+import com.jme3.scene.Spatial;
 import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
 import com.jme3.scene.plugins.blender.BlenderContext;
 import com.jme3.scene.plugins.blender.curves.BezierCurve;
@@ -92,8 +93,8 @@ public class ArmatureHelper extends AbstractBlenderHelper {
 	 *             an exception is thrown when there is problem with the blender
 	 *             file
 	 */
-	public void buildBones(Structure boneStructure, Bone parent, List<Bone> result, Matrix4f arbt, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
-		BoneContext bc = new BoneContext(boneStructure, arbt, bonesPoseChannels, blenderContext);
+	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);
 	}
 

+ 22 - 7
engine/src/blender/com/jme3/scene/plugins/blender/animations/BoneContext.java

@@ -1,5 +1,9 @@
 package com.jme3.scene.plugins.blender.animations;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
 import com.jme3.animation.Bone;
 import com.jme3.math.Matrix4f;
 import com.jme3.math.Quaternion;
@@ -10,9 +14,6 @@ import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 import com.jme3.scene.plugins.blender.file.DynamicArray;
 import com.jme3.scene.plugins.blender.file.Structure;
 import com.jme3.scene.plugins.blender.objects.ObjectHelper;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
 
 /**
  * This class holds the basic data that describes a bone.
@@ -20,6 +21,8 @@ import java.util.Map;
  * @author Marcin Roguski (Kaelthas)
  */
 public class BoneContext {
+	/** The OMA of the bone's armature object. */
+	private Long 				armatureObjectOMA;
 	/** The structure of the bone. */
 	private Structure			boneStructure;
 	/** Bone's pose channel structure. */
@@ -48,6 +51,8 @@ public class BoneContext {
 	/**
 	 * Constructor. Creates the basic set of bone's data.
 	 * 
+	 * @param armatureObjectOMA
+	 * 			  the OMA of the bone's armature object
 	 * @param boneStructure
 	 *            the bone's structure
 	 * @param objectToArmatureMatrix
@@ -60,8 +65,8 @@ public class BoneContext {
 	 *             an exception is thrown when problem with blender data reading
 	 *             occurs
 	 */
-	public BoneContext(Structure boneStructure, Matrix4f objectToArmatureMatrix, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
-		this(boneStructure, null, objectToArmatureMatrix, bonesPoseChannels, blenderContext);
+	public BoneContext(Long armatureObjectOMA, Structure boneStructure, Matrix4f objectToArmatureMatrix, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
+		this(boneStructure, armatureObjectOMA, null, objectToArmatureMatrix, bonesPoseChannels, blenderContext);
 	}
 
 	/**
@@ -69,6 +74,8 @@ public class BoneContext {
 	 * 
 	 * @param boneStructure
 	 *            the bone's structure
+	 * @param armatureObjectOMA
+	 *            the OMA of the bone's armature object
 	 * @param parent
 	 *            bone's parent (null if the bone is the root bone)
 	 * @param objectToArmatureMatrix
@@ -81,9 +88,10 @@ public class BoneContext {
 	 *             an exception is thrown when problem with blender data reading
 	 *             occurs
 	 */
-	private BoneContext(Structure boneStructure, BoneContext parent, Matrix4f objectToArmatureMatrix, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
+	private BoneContext(Structure boneStructure, Long armatureObjectOMA, BoneContext parent, Matrix4f objectToArmatureMatrix, final Map<Long, Structure> bonesPoseChannels, BlenderContext blenderContext) throws BlenderFileException {
 		this.parent = parent;
 		this.boneStructure = boneStructure;
+		this.armatureObjectOMA = armatureObjectOMA;
 		boneName = boneStructure.getFieldValue("name").toString();
 		ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
 		armatureMatrix = objectHelper.getMatrix(boneStructure, "arm_mat", true);
@@ -92,7 +100,7 @@ public class BoneContext {
 		this.computeRestMatrix(objectToArmatureMatrix);
 		List<Structure> childbase = ((Structure) boneStructure.getFieldValue("childbase")).evaluateListBase(blenderContext);
 		for (Structure child : childbase) {
-			this.children.add(new BoneContext(child, this, objectToArmatureMatrix, bonesPoseChannels, blenderContext));
+			this.children.add(new BoneContext(child, armatureObjectOMA, this, objectToArmatureMatrix, bonesPoseChannels, blenderContext));
 		}
 
 		poseChannel = bonesPoseChannels.get(boneStructure.getOldMemoryAddress());
@@ -207,4 +215,11 @@ public class BoneContext {
 	public Long getBoneOma() {
 		return boneStructure.getOldMemoryAddress();	
 	}
+	
+	/**
+	 * @return OMA of the bone's armature object
+	 */
+	public Long getArmatureObjectOMA() {
+		return armatureObjectOMA;
+	}
 }

+ 98 - 47
engine/src/blender/com/jme3/scene/plugins/blender/constraints/BoneConstraint.java

@@ -1,6 +1,7 @@
 package com.jme3.scene.plugins.blender.constraints;
 
 import java.util.Arrays;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.jme3.animation.Animation;
@@ -10,14 +11,15 @@ import com.jme3.animation.Track;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Transform;
 import com.jme3.math.Vector3f;
+import com.jme3.scene.Spatial;
 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.animations.BoneContext;
 import com.jme3.scene.plugins.blender.animations.Ipo;
 import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space;
 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 import com.jme3.scene.plugins.blender.file.Structure;
-import com.jme3.scene.plugins.blender.objects.ObjectHelper;
 import com.jme3.scene.plugins.ogre.AnimData;
 
 /**
@@ -26,52 +28,97 @@ import com.jme3.scene.plugins.ogre.AnimData;
  */
 /*package*/ class BoneConstraint extends Constraint {
 	private static final Logger LOGGER = Logger.getLogger(BoneConstraint.class.getName());
-	/** The OMA of the target armature. */
-	protected Long targetArmatureOMA;
 	
+	protected boolean isNodeTarget;
+	
+	/**
+	 * The bone constraint constructor.
+	 * 
+	 * @param constraintStructure
+	 *            the constraint's structure
+	 * @param ownerOMA
+	 *            the OMA of the bone that owns the constraint
+	 * @param influenceIpo
+	 *            the influence interpolation curve
+	 * @param blenderContext
+	 *            the blender context
+	 * @throws BlenderFileException
+	 *             exception thrown when problems with blender file occur
+	 */
 	public BoneConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext)
 			throws BlenderFileException {
 		super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
-		targetArmatureOMA = targetOMA;
-		if(targetArmatureOMA != null && targetArmatureOMA <= 0L) {
-			targetArmatureOMA = null;
-		}
-		targetOMA = null;
-		if(targetArmatureOMA != null && targetArmatureOMA > 0L && (subtargetName == null || subtargetName.length() == 0)) {
-			invalid = true;
-		}
 	}
 
 	@Override
-	public void performBakingOperation() {
-		Bone owner = blenderContext.getBoneContext(ownerOMA).getBone();
-		Bone target = null;
-		
-		if(targetArmatureOMA != null) {//first make sure the target is loaded
-			ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
-			try {
-				objectHelper.toObject((Structure) blenderContext.getLoadedFeature(targetArmatureOMA, LoadedFeatureDataType.LOADED_STRUCTURE), blenderContext);
-			} catch (BlenderFileException e) {
-				LOGGER.warning("Problems occured during target object loading. The constraint " + name + " will not be applied.");
-				return ;
+	protected boolean validate() {
+		if(targetOMA != null) {
+			Spatial nodeTarget = (Spatial)blenderContext.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
+			//the second part of the if expression verifies if the found node (if any) is an armature node
+			if(nodeTarget == null || nodeTarget.getUserData(ArmatureHelper.ARMETURE_NODE_MARKER) != null) {
+				//if the target is not an object node then it is an Armature, so make sure the bone is in the current skeleton
+				BoneContext boneContext = blenderContext.getBoneContext(ownerOMA);
+				if(targetOMA.longValue() != boneContext.getArmatureObjectOMA().longValue()) {
+					LOGGER.log(Level.WARNING, "Bone constraint {0} must target bone in the its own skeleton! Targeting bone in another skeleton is not supported!", name);
+					return false;
+				}
+			} else {
+				isNodeTarget = true;
 			}
-			
-			BoneContext boneContext = blenderContext.getBoneByName(subtargetName);
-			target = boneContext.getBone();
-			this.targetOMA = boneContext.getBoneOma();
 		}
 		
-		this.prepareTracksForApplyingConstraints();
-		AnimData animData = blenderContext.getAnimData(ownerOMA);
-		if(animData != null) {
-			for(Animation animation : animData.anims) {
-				Transform ownerTransform = constraintHelper.getBoneTransform(ownerSpace, owner);
-				Transform targetTransform = target != null ? constraintHelper.getBoneTransform(targetSpace, target) : null;
-				
-				BoneTrack boneTrack = constraintHelper.getTrack(owner, animData.skeleton, animation);
-				BoneTrack targetTrack = target != null ? constraintHelper.getTrack(target, animData.skeleton, animation) : null;
+		return true;
+	}
+	
+	@Override
+	public void performBakingOperation() {
+		Bone owner = blenderContext.getBoneContext(ownerOMA).getBone();
+		
+		if(targetOMA != null) {
+			if(isNodeTarget) {
+				Spatial target = (Spatial) blenderContext.getLoadedFeature(targetOMA, LoadedFeatureDataType.LOADED_FEATURE);
+				this.prepareTracksForApplyingConstraints();
+				AnimData animData = blenderContext.getAnimData(ownerOMA);
+				if(animData != null) {
+					for(Animation animation : animData.anims) {
+						Transform ownerTransform = constraintHelper.getBoneTransform(ownerSpace, owner);
+						Transform targetTransform = constraintHelper.getNodeObjectTransform(targetSpace, targetOMA, blenderContext);
+						
+						Track boneTrack = constraintHelper.getTrack(owner, animData.skeleton, animation);
+						Track targetTrack = constraintHelper.getTrack(target, animation);
+						
+						constraintDefinition.bake(ownerTransform, targetTransform, boneTrack, targetTrack, this.ipo);
+					}
+				}
+			} else {
+				BoneContext boneContext = blenderContext.getBoneByName(subtargetName);
+				Bone target = boneContext.getBone();
+				this.targetOMA = boneContext.getBoneOma();
 				
-				constraintDefinition.bake(ownerTransform, targetTransform, boneTrack, targetTrack, this.ipo);
+				this.prepareTracksForApplyingConstraints();
+				AnimData animData = blenderContext.getAnimData(ownerOMA);
+				if(animData != null) {
+					for(Animation animation : animData.anims) {
+						Transform ownerTransform = constraintHelper.getBoneTransform(ownerSpace, owner);
+						Transform targetTransform = constraintHelper.getBoneTransform(targetSpace, target);
+						
+						Track boneTrack = constraintHelper.getTrack(owner, animData.skeleton, animation);
+						Track targetTrack = constraintHelper.getTrack(target, animData.skeleton, animation);
+						
+						constraintDefinition.bake(ownerTransform, targetTransform, boneTrack, targetTrack, this.ipo);
+					}
+				}
+			}
+		} else {
+			this.prepareTracksForApplyingConstraints();
+			AnimData animData = blenderContext.getAnimData(ownerOMA);
+			if(animData != null) {
+				for(Animation animation : animData.anims) {
+					Transform ownerTransform = constraintHelper.getBoneTransform(ownerSpace, owner);
+					Track boneTrack = constraintHelper.getTrack(owner, animData.skeleton, animation);
+					
+					constraintDefinition.bake(ownerTransform, null, boneTrack, null, this.ipo);
+				}
 			}
 		}
 	}
@@ -112,21 +159,25 @@ import com.jme3.scene.plugins.ogre.AnimData;
 	/**
 	 * The method determines if the bone has animations.
 	 * 
-	 * @param boneOMA
-	 *            OMA of the bone
-	 * @return <b>true</b> if the bone has animations and <b>false</b> otherwise
+	 * @param animOwnerOMA
+	 *            OMA of the animation's owner
+	 * @return <b>true</b> if the target has animations and <b>false</b> otherwise
 	 */
-	protected boolean hasAnimation(Long boneOMA) {
-		AnimData animData = blenderContext.getAnimData(boneOMA);
+	protected boolean hasAnimation(Long animOwnerOMA) {
+		AnimData animData = blenderContext.getAnimData(animOwnerOMA);
 		if(animData != null) {
-			Bone bone = blenderContext.getBoneContext(boneOMA).getBone();
-			int boneIndex = animData.skeleton.getBoneIndex(bone);
-			for(Animation animation : animData.anims) {
-				for(Track track : animation.getTracks()) {
-					if(track instanceof BoneTrack && ((BoneTrack) track).getTargetBoneIndex() == boneIndex) {
-						return true;
+			if(!isNodeTarget) {
+				Bone bone = blenderContext.getBoneContext(animOwnerOMA).getBone();
+				int boneIndex = animData.skeleton.getBoneIndex(bone);
+				for(Animation animation : animData.anims) {
+					for(Track track : animation.getTracks()) {
+						if(track instanceof BoneTrack && ((BoneTrack) track).getTargetBoneIndex() == boneIndex) {
+							return true;
+						}
 					}
 				}
+			} else {
+				return true;
 			}
 		}
 		return false;

+ 7 - 3
engine/src/blender/com/jme3/scene/plugins/blender/constraints/Constraint.java

@@ -21,8 +21,6 @@ import com.jme3.scene.plugins.blender.file.Structure;
 public abstract class Constraint {
 	private static final Logger LOGGER = Logger.getLogger(Constraint.class.getName());
 	
-	/** Indicates if the constraint is invalid. */
-	protected boolean invalid;
 	/** The name of this constraint. */
 	protected final String name;
 	/** Indicates if the constraint is already baked or not. */
@@ -89,7 +87,7 @@ public abstract class Constraint {
 	 * order is kept.
 	 */
 	public void bake() {
-		if(invalid) {
+		if(!this.validate()) {
 			LOGGER.warning("The constraint " + name + " is invalid and will not be applied.");
 		} else if(!baked) {
 			if(targetOMA != null) {
@@ -108,6 +106,12 @@ public abstract class Constraint {
 		}
 	}
 	
+	/**
+	 * Performs validation before baking. Checks factors that can prevent constraint from baking that could not be
+	 * checked during constraint loading.
+	 */
+	protected abstract boolean validate();
+	
 	/**
 	 * This method should be overwridden and perform the baking opertion.
 	 */

+ 5 - 0
engine/src/blender/com/jme3/scene/plugins/blender/constraints/SkeletonConstraint.java

@@ -27,6 +27,11 @@ import com.jme3.scene.plugins.blender.file.Structure;
 		LOGGER.warning("Applying constraints to skeleton is not supported.");
 	}
 
+	@Override
+	protected boolean validate() {
+		return true;
+	}
+	
 	@Override
 	protected void prepareTracksForApplyingConstraints() { }
 }

+ 0 - 1
engine/src/blender/com/jme3/scene/plugins/blender/constraints/SpatialConstraint.java

@@ -39,7 +39,6 @@ import com.jme3.scene.plugins.ogre.AnimData;
 	public SpatialConstraint(Structure constraintStructure, Long ownerOMA, Ipo influenceIpo, BlenderContext blenderContext)
 			throws BlenderFileException {
 		super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
-		targetOMA = targetArmatureOMA;//spatial constraint uses only targetOMA and not armatureTargetOMA which is set by BoneConstraint
 	}
 	
 	@Override

+ 2 - 1
engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java

@@ -102,11 +102,12 @@ import com.jme3.util.BufferUtils;
 				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(bonebase.get(i), null, bonesList, objectToArmatureTransformation, bonesPoseChannels, blenderContext);
+					armatureHelper.buildBones(armatureObject.getOldMemoryAddress(), bonebase.get(i), null, bonesList, objectToArmatureTransformation, bonesPoseChannels, blenderContext);
 				}
 				bonesList.add(0, new Bone(""));
 				Bone[] bones = bonesList.toArray(new Bone[bonesList.size()]);
 				skeleton = new Skeleton(bones);
+				blenderContext.setSkeleton(armatureObject.getOldMemoryAddress(), skeleton);
 				this.objectStructure = objectStructure;
 				this.meshStructure = meshStructure;