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)?
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.