Community
FBX Forum
Welcome to Autodesk’s FBX Forums. Share your knowledge, ask questions, and explore popular FBX topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Relative local TRS

4 REPLIES 4
Reply
Message 1 of 5
Anonymous
417 Views, 4 Replies

Relative local TRS

I'm trying to compute the relative, local translation, quaternion rotation and scale for a node. Currently, the code I have is:


// Evaluate the node at the given time
KTime kTime;
kTime.SetSecondDouble(Time);
FbxAMatrix Transform = m_pFBXNode->EvaluateLocalTransform(kTime);
FbxVector4 Translation = Transform.GetT();
FbxQuaternion QuatRotation = Transform.GetQ();
FbxVector4 Scale = Transform.GetS();

// Make the values relative to time of 0
kTime.SetSecondDouble(0);
FbxAMatrix Frame0Transform = m_pFBXNode->EvaluateLocalTransform(kTime);
FbxVector4 Frame0Translation = Frame0Transform.GetT();
FbxQuaternion Frame0QuatRotation = Frame0Transform.GetQ();
FbxVector4 Frame0Scale = Frame0Transform.GetS();

FbxAMatrix InverseFrame0Transform = Frame0Transform.Inverse();

FbxAMatrix RelativeTransform = InverseFrame0Transform * Transform;
Translation = RelativeTransform.GetT();
QuatRotation = RelativeTransform.GetQ();
Scale = Transform.GetS() - Frame0Scale;

// Transform the translation by the inverse of the rotation
// This might be the correct thing to do, or it might not
/*
FbxMatrix inverseRotationMatrix;
inverseRotationMatrix.SetTQS(FbxVector4(0, 0, 0, 1), QuatRotation, FbxVector4(1, 1, 1, 1));
//inverseRotationMatrix = inverseRotationMatrix.Inverse();
Translation = inverseRotationMatrix.MultNormalize(Translation);
*/

Keyframe = (float)Translation;
Keyframe = (float)Translation;
Keyframe = (float)Translation;

Keyframe = (float)QuatRotation;
Keyframe = (float)QuatRotation;
Keyframe = (float)QuatRotation;
Keyframe = (float)QuatRotation;

Keyframe = (float)Scale;
Keyframe = (float)Scale;
Keyframe = (float)Scale;


But it seems that when reconstructing the transformation, the translation isn't orientated correctly. I think I may need to rotate the translation by the inverse of the rotation for the node, as looking at the FBX documentation, it states that the order of transformation in FBX is translated, then rotated, then scaled, but our engine performs scale, then rotation, then translation. Am I on the right track with this? The commented out piece of code was supposed to do it but didn't seem to work correctly. Has anyone else done this?

BTW, I'm reconstructing the transformation by doing the following:


// Get the base transformation
// This is from the node's original position / rotation
m_Position = m_pModelNode->GetPosition();
m_Rotation = m_pModelNode->GetRotation();
m_Scale = m_pModelNode->GetScale();

// Blend in any timelines
// Timelines store the relative local transformation
for(std::map<int, TimelineInstancePtr>::iterator currentTimeline = m_TimelineInstances.begin(); currentTimeline != m_TimelineInstances.end(); ++currentTimeline)
{
// Update the timeline
TimelineInstancePtr instance = currentTimeline->second;
instance->Update(DeltaTime);

// Get the weight of the timeline
// Weights are 0 - 1, and are used to make the animation additive
float32 timelineWeight = m_TimelineInstanceWeights;

//Retrieve the keyframe values
m_Position += timelineWeight * Vector3(instance->GetCurrentValues(), instance->GetCurrentValues(), instance->GetCurrentValues());
m_Scale += timelineWeight * Vector3(instance->GetCurrentValues(), instance->GetCurrentValues(), instance->GetCurrentValues());

// Blend the quaternion rotation
Quaternion unitQuaternion(0, 0, 0, 1);
Quaternion newRotation = Quaternion::Slerp(unitQuaternion, Quaternion(instance->GetCurrentValues(), instance->GetCurrentValues(), instance->GetCurrentValues(), instance->GetCurrentValues()), timelineWeight);
m_Rotation = m_Rotation * newRotation;
}

// Construct the total matrix
m_TransformMatrix = ParentTransform * (Matrix4x4::Translation(m_Position)) * m_Rotation.ToMatrix4x4() * Matrix4x4::Scaling(m_Scale);
4 REPLIES 4
Message 2 of 5
jiayang.xu
in reply to: Anonymous

I am not sure this is applicable.
What you want to do is actually to find a new R1 and T1 which satisfy R*T*V = T1*R1*V.
V is the vector to transform. T is translation, R is Rotation in FBX file, R1 and T1 are the ones you want to calculate.
And in FBX it is R*T*V, means T apply to V first, then the R is applied.

Consider this:
R*T*V = R*T*R.Inv*R*V, if let R1=R, then T1= R*T*R.Inv, but can we ensure R*T*R.Inv is still a translation matrix?
or
R*T*V = T*T.Inv*R*T*V, if let T1=T, then R1= T.Inv*R*T, but can we ensure T.Inv*R*T is still a rotation matrix?
R.Inv means inverse of R.
Message 3 of 5
Anonymous
in reply to: Anonymous

Shouldn't transforming the translation by the rotation matrix produce the same result? I.e.:

FBX does R * T * V, so translating first, then rotating.

If we get the translation vector (Tv) that creates the matrix T, then transform Tv by the rotation matrix:

Tv' = R * Tv

Then we can generate a translation matrix, T', using Tv', such that:

T' * R * V = R * T * V

In code:

translation = relativeTransform.GetT();
translation = 1.0f;

quatRotation = relativeTransform.GetQ();

// Transform the translation by the inverse of the rotation
FbxMatrix rotationMatrix;
rotationMatrix.SetTQS(FbxVector4(0, 0, 0, 1), quatRotation, FbxVector4(1, 1, 1, 1));
translation = rotationMatrix.MultNormalize(translation);


Should that work in theory?
Message 4 of 5
Anonymous
in reply to: Anonymous

So I think I have the solution. The trick was to extract just the rotation from the relative rotation matrix, and calculate the relative translation and scales by doing subtraction:


// Evaluate the node at the given time
KTime kTime;
kTime.SetSecondDouble(Time);
FbxAMatrix Transform = m_pFBXNode->EvaluateLocalTransform(kTime);
FbxVector4 Translation = Transform.GetT();
FbxQuaternion QuatRotation = Transform.GetQ();
FbxVector4 Scale = Transform.GetS();

// Make the values relative to time of 0
kTime.SetSecondDouble(0);
FbxAMatrix Frame0Transform = m_pFBXNode->EvaluateLocalTransform(kTime);
FbxVector4 Frame0Translation = Frame0Transform.GetT();
FbxQuaternion Frame0QuatRotation = Frame0Transform.GetQ();
FbxVector4 Frame0Scale = Frame0Transform.GetS();

Scale = Scale - Frame0Scale;
Translation = Translation - Frame0Translation;

Transform.SetT(FbxVector4(0, 0, 0, 1));
Frame0Transform.SetT(FbxVector4(0, 0, 0, 1));

FbxAMatrix InverseFrame0Transform = Frame0Transform.Inverse();

FbxAMatrix RelativeTransform = InverseFrame0Transform * Transform;
QuatRotation = RelativeTransform.GetQ();


Can anyone see any problems with this?
Message 5 of 5
jiayang.xu
in reply to: Anonymous

Yes, you are right. The magic here is R*T*R.Inv will just cancel out the rotation part and keep the translation part in the matrix, which is the to use R to transform the Tv vector.
Thanks for clarifying this!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report