Hey guys I'm trying to calculate the unskinned pos from skinned pos.
A skinned pos is calculated like this:
FMatrix Matrices[3];
float Weights[3];
FVector Pos;
FVector NewPos;
for( int i = 0; i < 3; i++)
{
NewPos += Matrices[i].TransformPosition(Pos) * Weights[i];
}
How do I calculate Pos, when the Matrices, Weights, and NewPos are know?
I know that for a single transformation it is:
Pos = Matrices[0].InverseTransformPosition(NewPos / Weights[0]);
Is it even possible to recalculate Pos, and if it is how should that be done?
You can think of this TransformPosition
call as a matrix times vector multiplication. The weight can be applied to the matrix, too. So you have
M1*pos*w1 + M2*pos*w2 + M3*pos*w3 = (w1*M1 + w2*M2 + w3*M3)*pos
In other words, you can use the weights to scale the matrices, then add the matrices. The result will be a single matrix which combines your whole operation. Then you can use the inverse transformation from that.
FMatrix Combined;
for( int i = 0; i < 3; i++) {
Combined += Matrices[i] * Weights[i];
}
Combined *= 1 / Combined.M[3][3];
Pos = Combined.InverseTransformPosition(NewPos);
The normalization step where I divide by the bottom right corner element shouldn't be neccessary if the engine were handling homogeneous coordinates correctly, but apparently that's not the case. So one shouldn't use FVector
if the matrices might be representing a non-affine projective transformation (last row not 0 0 0 *
) but use an FVector4
instead. And if one wants to use FVector
one has to scale the matrix to make the last row 0 0 0 1
as I do above.