浏览代码

Bugfix: avoiding infinite loops while applying constraints.

jmekaelthas 10 年之前
父节点
当前提交
b0e751c81a
共有 1 个文件被更改,包括 37 次插入32 次删除
  1. 37 32
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SimulationNode.java

+ 37 - 32
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SimulationNode.java

@@ -7,6 +7,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.Stack;
 import java.util.logging.Logger;
 
 import com.jme3.animation.AnimChannel;
@@ -38,9 +39,9 @@ import com.jme3.util.TempVars;
  * @author Marcin Roguski (Kaelthas)
  */
 public class SimulationNode {
-    private static final Logger  LOGGER   = Logger.getLogger(SimulationNode.class.getName());
+    private static final Logger LOGGER = Logger.getLogger(SimulationNode.class.getName());
 
-    private Long featureOMA;
+    private Long                 featureOMA;
     /** The blender context. */
     private BlenderContext       blenderContext;
     /** The name of the node (for debugging purposes). */
@@ -51,11 +52,11 @@ public class SimulationNode {
     private List<Animation>      animations;
 
     /** The nodes spatial (if null then the boneContext should be set). */
-    private Spatial              spatial;
+    private Spatial     spatial;
     /** The skeleton of the bone (not null if the node simulated the bone). */
-    private Skeleton             skeleton;
+    private Skeleton    skeleton;
     /** Animation controller for the node's feature. */
-    private AnimControl          animControl;
+    private AnimControl animControl;
 
     /**
      * The star transform of a spatial. Needed to properly reset the spatial to
@@ -64,7 +65,7 @@ public class SimulationNode {
     private Transform            spatialStartTransform;
     /** Star transformations for bones. Needed to properly reset the bones. */
     private Map<Bone, Transform> boneStartTransforms;
-    
+
     /**
      * Builds the nodes tree for the given feature. The feature (bone or
      * spatial) is found by its OMA. The feature must be a root bone or a root
@@ -208,8 +209,7 @@ public class SimulationNode {
         if (animations != null) {
             TempVars vars = TempVars.get();
             AnimChannel animChannel = animControl.createChannel();
-            
-            // List<Bone> bonesWithConstraints = this.collectBonesWithConstraints(skeleton);
+
             for (Animation animation : animations) {
                 float[] animationTimeBoundaries = this.computeAnimationTimeBoundaries(animation);
                 int maxFrame = (int) animationTimeBoundaries[0];
@@ -233,7 +233,7 @@ public class SimulationNode {
                     for (Bone rootBone : skeleton.getRoots()) {
                         // ignore the 0-indexed bone
                         if (skeleton.getBoneIndex(rootBone) > 0) {
-                            this.applyConstraints(rootBone, alteredOmas, applied, frame);
+                            this.applyConstraints(rootBone, alteredOmas, applied, frame, new Stack<Bone>());
                         }
                     }
 
@@ -294,34 +294,39 @@ public class SimulationNode {
      *            the set of OMAS of the altered bones (is populated if necessary)
      * @param frame
      *            the current frame of the animation
+     * @param bonesStack
+     *            the stack of bones used to avoid infinite loops while applying constraints
      */
-    private void applyConstraints(Bone bone, Set<Long> alteredOmas, Set<Long> applied, int frame) {
-        BoneContext boneContext = blenderContext.getBoneContext(bone);
-        if(!applied.contains(boneContext.getBoneOma())) {
-            List<Constraint> constraints = this.findConstraints(boneContext.getBoneOma(), blenderContext);
-            if (constraints != null && constraints.size() > 0) {
-                // TODO: BEWARE OF INFINITE LOOPS !!!!!!!!!!!!!!!!!!!!!!!!!!
-                for (Constraint constraint : constraints) {
-                    if (constraint.getTargetOMA() != null && constraint.getTargetOMA() > 0L) {
-                        // first apply constraints of the target bone
-                        BoneContext targetBone = blenderContext.getBoneContext(constraint.getTargetOMA());
-                        this.applyConstraints(targetBone.getBone(), alteredOmas, applied, frame);
-                    }
-                    constraint.apply(frame);
-                    if (constraint.getAlteredOmas() != null) {
-                        alteredOmas.addAll(constraint.getAlteredOmas());
+    private void applyConstraints(Bone bone, Set<Long> alteredOmas, Set<Long> applied, int frame, Stack<Bone> bonesStack) {
+        if (!bonesStack.contains(bone)) {
+            bonesStack.push(bone);
+            BoneContext boneContext = blenderContext.getBoneContext(bone);
+            if (!applied.contains(boneContext.getBoneOma())) {
+                List<Constraint> constraints = this.findConstraints(boneContext.getBoneOma(), blenderContext);
+                if (constraints != null && constraints.size() > 0) {
+                    for (Constraint constraint : constraints) {
+                        if (constraint.getTargetOMA() != null && constraint.getTargetOMA() > 0L) {
+                            // first apply constraints of the target bone
+                            BoneContext targetBone = blenderContext.getBoneContext(constraint.getTargetOMA());
+                            this.applyConstraints(targetBone.getBone(), alteredOmas, applied, frame, bonesStack);
+                        }
+                        constraint.apply(frame);
+                        if (constraint.getAlteredOmas() != null) {
+                            alteredOmas.addAll(constraint.getAlteredOmas());
+                        }
+                        alteredOmas.add(boneContext.getBoneOma());
                     }
-                    alteredOmas.add(boneContext.getBoneOma());
                 }
+                applied.add(boneContext.getBoneOma());
             }
-            applied.add(boneContext.getBoneOma());
-        }
-        
-        List<Bone> children = bone.getChildren();
-        if (children != null && children.size() > 0) {
-            for (Bone child : bone.getChildren()) {
-                this.applyConstraints(child, alteredOmas, applied, frame);
+
+            List<Bone> children = bone.getChildren();
+            if (children != null && children.size() > 0) {
+                for (Bone child : bone.getChildren()) {
+                    this.applyConstraints(child, alteredOmas, applied, frame, bonesStack);
+                }
             }
+            bonesStack.pop();
         }
     }