【问题标题】:Mouse picking with ray casting in DirectX在 DirectX 中使用光线投射进行鼠标拾取
【发布时间】:2016-09-18 00:07:45
【问题描述】:

我正在尝试在 C++ 中使用 DirectX 实现光线投射,但遇到了问题。我尝试了两种方法,使用XMVector3Unproject 并按照前段时间here on stackoverflow 提供的说明进行操作。

取消项目方法:

//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);

矩阵求逆法:

//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);

我认为至少来自 stackoverflow 的矩阵求逆方法应该有效,但由于某种原因,我的尝试没有。我是否也需要世界矩阵,还是缺少某些步骤?

这是我的第一篇 stackoverflow 帖子,如果有任何不清楚或需要更多信息,请告诉我。

【问题讨论】:

  • 两种方法是等效的。事实上,XMVector3Unproject() 在内部使用了第二种方法的计算。为什么你认为结果是错误的? Vector3 类型是什么? DirectXMath 有向量和矩阵两种数据类型。一个简单的结构(XMFLOAT3XMFLOAT4X4、...)和一种加载到 SIMD 寄存器中的数据类型(XMVECTORXMMATRIX)。你需要确保通过正确的。
  • 我很高兴听到它们是等效的,因为XMVectorUnproject() 看起来更干净。 Vector3 似乎来自 DirectXTK,显然只是 XMVECTOR 类型的包装器,可简化操作和加载。我重写了用XMVECTORs 替换所有Vector3s 的函数,得到了相同的结果,所以我认为这不是问题所在。顺便说一句,我应该指定结果 - 它看起来像 this。光线始终从 (512, 384, 1) 开始,并投射到鼠标。这不正确,对吧?
  • 当你调用这个时,你的世界矩阵是身份吗?您确定您的项目符号代码是正确的吗?你检查过origdest的实际值吗?
  • 哦,是的,我忘记了我在 unproject 调用中用单位矩阵替换了世界矩阵。当我使用世界矩阵时,光线起源于 z = -900,y = -350,并且根据我点击的位置(甚至取决于点击高度)而变化的负 x 值,并且松散地跟随鼠标移动。项目符号的行为与我在使用断点进行调试时看到的原点方向向量相匹配。鸟类被杀死的原因是因为碰撞检测此时忽略了 z 值,所以当它到达正确的 x 和 y 坐标时,就会检测到碰撞。
  • 在你的第二个版本中,世界矩阵在哪里?

标签: c++ matrix 3d directx raycasting


【解决方案1】:

最后我意识到我的问题源于从透视图切换到正交视图以绘制 HUD 并且从未重置视图矩阵。我能够使用 XMVector3Unproject() 函数和单位矩阵代替世界矩阵,现在一切正常。

感谢 Nico Schertler 提供的信息和保证!

【讨论】:

    猜你喜欢
    • 2018-08-05
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    • 2013-08-17
    • 2014-07-24
    相关资源
    最近更新 更多