microsoft / DirectXMath

DirectXMath is an all inline SIMD C++ linear algebra library for use in games and graphics apps
https://walbourn.github.io/introducing-directxmath/
MIT License
1.54k stars 238 forks source link

XMMATRIX always NaN on CPU #122

Closed TheNosiriN closed 3 years ago

TheNosiriN commented 3 years ago

So I have this piece of code:

XMMATRIX matWorld = XMMatrixRotationY(3.14159f) * XMMatrixRotationZ(3.14159f * TIME);
XMVECTOR vecCamPos = XMVectorSet(0.0f, 0.0f, 2.5f, 0);
XMVECTOR vecCamLookAt = XMVectorSet(0, 0, 0, 0);
XMVECTOR vecCamUp = XMVectorSet(0, 1, 0, 0);
XMMATRIX matView = XMMatrixLookAtLH(vecCamPos, vecCamLookAt, vecCamUp);

XMMATRIX matProjection = XMMatrixPerspectiveFovLH(
    XMConvertToRadians(45.0f), w/h, 0.1f, 100.0f
);

XMMATRIX matMVP = matWorld * matView * matProjection;
std::cout << matMVP.r[0][0] << matMVP.r[1][0] << matMVP.r[1][1] << '\n';

Straight out from a tutorial I was following, but when I print some of the values they're -nan:

And when I view them individually they look like this: image

I don't know if this is a bug or a problem on my end but I'm using version 3.16 as I downloaded the release package mid January.

shawnhar commented 3 years ago

I'd suggest debugging through this code to find exactly where the NaN is originating. Wild guess: what are w and h set to?

VladSerhiienko commented 3 years ago

Ensure TIME, w and h are valid values. Use 1 in w components for vectors: camPos = vectorSet(x,y,z,1)

TheNosiriN commented 3 years ago

I have replaced all the w in the vectors with 1 and printed w h and time this is the new code:

XMMATRIX matWorld = XMMatrixRotationY(3.14159f) * XMMatrixRotationZ(3.14159f * TIME);
XMVECTOR vecCamPos = XMVectorSet(0.0f, 0.0f, 2.5f, 1);
XMVECTOR vecCamLookAt = XMVectorSet(0, 0, 0, 1);
XMVECTOR vecCamUp = XMVectorSet(0, 1, 0, 1);
XMMATRIX matView = XMMatrixLookAtLH(vecCamPos, vecCamLookAt, vecCamUp);

std::cout << w << " " << h << " " << TIME << '\n';
XMMATRIX matProjection = XMMatrixPerspectiveFovLH(
   XMConvertToRadians(45.0f), w/h, 0.1f, 100.0f
);

XMMATRIX matMVP = matWorld * matView * matProjection;
std::cout << matMVP.r[0][0] << matMVP.r[1][0] << matMVP.r[1][1] << '\n';

and it gave me this result: w = 640, h = 360, TIME = 2.594 image

I am yet to debug through the header's functions however. I will try later using Visual Studio 2019

walbourn commented 3 years ago

Not sure what else is going on, but at least part of the problem is that this is ill-formed code:

std::cout << matMVP.r[0][0] << matMVP.r[1][0] << matMVP.r[1][1] << std::endl;

I'm not sure who you got it to build. Current VS 2019 rejects it:

error C2676: binary '[': 'DirectX::XMVECTOR' does not define this operator or a conversion to a type acceptable to the predefined operator

The r element of the XMMATRIX union an XMVECTOR. If you want individual element access, you can use m[][], but only if building with _XM_NO_INTRINSICS_.

The robust and portable solution for output is:

XMFLOAT4X4 matOut;
XMStoreFloat4x4(&matOut, matMVP);
std::cout << matOut.m[0][0] << " " << matOut.m[1][0] << " " << matOut.m[1][1] << std::endl;
walbourn commented 3 years ago

I have this completely stand-alone version of your repro:

#include <DirectXMath.h>
#include <iostream>

using namespace DirectX;

void main()
{
   float w = 640.f;
   float h = 360.f;
   float TIME = 2.594;

   XMMATRIX matWorld = XMMatrixRotationY(3.14159f) * XMMatrixRotationZ(3.14159f * TIME);
   XMVECTOR vecCamPos = XMVectorSet(0.0f, 0.0f, 2.5f, 1);
   XMVECTOR vecCamLookAt = XMVectorSet(0, 0, 0, 1);
   XMVECTOR vecCamUp = XMVectorSet(0, 1, 0, 1);
   XMMATRIX matView = XMMatrixLookAtLH(vecCamPos, vecCamLookAt, vecCamUp);

   std::cout << w << " " << h << " " << TIME << '\n';
   XMMATRIX matProjection = XMMatrixPerspectiveFovLH(
   XMConvertToRadians(45.0f), w/h, 0.1f, 100.0f);

   XMMATRIX matMVP = matWorld * matView * matProjection;

   XMFLOAT4X4 matOut;
   XMStoreFloat4x4(&matOut, matMVP);
   std::cout << matOut.m[0][0] << " " << matOut.m[1][0] << " " << matOut.m[1][1] << std::endl;
}

When I build and run it, I get:

640 360 2.594
-0.395217 1.29921 -0.702609
walbourn commented 3 years ago

What version of compiler are you running exactly? From a developer command prompt type cl -Bv and capture the output.

TheNosiriN commented 3 years ago

I am using GCC 10.2.0 compiler in a cygwin environment and _XM_SSEINTRINSICS is defined in the matrix header. Thank you for helping me with this code. Unfortunately when I run it I get this output:

$ ./main
640 360 2.594
0 0 0

run with both _XM_SSEINTRINSICS and _XM_NOINTRINSICS

walbourn commented 3 years ago

You should have _XM_SSE_INTRINSICS_ defined before including DirectXMath.h. Normally it's enabled by default if you are using the latest DirectXMath which is offered by vcpkg.

walbourn commented 3 years ago

Built this code on WSL for Linux (x64) using GNC 9.3.0

CMakeLists.txt

cmake_minimum_required (VERSION 3.11)

project(mytest LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(test main.cpp)

find_package(directxmath CONFIG REQUIRED)
target_link_libraries(test PRIVATE Microsoft::DirectXMath)

main.cpp

#include <iostream>

#include <DirectXMath.h>
using namespace DirectX;

int main()
{
   float w = 640.f;
   float h = 360.f;
   float TIME = 2.594;

   XMMATRIX matWorld = XMMatrixRotationY(3.14159f) * XMMatrixRotationZ(3.14159f * TIME);
   XMVECTOR vecCamPos = XMVectorSet(0.0f, 0.0f, 2.5f, 1);
   XMVECTOR vecCamLookAt = XMVectorSet(0, 0, 0, 1);
   XMVECTOR vecCamUp = XMVectorSet(0, 1, 0, 1);
   XMMATRIX matView = XMMatrixLookAtLH(vecCamPos, vecCamLookAt, vecCamUp);

   std::cout << w << " " << h << " " << TIME << '\n';
   XMMATRIX matProjection = XMMatrixPerspectiveFovLH(
   XMConvertToRadians(45.0f), w/h, 0.1f, 100.0f);

   XMMATRIX matMVP = matWorld * matView * matProjection;

   XMFLOAT4X4 matOut;
   XMStoreFloat4x4(&matOut, matMVP);
   std::cout << matOut.m[0][0] << " " << matOut.m[1][0] << " " << matOut.m[1][1] << std::endl;

   return 0;
}

I'm using vcpkg for directxmath:

git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
sh bootstrap-vcpkg.sh
./vcpkg install directxmath
cmake -DCMAKE_TOOLCHAIN_FILE=/home/walbourn/vcpkg/scripts/buildsystems/vcpkg.cmake .
cmake -build .
./test

Output:

640 360 2.594
-0.395217 1.29921 -0.702609
walbourn commented 3 years ago

Same result using x64-linux with GNUC 10.2

Same result with arm64-linux with both GNUC 9.3.0 and GNUC 10.2.