Search code examples
c++mathmatrixunreal-engine4

Calculating unskinned pos from skinned pos


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?


Solution

  • 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.