Bugfix: avoiding infinite loops while applying constraints.

experimental
jmekaelthas 10 years ago
parent 2d9a1b8737
commit b0e751c81a
  1. 69
      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;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.Stack;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.jme3.animation.AnimChannel; import com.jme3.animation.AnimChannel;
@ -38,9 +39,9 @@ import com.jme3.util.TempVars;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
public class SimulationNode { 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. */ /** The blender context. */
private BlenderContext blenderContext; private BlenderContext blenderContext;
/** The name of the node (for debugging purposes). */ /** The name of the node (for debugging purposes). */
@ -51,11 +52,11 @@ public class SimulationNode {
private List<Animation> animations; private List<Animation> animations;
/** The nodes spatial (if null then the boneContext should be set). */ /** 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). */ /** 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. */ /** 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 * The star transform of a spatial. Needed to properly reset the spatial to
@ -64,7 +65,7 @@ public class SimulationNode {
private Transform spatialStartTransform; private Transform spatialStartTransform;
/** Star transformations for bones. Needed to properly reset the bones. */ /** Star transformations for bones. Needed to properly reset the bones. */
private Map<Bone, Transform> boneStartTransforms; private Map<Bone, Transform> boneStartTransforms;
/** /**
* Builds the nodes tree for the given feature. The feature (bone or * 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 * 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) { if (animations != null) {
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
AnimChannel animChannel = animControl.createChannel(); AnimChannel animChannel = animControl.createChannel();
// List<Bone> bonesWithConstraints = this.collectBonesWithConstraints(skeleton);
for (Animation animation : animations) { for (Animation animation : animations) {
float[] animationTimeBoundaries = this.computeAnimationTimeBoundaries(animation); float[] animationTimeBoundaries = this.computeAnimationTimeBoundaries(animation);
int maxFrame = (int) animationTimeBoundaries[0]; int maxFrame = (int) animationTimeBoundaries[0];
@ -233,7 +233,7 @@ public class SimulationNode {
for (Bone rootBone : skeleton.getRoots()) { for (Bone rootBone : skeleton.getRoots()) {
// ignore the 0-indexed bone // ignore the 0-indexed bone
if (skeleton.getBoneIndex(rootBone) > 0) { 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) * the set of OMAS of the altered bones (is populated if necessary)
* @param frame * @param frame
* the current frame of the animation * 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) { private void applyConstraints(Bone bone, Set<Long> alteredOmas, Set<Long> applied, int frame, Stack<Bone> bonesStack) {
BoneContext boneContext = blenderContext.getBoneContext(bone); if (!bonesStack.contains(bone)) {
if(!applied.contains(boneContext.getBoneOma())) { bonesStack.push(bone);
List<Constraint> constraints = this.findConstraints(boneContext.getBoneOma(), blenderContext); BoneContext boneContext = blenderContext.getBoneContext(bone);
if (constraints != null && constraints.size() > 0) { if (!applied.contains(boneContext.getBoneOma())) {
// TODO: BEWARE OF INFINITE LOOPS !!!!!!!!!!!!!!!!!!!!!!!!!! List<Constraint> constraints = this.findConstraints(boneContext.getBoneOma(), blenderContext);
for (Constraint constraint : constraints) { if (constraints != null && constraints.size() > 0) {
if (constraint.getTargetOMA() != null && constraint.getTargetOMA() > 0L) { for (Constraint constraint : constraints) {
// first apply constraints of the target bone if (constraint.getTargetOMA() != null && constraint.getTargetOMA() > 0L) {
BoneContext targetBone = blenderContext.getBoneContext(constraint.getTargetOMA()); // first apply constraints of the target bone
this.applyConstraints(targetBone.getBone(), alteredOmas, applied, frame); BoneContext targetBone = blenderContext.getBoneContext(constraint.getTargetOMA());
} this.applyConstraints(targetBone.getBone(), alteredOmas, applied, frame, bonesStack);
constraint.apply(frame); }
if (constraint.getAlteredOmas() != null) { constraint.apply(frame);
alteredOmas.addAll(constraint.getAlteredOmas()); 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) {
List<Bone> children = bone.getChildren(); for (Bone child : bone.getChildren()) {
if (children != null && children.size() > 0) { this.applyConstraints(child, alteredOmas, applied, frame, bonesStack);
for (Bone child : bone.getChildren()) { }
this.applyConstraints(child, alteredOmas, applied, frame);
} }
bonesStack.pop();
} }
} }

Loading…
Cancel
Save