Updated documentation of the Bone class and changed names of the transforms variables and accessors so that they properly describe what they are an are misleading anymore.

Kept old methods as deprecated to not break user code.
Changed all calls to the deprecated methods in the engine.
experimental
Nehon 11 years ago
parent 6d9a7fbcfb
commit 3f43d7832f
  1. 2
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/BoneConstraint.java
  2. 2
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/SimulationNode.java
  3. 4
      jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java
  4. 12
      jme3-bullet/src/common/java/com/jme3/bullet/control/KinematicRagdollControl.java
  5. 2
      jme3-bullet/src/common/java/com/jme3/bullet/control/ragdoll/RagdollUtils.java
  6. 392
      jme3-core/src/main/java/com/jme3/animation/Bone.java

@ -68,6 +68,6 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
@Override @Override
public void apply(int frame) { public void apply(int frame) {
super.apply(frame); super.apply(frame);
blenderContext.getBoneContext(ownerOMA).getBone().updateWorldVectors(); blenderContext.getBoneContext(ownerOMA).getBone().updateModelTransforms();
} }
} }

@ -103,7 +103,7 @@ public class SimulationNode {
boneStartTransforms = new HashMap<Bone, Transform>(); boneStartTransforms = new HashMap<Bone, Transform>();
for (int i = 0; i < skeleton.getBoneCount(); ++i) { for (int i = 0; i < skeleton.getBoneCount(); ++i) {
Bone bone = skeleton.getBone(i); Bone bone = skeleton.getBone(i);
boneStartTransforms.put(bone, new Transform(bone.getWorldBindPosition(), bone.getWorldBindRotation(), bone.getWorldBindScale())); boneStartTransforms.put(bone, new Transform(bone.getBindPosition(), bone.getBindRotation(), bone.getBindScale()));
} }
} else { } else {
if (rootNode && spatial.getParent() != null) { if (rootNode && spatial.getParent() != null) {

@ -49,7 +49,7 @@ public class ConstraintDefinitionIK extends ConstraintDefinition {
for (int i = 0; i < boneContexts.length; ++i) { for (int i = 0; i < boneContexts.length; ++i) {
Bone bone = boneContexts[i].getBone(); Bone bone = boneContexts[i].getBone();
bone.updateWorldVectors(); bone.updateModelTransforms();
Transform boneWorldTransform = constraintHelper.getTransform(boneContexts[i].getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD); Transform boneWorldTransform = constraintHelper.getTransform(boneContexts[i].getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD);
Vector3f head = boneWorldTransform.getTranslation(); Vector3f head = boneWorldTransform.getTranslation();
@ -83,7 +83,7 @@ public class ConstraintDefinitionIK extends ConstraintDefinition {
constraintHelper.applyTransform(boneContexts[i].getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD, boneWorldTransform); constraintHelper.applyTransform(boneContexts[i].getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD, boneWorldTransform);
} }
bone.updateWorldVectors(); bone.updateModelTransforms();
alteredOmas.add(boneContexts[i].getBoneOma()); alteredOmas.add(boneContexts[i].getBoneOma());
} }
} }

@ -225,9 +225,9 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
if (link.bone.getParent() == null) { if (link.bone.getParent() == null) {
//offsetting the physic's position/rotation by the root bone inverse model space position/rotaion //offsetting the physic's position/rotation by the root bone inverse model space position/rotaion
modelPosition.set(p).subtractLocal(link.bone.getWorldBindPosition()); modelPosition.set(p).subtractLocal(link.bone.getBindPosition());
targetModel.getParent().getWorldTransform().transformInverseVector(modelPosition, modelPosition); targetModel.getParent().getWorldTransform().transformInverseVector(modelPosition, modelPosition);
modelRotation.set(q).multLocal(tmpRot2.set(link.bone.getWorldBindRotation()).inverseLocal()); modelRotation.set(q).multLocal(tmpRot2.set(link.bone.getBindRotation()).inverseLocal());
//applying transforms to the model //applying transforms to the model
@ -236,13 +236,13 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
targetModel.setLocalRotation(modelRotation); targetModel.setLocalRotation(modelRotation);
//Applying computed transforms to the bone //Applying computed transforms to the bone
link.bone.setUserTransformsWorld(position, tmpRot1); link.bone.setUserTransformsInModelSpace(position, tmpRot1);
} else { } else {
//if boneList is empty, this means that every bone in the ragdoll has a collision shape, //if boneList is empty, this means that every bone in the ragdoll has a collision shape,
//so we just update the bone position //so we just update the bone position
if (boneList.isEmpty()) { if (boneList.isEmpty()) {
link.bone.setUserTransformsWorld(position, tmpRot1); link.bone.setUserTransformsInModelSpace(position, tmpRot1);
} else { } else {
//boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape. //boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape.
//So we update them recusively //So we update them recusively
@ -278,7 +278,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
if (boneList.isEmpty()) { if (boneList.isEmpty()) {
//we ensure we have the control to update the bone //we ensure we have the control to update the bone
link.bone.setUserControl(true); link.bone.setUserControl(true);
link.bone.setUserTransformsWorld(position, tmpRot1); link.bone.setUserTransformsInModelSpace(position, tmpRot1);
//we give control back to the key framed animation. //we give control back to the key framed animation.
link.bone.setUserControl(false); link.bone.setUserControl(false);
} else { } else {
@ -315,7 +315,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
targetModel.getWorldTransform().transformVector(link.bone.getModelSpacePosition(), position); targetModel.getWorldTransform().transformVector(link.bone.getModelSpacePosition(), position);
//computing rotation //computing rotation
tmpRot1.set(link.bone.getModelSpaceRotation()).multLocal(link.bone.getWorldBindInverseRotation()); tmpRot1.set(link.bone.getModelSpaceRotation()).multLocal(link.bone.getModelBindInverseRotation());
targetModel.getWorldRotation().mult(tmpRot1, tmpRot1); targetModel.getWorldRotation().mult(tmpRot1, tmpRot1);
tmpRot1.normalizeLocal(); tmpRot1.normalizeLocal();

@ -278,7 +278,7 @@ public class RagdollUtils {
bone.setUserControl(true); bone.setUserControl(true);
} }
//we set te user transforms of the bone //we set te user transforms of the bone
bone.setUserTransformsWorld(pos, rot); bone.setUserTransformsInModelSpace(pos, rot);
for (Bone childBone : bone.getChildren()) { for (Bone childBone : bone.getChildren()) {
//each child bone that is not in the list is updated //each child bone that is not in the list is updated
if (!boneList.contains(childBone.getName())) { if (!boneList.contains(childBone.getName())) {

@ -42,11 +42,30 @@ import java.util.ArrayList;
* <code>Bone</code> describes a bone in the bone-weight skeletal animation * <code>Bone</code> describes a bone in the bone-weight skeletal animation
* system. A bone contains a name and an index, as well as relevant * system. A bone contains a name and an index, as well as relevant
* transformation data. * transformation data.
*
* A bone has 3 sets of transforms :
* 1. The bind transforms, that are the transforms of the bone when the skeleton
* is in its rest pose (also called bind pose or T pose in the literature).
* The bind transforms are expressed in Local space meaning relatively to the
* parent bone.
*
* 2. The Local transforms, that are the transforms of the bone once animation
* or user transforms has been applied to the bind pose. The local transforms are
* expressed in Local space meaning relatively to the parent bone.
*
* 3. The Model transforms, that are the transforms of the bone relatives to the
* rootBone of the skeleton. Those transforms are what is needed to apply skinning
* to the mesh the skeleton controls.
* Note that there can be several rootBones in a skeleton. The one considered for
* these transforms is the one that is an ancestor of this bone.
* *
* @author Kirill Vainer * @author Kirill Vainer
* @author Rémy Bouquet
*/ */
public final class Bone implements Savable { public final class Bone implements Savable {
// Version #2: Changed naming of transforms as they were misleading
public static final int SAVABLE_VERSION = 2;
private String name; private String name;
private Bone parent; private Bone parent;
private final ArrayList<Bone> children = new ArrayList<Bone>(); private final ArrayList<Bone> children = new ArrayList<Bone>();
@ -59,35 +78,36 @@ public final class Bone implements Savable {
* The attachment node. * The attachment node.
*/ */
private Node attachNode; private Node attachNode;
/** /**
* Initial transform is the local bind transform of this bone. * Bind transform is the local bind transform of this bone. (local space)
* PARENT SPACE -&gt; BONE SPACE
*/ */
private Vector3f initialPos; private Vector3f bindPos;
private Quaternion initialRot; private Quaternion bindRot;
private Vector3f initialScale; private Vector3f bindScale;
/** /**
* The inverse world bind transform. * The inverse bind transforms of this bone expressed in model space
* BONE SPACE -&gt; MODEL SPACE
*/ */
private Vector3f worldBindInversePos; private Vector3f modelBindInversePos;
private Quaternion worldBindInverseRot; private Quaternion modelBindInverseRot;
private Vector3f worldBindInverseScale; private Vector3f modelBindInverseScale;
/** /**
* The local animated transform combined with the local bind transform and parent world transform * The local animated or user transform combined with the local bind transform
*/ */
private Vector3f localPos = new Vector3f(); private Vector3f localPos = new Vector3f();
private Quaternion localRot = new Quaternion(); private Quaternion localRot = new Quaternion();
private Vector3f localScale = new Vector3f(1.0f, 1.0f, 1.0f); private Vector3f localScale = new Vector3f(1.0f, 1.0f, 1.0f);
/** /**
* MODEL SPACE -&gt; BONE SPACE (in animated state) * The model transforms of this bone
*/ */
private Vector3f worldPos = new Vector3f(); private Vector3f modelPos = new Vector3f();
private Quaternion worldRot = new Quaternion(); private Quaternion modelRot = new Quaternion();
private Vector3f worldScale = new Vector3f(); private Vector3f modelScale = new Vector3f();
// Used for getCombinedTransform // Used for getCombinedTransform
private Transform tmpTransform = new Transform(); private Transform tmpTransform;
/** /**
* Used to handle blending from one animation to another. * Used to handle blending from one animation to another.
@ -107,13 +127,13 @@ public final class Bone implements Savable {
this.name = name; this.name = name;
initialPos = new Vector3f(); bindPos = new Vector3f();
initialRot = new Quaternion(); bindRot = new Quaternion();
initialScale = new Vector3f(1, 1, 1); bindScale = new Vector3f(1, 1, 1);
worldBindInversePos = new Vector3f(); modelBindInversePos = new Vector3f();
worldBindInverseRot = new Quaternion(); modelBindInverseRot = new Quaternion();
worldBindInverseScale = new Vector3f(); modelBindInverseScale = new Vector3f();
} }
/** /**
@ -135,13 +155,13 @@ public final class Bone implements Savable {
userControl = source.userControl; userControl = source.userControl;
initialPos = source.initialPos; bindPos = source.bindPos;
initialRot = source.initialRot; bindRot = source.bindRot;
initialScale = source.initialScale; bindScale = source.bindScale;
worldBindInversePos = source.worldBindInversePos; modelBindInversePos = source.modelBindInversePos;
worldBindInverseRot = source.worldBindInverseRot; modelBindInverseRot = source.modelBindInverseRot;
worldBindInverseScale = source.worldBindInverseScale; modelBindInverseScale = source.modelBindInverseScale;
// parent and children will be assigned manually.. // parent and children will be assigned manually..
} }
@ -211,7 +231,7 @@ public final class Bone implements Savable {
* @return The position of the bone in model space. * @return The position of the bone in model space.
*/ */
public Vector3f getModelSpacePosition() { public Vector3f getModelSpacePosition() {
return worldPos; return modelPos;
} }
/** /**
@ -220,7 +240,7 @@ public final class Bone implements Savable {
* @return The rotation of the bone in model space. * @return The rotation of the bone in model space.
*/ */
public Quaternion getModelSpaceRotation() { public Quaternion getModelSpaceRotation() {
return worldRot; return modelRot;
} }
/** /**
@ -229,79 +249,128 @@ public final class Bone implements Savable {
* @return The scale of the bone in model space. * @return The scale of the bone in model space.
*/ */
public Vector3f getModelSpaceScale() { public Vector3f getModelSpaceScale() {
return worldScale; return modelScale;
} }
/** /**
* Returns the inverse world bind pose position. * @deprecated use {@link #getModelBindInversePosition()}
*/
@Deprecated
public Vector3f getWorldBindInversePosition() {
return modelBindInversePos;
}
/**
* Returns the inverse Bind position of this bone expressed in model space.
* <p> * <p>
* The bind pose transform of the bone is its "default" * The inverse bind pose transform of the bone in model space is its "default"
* transform with no animation applied. * transform with no animation applied.
* *
* @return the inverse world bind pose position. * @return the inverse bind position of this bone expressed in model space.
*/ */
public Vector3f getWorldBindInversePosition() { public Vector3f getModelBindInversePosition() {
return worldBindInversePos; return modelBindInversePos;
} }
/** /**
* Returns the inverse world bind pose rotation. * @deprecated use {@link #getModelBindInverseRotation()}
*/
@Deprecated
public Quaternion getWorldBindInverseRotation() {
return modelBindInverseRot;
}
/**
* Returns the inverse bind rotation of this bone expressed in model space.
* <p> * <p>
* The bind pose transform of the bone is its "default" * The inverse bind pose transform of the bone in model space is its "default"
* transform with no animation applied. * transform with no animation applied.
* *
* @return the inverse world bind pose rotation. * @return the inverse bind rotation of this bone expressed in model space.
*/ */
public Quaternion getWorldBindInverseRotation() { public Quaternion getModelBindInverseRotation() {
return worldBindInverseRot; return modelBindInverseRot;
} }
/**
* @deprecated use {@link #getModelBindInverseScale()}
*/
@Deprecated
public Vector3f getWorldBindInverseScale() {
return modelBindInverseScale;
}
/** /**
* Returns the inverse world bind pose scale. * Returns the inverse world bind pose scale.
* <p> * <p>
* The bind pose transform of the bone is its "default" * The inverse bind pose transform of the bone in model space is its "default"
* transform with no animation applied. * transform with no animation applied.
* *
* @return the inverse world bind pose scale. * @return the inverse world bind pose scale.
*/ */
public Vector3f getWorldBindInverseScale() { public Vector3f getModelBindInverseScale() {
return worldBindInverseScale; return modelBindInverseScale;
} }
/** /**
* Returns the world bind pose position. * @deprecated use {@link #getBindPosition()}
*/
@Deprecated
public Vector3f getWorldBindPosition() {
return bindPos;
}
/**
* Returns the bind position expressed in local space (relative to the parent bone).
* <p> * <p>
* The bind pose transform of the bone is its "default" * The bind pose transform of the bone in local space is its "default"
* transform with no animation applied. * transform with no animation applied.
* *
* @return the world bind pose position. * @return the bind position in local space.
*/ */
public Vector3f getWorldBindPosition() { public Vector3f getBindPosition() {
return initialPos; return bindPos;
}
/**
* @deprecated use {@link #getBindRotation() }
*/
@Deprecated
public Quaternion getWorldBindRotation() {
return bindRot;
} }
/** /**
* Returns the world bind pose rotation. * Returns the bind rotation expressed in local space (relative to the parent bone).
* <p> * <p>
* The bind pose transform of the bone is its "default" * The bind pose transform of the bone in local space is its "default"
* transform with no animation applied. * transform with no animation applied.
* *
* @return the world bind pose rotation. * @return the bind rotation in local space.
*/
public Quaternion getBindRotation() {
return bindRot;
}
/**
* @deprecated use {@link #getBindScale() }
*/ */
public Quaternion getWorldBindRotation() { @Deprecated
return initialRot; public Vector3f getWorldBindScale() {
return bindScale;
} }
/** /**
* Returns the world bind pose scale. * Returns the bind scale expressed in local space (relative to the parent bone).
* <p> * <p>
* The bind pose transform of the bone is its "default" * The bind pose transform of the bone in local space is its "default"
* transform with no animation applied. * transform with no animation applied.
* *
* @return the world bind pose scale. * @return the bind scale in local space.
*/ */
public Vector3f getWorldBindScale() { public Vector3f getBindScale() {
return initialScale; return bindScale;
} }
/** /**
@ -324,26 +393,36 @@ public final class Bone implements Savable {
} }
/** /**
* Updates the world transforms for this bone, and, possibly the attach node *
* @deprecated use {@link #updateModelTransforms() }
*/
@Deprecated
public final void updateWorldVectors(){
updateModelTransforms();
}
/**
* Updates the model transforms for this bone, and, possibly the attach node
* if not null. * if not null.
* <p> * <p>
* The world transform of this bone is computed by combining the parent's * The model transform of this bone is computed by combining the parent's
* world transform with this bones' local transform. * model transform with this bones' local transform.
*/ */
public final void updateWorldVectors() { public final void updateModelTransforms() {
if (currentWeightSum == 1f) { if (currentWeightSum == 1f) {
currentWeightSum = -1; currentWeightSum = -1;
} else if (currentWeightSum != -1f) { } else if (currentWeightSum != -1f) {
// Apply the weight to the local transform // Apply the weight to the local transform
if (currentWeightSum == 0) { if (currentWeightSum == 0) {
localRot.set(initialRot); localRot.set(bindRot);
localPos.set(initialPos); localPos.set(bindPos);
localScale.set(initialScale); localScale.set(bindScale);
} else { } else {
float invWeightSum = 1f - currentWeightSum; float invWeightSum = 1f - currentWeightSum;
localRot.nlerp(initialRot, invWeightSum); localRot.nlerp(bindRot, invWeightSum);
localPos.interpolateLocal(initialPos, invWeightSum); localPos.interpolateLocal(bindPos, invWeightSum);
localScale.interpolateLocal(initialScale, invWeightSum); localScale.interpolateLocal(bindScale, invWeightSum);
} }
// Future invocations of transform blend will start over. // Future invocations of transform blend will start over.
@ -352,28 +431,28 @@ public final class Bone implements Savable {
if (parent != null) { if (parent != null) {
//rotation //rotation
parent.worldRot.mult(localRot, worldRot); parent.modelRot.mult(localRot, modelRot);
//scale //scale
//For scale parent scale is not taken into account! //For scale parent scale is not taken into account!
// worldScale.set(localScale); // worldScale.set(localScale);
parent.worldScale.mult(localScale, worldScale); parent.modelScale.mult(localScale, modelScale);
//translation //translation
//scale and rotation of parent affect bone position //scale and rotation of parent affect bone position
parent.worldRot.mult(localPos, worldPos); parent.modelRot.mult(localPos, modelPos);
worldPos.multLocal(parent.worldScale); modelPos.multLocal(parent.modelScale);
worldPos.addLocal(parent.worldPos); modelPos.addLocal(parent.modelPos);
} else { } else {
worldRot.set(localRot); modelRot.set(localRot);
worldPos.set(localPos); modelPos.set(localPos);
worldScale.set(localScale); modelScale.set(localScale);
} }
if (attachNode != null) { if (attachNode != null) {
attachNode.setLocalTranslation(worldPos); attachNode.setLocalTranslation(modelPos);
attachNode.setLocalRotation(worldRot); attachNode.setLocalRotation(modelRot);
attachNode.setLocalScale(worldScale); attachNode.setLocalScale(modelScale);
} }
} }
@ -381,7 +460,7 @@ public final class Bone implements Savable {
* Updates world transforms for this bone and it's children. * Updates world transforms for this bone and it's children.
*/ */
final void update() { final void update() {
this.updateWorldVectors(); this.updateModelTransforms();
for (int i = children.size() - 1; i >= 0; i--) { for (int i = children.size() - 1; i >= 0; i--) {
children.get(i).update(); children.get(i).update();
@ -392,25 +471,25 @@ public final class Bone implements Savable {
* Saves the current bone state as its binding pose, including its children. * Saves the current bone state as its binding pose, including its children.
*/ */
void setBindingPose() { void setBindingPose() {
initialPos.set(localPos); bindPos.set(localPos);
initialRot.set(localRot); bindRot.set(localRot);
initialScale.set(localScale); bindScale.set(localScale);
if (worldBindInversePos == null) { if (modelBindInversePos == null) {
worldBindInversePos = new Vector3f(); modelBindInversePos = new Vector3f();
worldBindInverseRot = new Quaternion(); modelBindInverseRot = new Quaternion();
worldBindInverseScale = new Vector3f(); modelBindInverseScale = new Vector3f();
} }
// Save inverse derived position/scale/orientation, used for calculate offset transform later // Save inverse derived position/scale/orientation, used for calculate offset transform later
worldBindInversePos.set(worldPos); modelBindInversePos.set(modelPos);
worldBindInversePos.negateLocal(); modelBindInversePos.negateLocal();
worldBindInverseRot.set(worldRot); modelBindInverseRot.set(modelRot);
worldBindInverseRot.inverseLocal(); modelBindInverseRot.inverseLocal();
worldBindInverseScale.set(Vector3f.UNIT_XYZ); modelBindInverseScale.set(Vector3f.UNIT_XYZ);
worldBindInverseScale.divideLocal(worldScale); modelBindInverseScale.divideLocal(modelScale);
for (Bone b : children) { for (Bone b : children) {
b.setBindingPose(); b.setBindingPose();
@ -422,9 +501,9 @@ public final class Bone implements Savable {
*/ */
final void reset() { final void reset() {
if (!userControl) { if (!userControl) {
localPos.set(initialPos); localPos.set(bindPos);
localRot.set(initialRot); localRot.set(bindRot);
localScale.set(initialScale); localScale.set(bindScale);
} }
for (int i = children.size() - 1; i >= 0; i--) { for (int i = children.size() - 1; i >= 0; i--) {
@ -444,14 +523,14 @@ public final class Bone implements Savable {
*/ */
void getOffsetTransform(Matrix4f outTransform, Quaternion tmp1, Vector3f tmp2, Vector3f tmp3, Matrix3f tmp4) { void getOffsetTransform(Matrix4f outTransform, Quaternion tmp1, Vector3f tmp2, Vector3f tmp3, Matrix3f tmp4) {
// Computing scale // Computing scale
Vector3f scale = worldScale.mult(worldBindInverseScale, tmp3); Vector3f scale = modelScale.mult(modelBindInverseScale, tmp3);
// Computing rotation // Computing rotation
Quaternion rotate = worldRot.mult(worldBindInverseRot, tmp1); Quaternion rotate = modelRot.mult(modelBindInverseRot, tmp1);
// Computing translation // Computing translation
// Translation depend on rotation and scale // Translation depend on rotation and scale
Vector3f translate = worldPos.add(rotate.mult(scale.mult(worldBindInversePos, tmp2), tmp2), tmp2); Vector3f translate = modelPos.add(rotate.mult(scale.mult(modelBindInversePos, tmp2), tmp2), tmp2);
// Populating the matrix // Populating the matrix
outTransform.loadIdentity(); outTransform.loadIdentity();
@ -459,35 +538,52 @@ public final class Bone implements Savable {
} }
/** /**
* Sets user transform. *
* Sets the transforms of this bone in local space (relative to the parent bone)
*
* @param translation the translation in local space
* @param rotation the rotation in local space
* @param scale the scale in local space
*/ */
public void setUserTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) { public void setUserTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) {
if (!userControl) { if (!userControl) {
throw new IllegalStateException("User control must be on bone to allow user transforms"); throw new IllegalStateException("You must call setUserControl(true) in order to setUserTransform to work");
} }
localPos.set(initialPos); localPos.set(bindPos);
localRot.set(initialRot); localRot.set(bindRot);
localScale.set(initialScale); localScale.set(bindScale);
localPos.addLocal(translation); localPos.addLocal(translation);
localRot = localRot.mult(rotation); localRot.multLocal(rotation);
localScale.multLocal(scale); localScale.multLocal(scale);
} }
/** /**
* Must update all bones in skeleton for this to work. *
* @param translation * @param translation -
* @param rotation * @param rotation -
* @deprecated use {@link #setUserTransformsInModelSpace(com.jme3.math.Vector3f, com.jme3.math.Quaternion) }
*/ */
@Deprecated
public void setUserTransformsWorld(Vector3f translation, Quaternion rotation) { public void setUserTransformsWorld(Vector3f translation, Quaternion rotation) {
}
/**
* Sets the transforms of this bone in model space (relative to the root bone)
*
* Must update all bones in skeleton for this to work.
* @param translation translation in model space
* @param rotation rotation in model space
*/
public void setUserTransformsInModelSpace(Vector3f translation, Quaternion rotation) {
if (!userControl) { if (!userControl) {
throw new IllegalStateException("User control must be on bone to allow user transforms"); throw new IllegalStateException("You must call setUserControl(true) in order to setUserTransformsInModelSpace to work");
} }
// TODO: add scale here ??? // TODO: add scale here ???
worldPos.set(translation); modelPos.set(translation);
worldRot.set(rotation); modelRot.set(rotation);
//if there is an attached Node we need to set it's local transforms too. //if there is an attached Node we need to set it's local transforms too.
if(attachNode != null){ if(attachNode != null){
@ -502,6 +598,9 @@ public final class Bone implements Savable {
* @param rotation a rotation * @param rotation a rotation
*/ */
public Transform getCombinedTransform(Vector3f position, Quaternion rotation) { public Transform getCombinedTransform(Vector3f position, Quaternion rotation) {
if(tmpTransform == null){
tmpTransform = new Transform();
}
rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position); rotation.mult(localPos, tmpTransform.getTranslation()).addLocal(position);
tmpTransform.setRotation(rotation).getRotation().multLocal(localRot); tmpTransform.setRotation(rotation).getRotation().multLocal(localRot);
return tmpTransform; return tmpTransform;
@ -541,11 +640,11 @@ public final class Bone implements Savable {
// localRot.multLocal(rotation); // localRot.multLocal(rotation);
//localRot = localRot.mult(rotation); //localRot = localRot.mult(rotation);
localPos.set(initialPos).addLocal(translation); localPos.set(bindPos).addLocal(translation);
localRot.set(initialRot).multLocal(rotation); localRot.set(bindRot).multLocal(rotation);
if (scale != null) { if (scale != null) {
localScale.set(initialScale).multLocal(scale); localScale.set(bindScale).multLocal(scale);
} }
} }
@ -553,11 +652,11 @@ public final class Bone implements Savable {
* Blends the given animation transform onto the bone's local transform. * Blends the given animation transform onto the bone's local transform.
* <p> * <p>
* Subsequent calls of this method stack up, with the final transformation * Subsequent calls of this method stack up, with the final transformation
* of the bone computed at {@link #updateWorldVectors() } which resets * of the bone computed at {@link #updateModelTransforms() } which resets
* the stack. * the stack.
* <p> * <p>
* E.g. a single transform blend with weight = 0.5 followed by an * E.g. a single transform blend with weight = 0.5 followed by an
* updateWorldVectors() call will result in final transform = transform * 0.5. * updateModelTransforms() call will result in final transform = transform * 0.5.
* Two transform blends with weight = 0.5 each will result in the two * Two transform blends with weight = 0.5 each will result in the two
* transforms blended together (nlerp) with blend = 0.5. * transforms blended together (nlerp) with blend = 0.5.
* *
@ -565,7 +664,7 @@ public final class Bone implements Savable {
* @param rotation The rotation to blend in * @param rotation The rotation to blend in
* @param scale The scale to blend in * @param scale The scale to blend in
* @param weight The weight of the transform to apply. Set to 1.0 to prevent * @param weight The weight of the transform to apply. Set to 1.0 to prevent
* any other transform from being applied until updateWorldVectors(). * any other transform from being applied until updateModelTransforms().
*/ */
void blendAnimTransforms(Vector3f translation, Quaternion rotation, Vector3f scale, float weight) { void blendAnimTransforms(Vector3f translation, Quaternion rotation, Vector3f scale, float weight) {
if (userControl) { if (userControl) {
@ -581,12 +680,12 @@ public final class Bone implements Savable {
return; // More than 2 transforms are being blended return; // More than 2 transforms are being blended
} else if (currentWeightSum == -1 || currentWeightSum == 0) { } else if (currentWeightSum == -1 || currentWeightSum == 0) {
// Set the transform fully // Set the transform fully
localPos.set(initialPos).addLocal(translation); localPos.set(bindPos).addLocal(translation);
localRot.set(initialRot).multLocal(rotation); localRot.set(bindRot).multLocal(rotation);
if (scale != null) { if (scale != null) {
localScale.set(initialScale).multLocal(scale); localScale.set(bindScale).multLocal(scale);
} }
// Set the weight. It will be applied in updateWorldVectors(). // Set the weight. It will be applied in updateModelTransforms().
currentWeightSum = weight; currentWeightSum = weight;
} else { } else {
// The weight is already set. // The weight is already set.
@ -597,14 +696,14 @@ public final class Bone implements Savable {
Vector3f tmpV2 = vars.vect2; Vector3f tmpV2 = vars.vect2;
Quaternion tmpQ = vars.quat1; Quaternion tmpQ = vars.quat1;
tmpV.set(initialPos).addLocal(translation); tmpV.set(bindPos).addLocal(translation);
localPos.interpolateLocal(tmpV, weight); localPos.interpolateLocal(tmpV, weight);
tmpQ.set(initialRot).multLocal(rotation); tmpQ.set(bindRot).multLocal(rotation);
localRot.nlerp(tmpQ, weight); localRot.nlerp(tmpQ, weight);
if (scale != null) { if (scale != null) {
tmpV2.set(initialScale).multLocal(scale); tmpV2.set(bindScale).multLocal(scale);
localScale.interpolateLocal(tmpV2, weight); localScale.interpolateLocal(tmpV2, weight);
} }
@ -620,11 +719,11 @@ public final class Bone implements Savable {
* Call setBindingPose() after all of the skeleton bones' bind transforms are set to save them. * Call setBindingPose() after all of the skeleton bones' bind transforms are set to save them.
*/ */
public void setBindTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) { public void setBindTransforms(Vector3f translation, Quaternion rotation, Vector3f scale) {
initialPos.set(translation); bindPos.set(translation);
initialRot.set(rotation); bindRot.set(rotation);
//ogre.xml can have null scale values breaking this if the check is removed //ogre.xml can have null scale values breaking this if the check is removed
if (scale != null) { if (scale != null) {
initialScale.set(scale); bindScale.set(scale);
} }
localPos.set(translation); localPos.set(translation);
@ -658,13 +757,22 @@ public final class Bone implements Savable {
InputCapsule input = im.getCapsule(this); InputCapsule input = im.getCapsule(this);
name = input.readString("name", null); name = input.readString("name", null);
initialPos = (Vector3f) input.readSavable("initialPos", null); int ver = input.getSavableVersion(Bone.class);
initialRot = (Quaternion) input.readSavable("initialRot", null); if(ver < 2){
initialScale = (Vector3f) input.readSavable("initialScale", new Vector3f(1.0f, 1.0f, 1.0f)); bindPos = (Vector3f) input.readSavable("initialPos", null);
bindRot = (Quaternion) input.readSavable("initialRot", null);
bindScale = (Vector3f) input.readSavable("initialScale", new Vector3f(1.0f, 1.0f, 1.0f));
}else{
bindPos = (Vector3f) input.readSavable("bindPos", null);
bindRot = (Quaternion) input.readSavable("bindRot", null);
bindScale = (Vector3f) input.readSavable("bindScale", new Vector3f(1.0f, 1.0f, 1.0f));
}
attachNode = (Node) input.readSavable("attachNode", null); attachNode = (Node) input.readSavable("attachNode", null);
localPos.set(initialPos); localPos.set(bindPos);
localRot.set(initialRot); localRot.set(bindRot);
localScale.set(bindScale);
ArrayList<Bone> childList = input.readSavableArrayList("children", null); ArrayList<Bone> childList = input.readSavableArrayList("children", null);
for (int i = childList.size() - 1; i >= 0; i--) { for (int i = childList.size() - 1; i >= 0; i--) {
@ -683,9 +791,9 @@ public final class Bone implements Savable {
output.write(name, "name", null); output.write(name, "name", null);
output.write(attachNode, "attachNode", null); output.write(attachNode, "attachNode", null);
output.write(initialPos, "initialPos", null); output.write(bindPos, "bindPos", null);
output.write(initialRot, "initialRot", null); output.write(bindRot, "bindRot", null);
output.write(initialScale, "initialScale", new Vector3f(1.0f, 1.0f, 1.0f)); output.write(bindScale, "bindScale", new Vector3f(1.0f, 1.0f, 1.0f));
output.writeSavableArrayList(children, "children", null); output.writeSavableArrayList(children, "children", null);
} }
} }

Loading…
Cancel
Save