如何找到鼠标单击和 3D 网格的交集?

发布于 2024-10-05 14:14:50 字数 1553 浏览 3 评论 0原文

在我的程序中,我正在加载 3D 网格以进行查看和交互。用户可以旋转和缩放视图。我将使用旋转矩阵进行旋转,并调用 multmatrix 来旋转视图,并使用 glScalef 进行缩放。用户还可以绘制网格,这就是为什么我需要平移鼠标坐标以查看它是否与网格相交。

我读过 http://www.opengl.org/resources/faq/technical /selection.htm 以及我在近平面和远平面使用 gluUnproject 并相减的方法,并且我取得了一些成功,但仅当 gluLookAt 的位置为 (0, 0, z) 时,其中 z 可以是任何合理的数量。当我将位置移动到 (0, 1, z) 时,它会变得混乱并返回只有空白空间的交集,并且在网格明显位于鼠标下方的情况下不返回交集。

这就是我从鼠标单击到场景的光线的方式:

float hx, hy;
hx = mouse_x;
hy = mouse_y;

GLdouble m1x,m1y,m1z,m2x,m2y,m2z;
GLint viewport[4];
GLdouble projMatrix[16], mvMatrix[16];
glGetIntegerv(GL_VIEWPORT,viewport);
glGetDoublev(GL_MODELVIEW_MATRIX,mvMatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);

//unproject to find actual coordinates
gluUnProject(hx,scrHeight-hy,2.0,mvMatrix,projMatrix,viewport,&m1x,&m1y,&m1z);
gluUnProject(hx,scrHeight-hy,10.0,mvMatrix,projMatrix,viewport,&m2x,&m2y,&m2z);

gmVector3 dir = gmVector3(m2x,m2y,m2z) - gmVector3(m1x,m1y,m1z);
dir.normalize();

gmVector3 point;
bool intersected = findIntersection(gmVector3(0,0,5), dir, point);

如果这有什么区别的话,我正在使用 glFrustum。

findIntersection 代码确实很长,而且我非常有信心它可以工作,所以除非有人想看到它,否则我不会发布它。其要点是,对于网格中的每个面,找到射线与平面之间的交点,然后查看交点是否在面内部。

我相信这与相机的位置和查看矢量有关,但我不知道如何以及如何处理它们,以便鼠标正确单击网格。谁能帮我解决这个问题吗?

我还没有使用 glScalef 制作旋转矩阵或任何东西,所以有人可以让我深入了解这一点吗?例如,计算时 unproject 是否会考虑 multmatrixglScalef 调用?

非常感谢!

In my program I'm loading in a 3D mesh to view and interact with. The user can rotate and scale the view. I will be using a rotation matrix for the rotation and calling multmatrix to rotate the view, and scaling using glScalef. The user can also paint the mesh, and this is why I need to translate the mouse coordinates to see if it intersects with the mesh.

I've read http://www.opengl.org/resources/faq/technical/selection.htm and the method where I use gluUnproject at the near and far plane and subtracting, and I have some success with it, but only when gluLookAt's position is (0, 0, z) where z can be any reasonable number. When I move the position to say (0, 1, z), it goes haywire and returns an intersection where there is only empty space, and returns no intersection where the mesh is clearly underneath the mouse.

This is how I'm making the ray from the mouse click to the scene:

float hx, hy;
hx = mouse_x;
hy = mouse_y;

GLdouble m1x,m1y,m1z,m2x,m2y,m2z;
GLint viewport[4];
GLdouble projMatrix[16], mvMatrix[16];
glGetIntegerv(GL_VIEWPORT,viewport);
glGetDoublev(GL_MODELVIEW_MATRIX,mvMatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);

//unproject to find actual coordinates
gluUnProject(hx,scrHeight-hy,2.0,mvMatrix,projMatrix,viewport,&m1x,&m1y,&m1z);
gluUnProject(hx,scrHeight-hy,10.0,mvMatrix,projMatrix,viewport,&m2x,&m2y,&m2z);

gmVector3 dir = gmVector3(m2x,m2y,m2z) - gmVector3(m1x,m1y,m1z);
dir.normalize();

gmVector3 point;
bool intersected = findIntersection(gmVector3(0,0,5), dir, point);

I'm using glFrustum if that makes any difference.

The findIntersection code is really long and I'm pretty confident it works, so I won't post it unless someone wants to see it. The gist of it is that for every face in the mesh, find intersection between the ray and the plane, then see if the intersection point is inside the face.

I believe that it has to do with the camera's position and look at vector, but I don't know how, and what to do with them so that the mouse clicks on the mesh properly. Can anyone help me with this?

I also haven't yet made the rotation matrix or anything with the glScalef, so can anyone give me insight into this? Like, does unproject account for the multmatrix and glScalef calls when calculating?

Many thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦里梦着梦中梦 2024-10-12 14:14:50

解决方案是使用光线追踪。您发射的光线是通过两点定义的。第一个是相机的原点,第二个是投影在场景中的视图平面(您用 glFrustum 描述的平面)上的鼠标位置。该射线与模型的交点是鼠标单击击中模型的点

The solution is with raytracing. The ray you shoot is defined through two points. The first one is the origin of the camera, the second one is the mouse position projected on the view plane in the scene (the plane you describe with glFrustum). The intersection of this ray with you model is the point where your mouse click has hit the model

离旧人 2024-10-12 14:14:50

使用光线dir使光线从相机到场景,我应该使用:(

bool intersected = findIntersection(gmVector3(m1x,m1y,m1z), dir, point); 

注意传递给函数的不同向量)。这解决了我的问题,而且与 gluLookAt 没有任何关系!

另外,对于我问的问题的第二部分,是的,unproject 确实考虑了 glScale 和 glmultmatrix 函数。

making the ray from the camera to the scene using the ray dir, I should've used:

bool intersected = findIntersection(gmVector3(m1x,m1y,m1z), dir, point); 

(notice the different vector being passed to the function). This solved my problem, and didn't have anything to do with the gluLookAt after all!

Also, for the second part of the question that I asked, yes, the unproject does take into account the glScale and glmultmatrix functions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文