changeset 4278:c6a7452039b6

Joints' transforms were sometimes not marked dirty when they were; this caused the animation of multiple meshes to be desynchronized.
author Alex X. Lee
date Thu, 11 Jul 2013 18:23:34 -0700
parents 6c8c11e19315
children b5a930c2fd82
files apps/experiments/3DViewer/src/main/java/com/javafx/experiments/shape3d/SkinningMesh.java
diffstat 1 files changed, 22 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/shape3d/SkinningMesh.java	Thu Jul 11 16:49:50 2013 -0700
+++ b/apps/experiments/3DViewer/src/main/java/com/javafx/experiments/shape3d/SkinningMesh.java	Thu Jul 11 18:23:34 2013 -0700
@@ -3,7 +3,9 @@
 
 import com.javafx.experiments.importers.maya.Joint;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import javafx.beans.InvalidationListener;
 import javafx.beans.Observable;
 import javafx.collections.ObservableFloatArray;
@@ -92,15 +94,27 @@
                 relativePoints[j][3*i+2] = (float) relativePoint.getZ();
             }
         }
-        
-        // Add a listener to all the joints so that we can track when any of their transforms have changed
-        for (Joint joint : joints) {
-            joint.localToParentTransformProperty().addListener(new InvalidationListener() {
-                @Override
-                public void invalidated(Observable observable) {
-                    jointsTransformDirty = true;
+
+        // Add a listener to all the joints (and their parents nodes) so that we can track when any of their transforms have changed
+        // Set of joints that already have a listener (so we don't attach a listener to the same node more than once)
+        Set<Node> processedNodes = new HashSet<Node>(joints.size());
+        InvalidationListener invalidationListener = new InvalidationListener() {
+            @Override
+            public void invalidated(Observable observable) {
+                jointsTransformDirty = true;
+            }
+        };
+        for (int j = 0; j < joints.size(); j++) {
+            Node node = joints.get(j);
+            while (!processedNodes.contains(node)) {
+                node.localToParentTransformProperty().addListener(invalidationListener);
+                processedNodes.add(node);
+                // Don't check for nodes above the jointForest
+                if (jointForest.contains(node)) {
+                    break;
                 }
-            });
+                node = node.getParent();
+            }
         }
     }