|
@@ -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) {
|
|
|
|
- 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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|