Jump to content
• ### What is your GameDev Story?

• Advertisement

#### Archived

This topic is now archived and is closed to further replies.

# Transition between different animation sets of skinned mesh

This topic is 5361 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

## Recommended Posts

Dear all, I have tried almost everything to transition between 2 frames of different animation sets of a .X skinned mesh to no avail. A normal blending between 2 frames (the last of the previous animation set and the new animation set) of different animation sets is done by adding the previous transformation matrix with the new transformation matrix for for every bone in the skinned mesh (according to Jim Adam''s Advanced Animation book). I would assume that this will create a transition effect between both frames but it doesn''t. If I multiply a blending value to the transformation matrix, I will get a deformed in-between frame (I thought it was because I didn''t multiply with the inversed matrix first but that doesn''t seem to be the case). So, in the end I did this: Previous Bone Transformation Matrix + New Bone Transformation Matrix X Transition Value (default to 0.5). This is done before I call UpdateSkinnedMesh which does the actual: Vertex = Bone Transformation Matrix X Inverse Bone Transformation Matrix X (1-weight) x vertex. Unfortunately, I still get the deformed in-between frame. What am I doing wrong? Thanks. ^_^ _________________ Best regards, Sherman Chin Director Sherman3D (Malaysia) Sdn Bhd www.Sherman3D.com chat.Sherman3D.com forum.Sherman3D.com www.VibeForce.com

#### Share this post

##### Share on other sites
Advertisement
Rui,

Thanks for your reply again.

>Since you say your animations are working OK, do you interpolate the
>several animation keyframes

Yes, I interpolate them. I am using matrix keys so I do.
boneTransformMatrix = matrix[key1] + matrix[key2] * scalarValue;\

>One animation ends with the character upside down (feet on the air,
>hands on the ground), and the other Starts with an upstraight guy
>(feet on ground, hands near waist). No matter how you
>blend/transform it, it won''t look "Natural".

I am doing a transition from idle to walk. Basically, I want
a frame showing the hand at stomach level when the
hands swing from near the leg (last idle frame) to chest level
(first run frame).

When I do:
(Previous Bone Transformation Matrix + New Bone Transformation
Matrix) /2
I get the frame with the hand at stomach level but it appears
that the hand has shrunk somehow. It looks like it is calculating
a straight line between vertices of the hand at leg level and
hand at chest level and simply drawing a vertex halfway in-between.

Here are the pictures:

http://www.sherman3d.net/sherman/idle.jpg
http://www.sherman3d.net/sherman/trans.jpg
http://www.sherman3d.net/sherman/run.jpg

Notice the funny small size of the arm when transitioning?

Thanks a lot! ^_^

_________________
Best regards,
Sherman Chin
Director
Sherman3D (Malaysia) Sdn Bhd
www.Sherman3D.com
chat.Sherman3D.com
forum.Sherman3D.com
www.VibeForce.com

#### Share this post

##### Share on other sites
Reply from Rui Martins from FlipCode:

> Notice the funny small size of the arm when transitioning?

Yeah I do !

By interpolation, I hope you mean interpolate the joints angles, first and last.
The idea is:

interpolated_joint_angle = joint_first_angle + (joint_last_angle-joint_first_angle) * T

Where T is in the range 0 to 1.

> boneTransformMatrix = matrix[key1] + matrix[key2] * scalarValue;\

If you are using this formula, you will scale the entire matrix !
Every object transformed by this matrix is gona get shrinked (with scalarValue between 0 and 1).

What I sugest is create a very simple model, an arm (two sections), built from a paralelogram (8 points), try the most simple interpolation to debug:
StartAngle: 0 degrees
EndAngle: 90 degrees
T: 0.5
NOTE1:Rotation joint must be aligned to one of the major axis (World X, y or Z).
NOTE2: Don''t define any vertex weights for the arm (i.e. weight=1 for all vertexes).

if you know your math, you know the correct matrices for these angles (depending on your rotation axis), and you can work out the matrix for 45 degrees.
If not check this:
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=00010203&forum=3dtheory&id=7

Having that you can check what is wrong with your interpolation code.

Hope that Helps.

_______________________________________________

Actually, I got my code from Jim Adam''s Advanced Animation book.
Here is the relevant snippet:

// If we have matrix keys.
if(m_NumMatrixKeys && m_MatrixKeys != NULL)
{
Key = 0;
// Loop through all keys.
for(i=0;i{
// Find the key that fits this time
if(m_MatrixKeys.Time <= Time)
Key = i;
else
break;
} // End loop through all keys.

// If it''s the last key or non-smooth animation
if(Key == (m_NumMatrixKeys-1) || Smooth == FALSE)
{
// Set the unblended animation matrix to the current key
// without interpolation.
d3dxmatAnimation = m_MatrixKeys[Key].Matrix;
} // If it''s the last key or non-smooth animation
// Else If it''s not the last key or non-smooth animation
else
{
// Get difference in key times
DWORD dwTimeDiff = m_MatrixKeys[Key+1].Time -
m_MatrixKeys[Key].Time;
if(!dwTimeDiff)
dwTimeDiff = 1;

// Calculate a scalar value to use
float Scalar = (float)(Time - m_MatrixKeys[Key].Time)
/ (float)dwTimeDiff;

// Calculate interpolated matrix
d3dxmatAnimation = m_MatrixKeys[Key+1].Matrix -
m_MatrixKeys[Key].Matrix;
d3dxmatAnimation *= Scalar;
d3dxmatAnimation += m_MatrixKeys[Key].Matrix;

} // End else If it''s not the last key or non-smooth animation
} // End if we have matrix keys.

// If no transition
if (fBlend == -1.0f)
{
// Use animation as current frame''s transformation matrix.
m_Frame->m_matTransformed = d3dxmatAnimation;
} // End if no transition.
// Else if transition.
else
{
// Get the difference in transformation between current animation
// matrix and previous animation matrix.
D3DXMATRIX d3dxmatDiff = d3dxmatAnimation - m_Frame->m_matTransformed;

// Adjust by transition amount.
d3dxmatDiff *= fBlend;

// Add blended animation to current frame''s tranformation matrix.
m_Frame->m_matTransformed += d3dxmatDiff;

} // End else if transition.

_________________
Best regards,
Sherman Chin
Director
Sherman3D (Malaysia) Sdn Bhd
www.Sherman3D.com
chat.Sherman3D.com
forum.Sherman3D.com
www.VibeForce.com

#### Share this post

##### Share on other sites
Looks like nobody here can help me. ;_; Fortunately, I got
some very good help at Flipcode and I am going to post it here
for whoever does a search on this in the future. If you
need help, please e-mail me at info at Sherman3D.com in the
future (I won''t be checking this thread all the time).

"
What you get when you linearly interpolate matrices is, that each individual vertex moves on a straight line trajectory from the old pose to it''s corresponding position in the new pose.

You must decide for yourself if that''s ok with your art data.
"

"

If I''m understanding the problem correctly then I had the same issue while implementing one of these systems...The problem I had is that I would interpolate the rotations(I used quaternions and D3DXQuaternionSlerp to interpolate) AND I would also interpolate the positions.

Interpolating positions was the big problem - I had seen arms getting smaller also. What I did to fix this was to calculate the length of each bone(sqrt(ParentBonePosition - BonePos)) from the default skeleton(at load time...if there is no parent bone then I have no bone length...). Then I go through and slerp the bone rotations and lerp the bone positions for bones with no parent. After that I recurse through the new skeleton and calculate the bone positions kinda like:
vNewPos = vParentBonePos + (vBoneForwardVector * fBoneLength);

The nice thing about doing it this way is that you can have a whole set of character models - each with a different sized skeleton - and you can share a common set of animations and not worry about arms getting streched or shrunk.
"

_________________
Best regards,
Sherman Chin
Director
Sherman3D (Malaysia) Sdn Bhd
www.Sherman3D.com
chat.Sherman3D.com
forum.Sherman3D.com
www.VibeForce.com

#### Share this post

##### Share on other sites
My final post in this thread to close the topic:

I seem to have solved my problem:

D3DXQUATERNION d3dxquatPrev, d3dxquatNow;            // Convert previous bone transformation matrix to quaternion.            D3DXQuaternionRotationMatrix(                                            &d3dxquatPrev,                                            &m_Frame->m_d3dxmatTranformPrev            // Convert current bone transformation matrix to quaternion.            D3DXQuaternionRotationMatrix(                                            &d3dxquatNow,                                            &d3dxmatAnimation            D3DXQUATERNION d3dxquatInterpolatedTransform;            // Perform quaternion rotation interpolation.            D3DXQuaternionSlerp(    &d3dxquatInterpolatedTransform,                                     &d3dxquatPrev,                                    &d3dxquatNow,                                     fBlend            D3DXMATRIX d3dxmatTransform;            D3DXMatrixIdentity(&d3dxmatTransform);            // Convert interpolated rotation quarternion to transform matrix.            D3DXMatrixRotationQuaternion(                                            &d3dxmatTransform,                                             &d3dxquatInterpolatedTransform            // Now, re-add translation.            d3dxmatTransform._41 =                 m_Frame->m_d3dxmatTranformPrev._41 +                     (d3dxmatAnimation._41 - m_Frame->m_d3dxmatTranformPrev._41)                         * fBlend;            d3dxmatTransform._42 =                 m_Frame->m_d3dxmatTranformPrev._42 +                     (d3dxmatAnimation._42 - m_Frame->m_d3dxmatTranformPrev._42)                         * fBlend;            d3dxmatTransform._43 =                 m_Frame->m_d3dxmatTranformPrev._43 +                     (d3dxmatAnimation._43 - m_Frame->m_d3dxmatTranformPrev._43)                         * fBlend;            d3dxmatTransform._44 =                 m_Frame->m_d3dxmatTranformPrev._44 +                     (d3dxmatAnimation._44 - m_Frame->m_d3dxmatTranformPrev._44)                         * fBlend;            // Use blended animation as current frame''s transformation matrix.            m_Frame->m_matTransformed = d3dxmatTransform;

The strange thing is that I just did the normal linear interpolation:
current position vector = previous position vector + (current position vector - previous position vector) * blending value
for the position vector and it works! No more distorted hand! I
guess the culprit was the rotation key all along - need to
use SLERP on it no matter what. ^_^v

_________________
Best regards,
Sherman Chin
Director
Sherman3D (Malaysia) Sdn Bhd
www.Sherman3D.com
chat.Sherman3D.com
forum.Sherman3D.com
www.VibeForce.com

#### Share this post

##### Share on other sites

• Advertisement
• Advertisement
• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

(You must login to your GameDev.net account.)

• ### Popular Now

• 15
• 14
• 46
• 22
• 27
• Advertisement
• ### Forum Statistics

• Total Topics
634047
• Total Posts
3015230
×

## Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!