Another Question about Bones

If I have a bone that is attached to another bone, when I perform the bone translation on the child, do I have to take into account the transformation of the parent as well?  If so, how do I calculate the influence from the parent bone's transformation, simply multiply the parent's translation & rotation matrices against the child's?



Thanks for any help.

Actually, I think I just answered my own question.



http://en.wikipedia.org/wiki/Skeletal_animation



Though, does JME already do this for me once I've set up a skeletal system for a particular skin?

Yes, the system in jME will handle your hierarchy of transformations for you, so you only need to worry about the transformation in local terms.

So I've been struggling to do some of the animation on a WoW model viewer application I've been playing with and have reached a point where I'm banging my head against the wall.  I'm very close but for some odd reason, certain parts of the skeletal animation are not working.  I posted an example on Youtube.



http://www.youtube.com/watch?v=Q2KQeaRXSH8



If you watch the short clip, you'll see an animated frog trying to catch a fly, except there's no fly and no tongue.  Those are actually INSIDE of the body.  I then turn on bone debugging and you can see the two bones that are "supposed" to be attached to the vertices for the tongue and fly.  They even move correctly, except the vertices that the bones are attached to do not move.  I have combed through my code looking for a good reason as to why this is happening and was wondering if anyone has any idea as to why I may be experiencing this issue.  I've actually logged the bone structure as can be seen below:



[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:404) - Bone index: 0

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:420) -  Attaching bone[0] to the model node

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:404) - Bone index: 1

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:424) -  Attaching bone[1] to bone bone[0]

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:426) -    bone[0] now has 1 children.

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:404) - Bone index: 2

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:424) -  Attaching bone[2] to bone bone[0]

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:426) -    bone[0] now has 2 children.

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:404) - Bone index: 3

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:424) -  Attaching bone[3] to bone bone[0]

[2009-02-11 10:14:35,000] DEBUG (TestM2Render.java:426) -    bone[0] now has 3 children.



I have identified that bone[2] and bone[3] are actually attached to the vertexes controlling the model's tongue and the little fly (which is essentially one or two triangles with a transparent bitmap on it).



I have also verified that the bone weights are correctly applied to the vertexes in question, but still it just doesn't seem to work.  In almost every animation for that particular model (there are like 7 of them) everything works perfectly except that stupid tongue.



Here is a second video showing this in a different animation:



http://www.youtube.com/watch?v=YzJ2LdSZTtc



If anyone has any ideas no matter how far fetched, please let me know.

I'm actually thinking that it has something to do with my animation interpolation between frames as well as the root bone selection where I do setSkeleton() on the skin node.  Apparently, the root bone index was being set incorrectly.  However, when I do set it correctly only the first animation works.  After examining my animation sequences, it would appear that only the first animation has translation values for the root bone (i.e. the root bone doesn't get translated in any other animation sequences).  When I attempt to animate the other sequences the little fellow just sits there stupidly.  However, if I initially set the current time in the animation sequence a single frame is rendered correctly (and he, once again, just freezes in that frame).  I'm thinking the only way this could occur is if the code that I wrote that interpolates values between two frames has a bug.  I guess sometimes trying to explain myself to other people, regardless of getting help, often helps me understand where I may have gone wrong :).



Btw, so far I'm very impressed with JME.  Being a TOTAL novice at 3D graphics programming with only a working knowledge of how things work has really been enlightening.  I'd really love to contribute to the project.  In all honesty, it would probably be best in the documentation area.  Seeing as I've recently gotten into this and I've had to learn everything, it might give a fresh perspective on how to word the documentation.  I've written a lot of documentation in the last 25 years of my professional career.

Does anyone have any ideas why the bones would deform the mesh correctly the first time, but only the first time.  When I turn on bone debugging I see the bones moving in what seems to be a correct path.  However, the model/mesh does not move at all beyond the first rendered frame.

So it would seem that I just needed to add a call to updateSkin() after I transformed the bones.  Odd that one animation does not require it but the others do.  Is there some relationship between the bones and the skin that I'm unaware of?  Perhaps some observer that relates the bones to the skin?



Anyhow, I think this solves the problem.

So now it seems I've got the bone translation and rotation down but adding in scaling is causing distortion (again).  I've included a screenshot to show the effect.  Below is my code.



   public Matrix4f calculateMatrixJme (int animationSequence, int time) {
      boolean didTranslation = false;
      boolean didRotation = false;
      boolean didScaling = false;
      Matrix4f m = new Matrix4f ();
      m.setTranslation (this.pivotPoint.x, this.pivotPoint.y, this.pivotPoint.z);

      //
      // Get the translation, rotation, and scaling vectors for the given
      // animation sequence and time.  These values will be interpolated between
      // the two frames that "surround" the time.
      //
      Vector3f transVec = this.getTransformationAnimation ().getKeyFrameDataValue (animationSequence, time);
      Quaternion rotQuat = this.getRotationAnimation ().getKeyFrameDataValue (animationSequence, time);
      Vector3f scaleVec = this.getScalingAnimation ().getKeyFrameDataValue (animationSequence, time);


      //
      // Calculate the translation part of the animation.
      //
      if (transVec != null) {
         //
         // Set the translation for the matrix.
         //
         com.jme.math.Matrix4f transMat = new com.jme.math.Matrix4f ();
         transMat.setTranslation (transVec);
         m = m.mult (transMat);
         didTranslation = true;
      }
      
      //
      // Calculate the rotation part of the animation. Get the rotation quaternion
      // for the given animation sequence.
      //
      if (rotQuat != null) {
         //
         // Get the rotation quaternion for this frame.
         //
         com.jme.math.Matrix4f rotMat = new com.jme.math.Matrix4f ();
         rotMat.setRotationQuaternion (rotQuat);
         m = m.mult (rotMat);
         didRotation = true;
      }

      //
      // Calculate the scaling part of the animation.
      //
      if (scaleVec != null) {
          this.lastScaling = scaleVec;
//          m.scale (scaleVec);
         didScaling = true;
      }
      
      //
      // If we didn't do anything, return a matrix set to an identity matrix.
      //
      if (didTranslation == false && didRotation == false && didScaling == false) {
         m = new com.jme.math.Matrix4f ();
      } else {
         //
         // Finish up...
         //
         com.jme.math.Vector3f unpivot = new com.jme.math.Vector3f (this.pivotPoint.x, this.pivotPoint.y, this.pivotPoint.z);
         unpivot = unpivot.mult (-1.0f);
         com.jme.math.Matrix4f unpiv = new com.jme.math.Matrix4f ();
         unpiv.setTranslation (new com.jme.math.Vector3f (unpivot));
         m = m.mult (unpiv);
      }

      //
      // Save the matrix.
      //
      this.lastCalcMatrix = m;
      return m;
   }



Notice that I've commented out the scaling because it's causing the model to become distorted.  What exactly should be done to scale the bone?  I've tried several different ideas but no matter what I do, it causes the bones to distort the model.  Is it as simple as doing a multiply of the scale vector and using the returned vector as the local scaling?  I've been pouring over tons of documentation and general 3D animation documents trying to understand but everything I do just causes the animation to "degrade."  If anyone could help me out here, or point me in the right direction, I'd be greatly appreciative.

Thanks.

Below is the screen shot.  Notice that the mesh is not stretched/scaled (because the code is commented out).

Wish I could help :slight_smile:



(just a comment to show that people are reading your posts and probably just can't contribute anything intelligent…)

Thanks :).  You're welcome to check out the code I've written if it helps people understand.  It's at http://code.google.com/p/jwowmodelview