如何找到鼠标单击和 3D 网格的交集?
在我的程序中,我正在加载 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 是否会考虑 multmatrix
和 glScalef
调用?
非常感谢!
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
解决方案是使用光线追踪。您发射的光线是通过两点定义的。第一个是相机的原点,第二个是投影在场景中的视图平面(您用 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
使用光线
dir
使光线从相机到场景,我应该使用:(注意传递给函数的不同向量)。这解决了我的问题,而且与 gluLookAt 没有任何关系!
另外,对于我问的问题的第二部分,是的,unproject 确实考虑了 glScale 和 glmultmatrix 函数。
making the ray from the camera to the scene using the ray
dir
, I should've used:(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.