0

I'm trying to implement raycasting with DirectX in C++ but have run into problems. I've tried two approaches, using XMVector3Unproject and following the instructions provided here on stackoverflow a while ago.

Unproject Approach:

//p is mouse location vector

//Don't know if I need to normalize mouse input
//p.x = (2.0f * p.x) / g_nScreenWidth - 1.0f;
//p.y = 1.0f - (2.0f * p.y) / g_nScreenHeight;

Vector3 orig = XMVector3Unproject(Vector3(p.x, p.y, 0),
                 0,
                 0,
                 g_nScreenWidth,
                 g_nScreenHeight,
                 0,
                 1,
                 GameRenderer.m_matProj,
                 GameRenderer.m_matView,
                 GameRenderer.m_matWorld);

Vector3 dest = XMVector3Unproject(Vector3(p.x, p.y, 1),
                 0,
                 0,
                 g_nScreenWidth,
                 g_nScreenHeight,
                 0,
                 1,
                 GameRenderer.m_matProj,
                 GameRenderer.m_matView,
                 GameRenderer.m_matWorld);

Vector3 direction = dest - orig;
direction.Normalize();

//shoot a bullet to visualize the ray for testing
g_cObjectManager.createObject(BUL_OBJ, "bullet", orig, direction*100);

Matrix Inversion Approach:

//Normalized device coordinates
p.x = (2.0f * p.x) / g_nScreenWidth - 1.0f;
p.y = 1.0f - (2.0f * p.y) / g_nScreenHeight;

XMVECTOR det; //Determinant, needed for matrix inverse function call
Vector3 origin = Vector3(p.x, p.y, 0);
Vector3 faraway = Vector3(p.x, p.y, 1);

XMMATRIX invViewProj = XMMatrixInverse(&det, GameRenderer.m_matView * GameRenderer.m_matProj);
Vector3 rayorigin = XMVector3Transform(origin, invViewProj);
Vector3 rayend = XMVector3Transform(faraway, invViewProj);
Vector3 raydirection = rayend - rayorigin;
raydirection.Normalize();

g_cObjectManager.createObject(BUL_OBJ, "bullet", rayorigin, raydirection * 5);

I assume at least the matrix inversion approach from stackoverflow should work, but for some reason my attempt doesn't. Do I need the world matrix as well, or is there some step I'm missing?

This is my first stackoverflow post, so if anything is unclear or more information is needed please let me know.

Community
  • 1
  • 1
  • Both approaches are equivalent. In fact, `XMVector3Unproject()` internally uses the computations from the second approach. Why do you think that the result is wrong? What is the `Vector3` type? DirectXMath has two kinds of data types for vectors and matrices. One plain structure (`XMFLOAT3`, `XMFLOAT4X4`, ...) and a type for data loaded into SIMD registers (`XMVECTOR`, `XMMATRIX`). You need to be sure to pass the correct ones. – Nico Schertler Sep 09 '16 at 13:14
  • I'm glad to hear they're equivalent, because `XMVectorUnproject()` looks much cleaner. `Vector3` seems to come from DirectXTK, and apparently is just a wrapper for the `XMVECTOR` type that simplifies operations and loading. I rewrote the function replacing all `Vector3`s with `XMVECTOR`s and got the same result so I don't think that's the issue. By the way, I should have specified the result - it looks like [this](https://gfycat.com/DescriptiveJointGrayling). The ray always originates at (512, 384, 1) and is cast toward the mouse. That's not correct, right? – JuniorRailsDev Sep 15 '16 at 03:05
  • Is your world matrix the identity when you call this? Are you sure that your bullet code is correct? Have you checked the actual values of `orig` and `dest`? – Nico Schertler Sep 15 '16 at 12:18
  • Oh yes, I forgot that I I had replaced the world matrix with the identity matrix in the unproject call. When I use the world matrix the ray originates at z = -900, y = -350, and varying negative x values depending on where I click (even depends on click height), and loosely follows the mouse movement. The bullet behavior matches the origin direction vectors I see when debugging with breakpoints. The reason the birds are being killed is because collision detection disregards z values at the moment, so when it reaches the correct x and y coords in the distance a collision is detected. – JuniorRailsDev Sep 15 '16 at 14:13
  • In your second version, where's the world matrix? – Michael Chourdakis Jun 05 '21 at 18:21

1 Answers1

0

In the end I realized my problem originated with switching from perspective to orthographic view to draw the HUD and never resetting the view matrix. I was able to use the XMVector3Unproject() function with the identity matrix in place of the world matrix and everything works flawlessly now.

Thanks Nico Schertler for the information and reassurance!