[DirectX12学习笔记] 鼠标点选

本文介绍了如何在DirectX12中实现鼠标点击选择3D物体的功能,涉及从屏幕坐标到世界坐标的射线转换,以及Ray与AABB、Sphere、Triangle的碰撞检测方法。通过示例代码展示了一个可以高亮选中面片的Demo,当鼠标右键点击时,选取的物体面片会被高亮渲染。
摘要由CSDN通过智能技术生成
  • 注意!本文是在下几年前入门期间所写(young and naive),其中许多表述可能不正确,为防止误导,请各位读者仔细鉴别。

实现鼠标点选功能


检测方法

有的时候,我们要检测鼠标在屏幕上选中了哪个三维物体,很多3d建模软件之类的软件里面有这种功能,一般做法是用一条射线找出相交的最近的物体。

首先我们需要得到直线的方程式,假如我们知道屏幕上鼠标选中的像素点的位置sx和sy,这是两个整数坐标,然后知道视锥的宽高比r和fov角度alpha,宽和高w和h,那么投影空间里的直线方程如下
在这里插入图片描述
然后我们知道投影矩阵的P00和P11
在这里插入图片描述
在这里插入图片描述
所以上式可以化为
在这里插入图片描述
通过这个式子我们就可以求得投影坐标下的直线方程,然后我们还要把它变换到世界坐标,即乘个V的逆矩阵
在这里插入图片描述
然后现在我们有两种选择,一种是把物体的三角面变换到世界空间下来求交点,一种是把直线变换到物体空间下求交点,显然后者效率更高,因为我们只要变换一条直线,而前者的话我们要变换几千几万个三角面。所以我们选择再乘个W的逆矩阵来变换到局部空间。
在这里插入图片描述
变换的代码如下,注意XMVector3TransformCoord这个方法是将第四维认定成1,故可以用来变换点,XMVector3TransformNormal这个方法是将第四维认定成0,故可以用来变换矢量。

for(auto ri : mRitemLayer[(int)RenderLayer::Opaque]) {
   
auto geo = ri->Geo;
// Skip invisible render-items.
if(ri->Visible == false) continue;
XMMATRIX V = mCamera.GetView();
XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(V), V);
XMMATRIX W = XMLoadFloat4x4(&ri->World);
XMMATRIX invWorld = XMMatrixInverse(&XMMatrixDeterminant(W), W);
// Tranform ray to vi space of Mesh.
XMMATRIX toLocal = XMMatrixMultiply(invView, invWorld);
rayOrigin = XMVector3TransformCoord(rayOrigin, toLocal);
rayDir = XMVector3TransformNormal(rayDir, toLocal);
// Make the ray direction unit length for the intersection tests.
rayDir = XMVector3Normalize(rayDir);

然后是碰撞检测,检测用到的函数有三个,一个是Ray/AABB的碰撞检测

bool XM_CALLCONV BoundingBox::Intersects(
FXMVECTOR Origin,	 // ray origin
FXMVECTOR Direction,// ray	direction (must be unit length)
float& Dist ); const// ray intersection parameter 

其中第三个是输出变量,输出的是以下方程中的t0。
在这里插入图片描述
接下来是Ray/Sphere

bool XM_CALLCONV
BoundingSphere::Intersects(
FXMVECTOR Origin,
FXMVECTOR Direction
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值