directx-12

Why does XMVector3Transform return multiplcation by the transpose?


I have a XMFLOAT4X4 matrix m. Mathematically, I should obtain the last column of this matrix by multiplying m with the vector (0, 0, 0, 1).

I only need the first three components of that column. For that reason, I've tried the following computation:

XMFLOAT3 x{};
XMStoreFloat3(&y, XMVector3Transform(XMLoadFloat3(&x), m));

I'm obviously assuming here that XMVector3Transform(XMLoadFloat3(&x), m) is computing "(m * (0, 0, 0, 1)).xyz". Maybe this assumption is wrong.

Anyways, what I'm getting are the first three components of the last row instead. That is, I'm actually getting what I expected, but with m replaced by the transpose of m. Why is that and how can I get the right result (by a matrix-vector multiplication)?


Solution

  • DirectXMath provides C++ implementations of all functions, so you can see them in the .inl files:

    XMVECTOR XM_CALLCONV XMVector3Transform
    (
        FXMVECTOR V,
        FXMMATRIX M
    ) noexcept
    {
        XMVECTOR Z = XMVectorSplatZ(V);
        XMVECTOR Y = XMVectorSplatY(V);
        XMVECTOR X = XMVectorSplatX(V);
    
        XMVECTOR Result = XMVectorMultiplyAdd(Z, M.r[2], M.r[3]);
        Result = XMVectorMultiplyAdd(Y, M.r[1], Result);
        Result = XMVectorMultiplyAdd(X, M.r[0], Result);
    
        return Result;
    }
    

    This is a normal vector/matrix multiply assuming the implied 'w' in the vector3 is a 1.

    The result is NOT guaranteed to be a 3-vector with an implied 1. That's why there are other functions like XMVector3TransformCoord which divides by W and XMVector3TransformNormal which ignores the offset in the transformation matrix.

    Technically to transform a normal, you use the inverse of the transpose, and for pure rotation that results in the same matrix.