|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
- * Copyright (c) 2009-2012 jMonkeyEngine
|
|
|
|
|
|
+ * Copyright (c) 2009-2017 jMonkeyEngine
|
|
* All rights reserved.
|
|
* All rights reserved.
|
|
*
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -33,7 +33,9 @@ package com.jme3.animation;
|
|
|
|
|
|
import com.jme3.export.*;
|
|
import com.jme3.export.*;
|
|
import com.jme3.math.*;
|
|
import com.jme3.math.*;
|
|
|
|
+import com.jme3.scene.Geometry;
|
|
import com.jme3.scene.Node;
|
|
import com.jme3.scene.Node;
|
|
|
|
+import com.jme3.scene.Spatial;
|
|
import com.jme3.util.TempVars;
|
|
import com.jme3.util.TempVars;
|
|
import com.jme3.util.clone.JmeCloneable;
|
|
import com.jme3.util.clone.JmeCloneable;
|
|
import com.jme3.util.clone.Cloner;
|
|
import com.jme3.util.clone.Cloner;
|
|
@@ -80,7 +82,10 @@ public final class Bone implements Savable, JmeCloneable {
|
|
* The attachment node.
|
|
* The attachment node.
|
|
*/
|
|
*/
|
|
private Node attachNode;
|
|
private Node attachNode;
|
|
-
|
|
|
|
|
|
+ /**
|
|
|
|
+ * A geometry animated by this node, used when updating the attachments node.
|
|
|
|
+ */
|
|
|
|
+ private Geometry targetGeometry = null;
|
|
/**
|
|
/**
|
|
* Bind transform is the local bind transform of this bone. (local space)
|
|
* Bind transform is the local bind transform of this bone. (local space)
|
|
*/
|
|
*/
|
|
@@ -187,7 +192,8 @@ public final class Bone implements Savable, JmeCloneable {
|
|
this.children = cloner.clone(children);
|
|
this.children = cloner.clone(children);
|
|
|
|
|
|
this.attachNode = cloner.clone(attachNode);
|
|
this.attachNode = cloner.clone(attachNode);
|
|
-
|
|
|
|
|
|
+ this.targetGeometry = cloner.clone(targetGeometry);
|
|
|
|
+
|
|
this.bindPos = cloner.clone(bindPos);
|
|
this.bindPos = cloner.clone(bindPos);
|
|
this.bindRot = cloner.clone(bindRot);
|
|
this.bindRot = cloner.clone(bindRot);
|
|
this.bindScale = cloner.clone(bindScale);
|
|
this.bindScale = cloner.clone(bindScale);
|
|
@@ -505,9 +511,39 @@ public final class Bone implements Savable, JmeCloneable {
|
|
}
|
|
}
|
|
|
|
|
|
if (attachNode != null) {
|
|
if (attachNode != null) {
|
|
|
|
+ updateAttachNode();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Update the local transform of the attachments node.
|
|
|
|
+ */
|
|
|
|
+ private void updateAttachNode() {
|
|
|
|
+ Node attachParent = attachNode.getParent();
|
|
|
|
+ if (attachParent == null || targetGeometry == null
|
|
|
|
+ || targetGeometry.getParent() == attachParent
|
|
|
|
+ && targetGeometry.getLocalTransform().isIdentity()) {
|
|
|
|
+ /*
|
|
|
|
+ * The animated meshes are in the same coordinate system as the
|
|
|
|
+ * attachments node: no further transforms are needed.
|
|
|
|
+ */
|
|
attachNode.setLocalTranslation(modelPos);
|
|
attachNode.setLocalTranslation(modelPos);
|
|
attachNode.setLocalRotation(modelRot);
|
|
attachNode.setLocalRotation(modelRot);
|
|
attachNode.setLocalScale(modelScale);
|
|
attachNode.setLocalScale(modelScale);
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ Spatial loopSpatial = targetGeometry;
|
|
|
|
+ Transform combined = new Transform(modelPos, modelRot, modelScale);
|
|
|
|
+ /*
|
|
|
|
+ * Climb the scene graph applying local transforms until the
|
|
|
|
+ * attachments node's parent is reached.
|
|
|
|
+ */
|
|
|
|
+ while (loopSpatial != attachParent && loopSpatial != null) {
|
|
|
|
+ Transform localTransform = loopSpatial.getLocalTransform();
|
|
|
|
+ combined.combineWithParent(localTransform);
|
|
|
|
+ loopSpatial = loopSpatial.getParent();
|
|
|
|
+ }
|
|
|
|
+ attachNode.setLocalTransform(combined);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -661,15 +697,21 @@ public final class Bone implements Savable, JmeCloneable {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Returns the attachment node.
|
|
|
|
- * Attach models and effects to this node to make
|
|
|
|
- * them follow this bone's motions.
|
|
|
|
|
|
+ * Access the attachments node of this bone. If this bone doesn't already
|
|
|
|
+ * have an attachments node, create one. Models and effects attached to the
|
|
|
|
+ * attachments node will follow this bone's motions.
|
|
|
|
+ *
|
|
|
|
+ * @param target a geometry animated by this bone, or null to indicate that
|
|
|
|
+ * all geometries affected by this bone have the same global transform as
|
|
|
|
+ * the attachment node's parent
|
|
*/
|
|
*/
|
|
- Node getAttachmentsNode() {
|
|
|
|
|
|
+ Node getAttachmentsNode(Geometry target) {
|
|
if (attachNode == null) {
|
|
if (attachNode == null) {
|
|
attachNode = new Node(name + "_attachnode");
|
|
attachNode = new Node(name + "_attachnode");
|
|
attachNode.setUserData("AttachedBone", this);
|
|
attachNode.setUserData("AttachedBone", this);
|
|
}
|
|
}
|
|
|
|
+ targetGeometry = target;
|
|
|
|
+
|
|
return attachNode;
|
|
return attachNode;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -823,6 +865,7 @@ public final class Bone implements Savable, JmeCloneable {
|
|
}
|
|
}
|
|
|
|
|
|
attachNode = (Node) input.readSavable("attachNode", null);
|
|
attachNode = (Node) input.readSavable("attachNode", null);
|
|
|
|
+ targetGeometry = (Geometry) input.readSavable("targetGeometry", null);
|
|
|
|
|
|
localPos.set(bindPos);
|
|
localPos.set(bindPos);
|
|
localRot.set(bindRot);
|
|
localRot.set(bindRot);
|
|
@@ -845,6 +888,7 @@ public final class Bone implements Savable, JmeCloneable {
|
|
|
|
|
|
output.write(name, "name", null);
|
|
output.write(name, "name", null);
|
|
output.write(attachNode, "attachNode", null);
|
|
output.write(attachNode, "attachNode", null);
|
|
|
|
+ output.write(targetGeometry, "targetGeometry", null);
|
|
output.write(bindPos, "bindPos", null);
|
|
output.write(bindPos, "bindPos", null);
|
|
output.write(bindRot, "bindRot", null);
|
|
output.write(bindRot, "bindRot", null);
|
|
output.write(bindScale, "bindScale", new Vector3f(1.0f, 1.0f, 1.0f));
|
|
output.write(bindScale, "bindScale", new Vector3f(1.0f, 1.0f, 1.0f));
|