#define BUFFER_LENGTH 64
void CPipeLineView::pick(GLfloat xpos,GLfloat ypos)
{
// Space for selection buffer 定义拣选缓冲区
GLuint selectBuff[BUFFER_LENGTH];
//xpos,ypos;
GLint viewport[4];
GLdouble mvmatrix[16],projmatrix[16];
GLint realy;
double wx1,wy1,wz1;
double wx2,wy2,wz2;
// Setup selection buffer
glSelectBuffer(BUFFER_LENGTH, selectBuff);
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
glGetIntegerv(GL_VIEWPORT,viewport);
realy = viewport[3]-(GLint)ypos -1;// 左下角为坐标原点
gluUnProject((GLdouble)xpos,(GLdouble)realy,0.0,mvmatrix,projmatrix,viewport,&wx1,&wy1,&wz1);
gluUnProject((GLdouble)xpos,(GLdouble)realy,1.0,mvmatrix,projmatrix,viewport,&wx2,&wy2,&wz2);
rayStart.x =wx1;
rayStart.y =wy1;
rayStart.z =wz1;
rayEnd.x =wx2;
rayEnd.y =wy2;
rayEnd.z =wz2;
g_color = 0.0f;
char strName[50];
if (IntersectTriangle())
{
strcpy(strName,"you have selected the triangle");
//g_color=1.0f;
}
else
{
strcpy(strName,"you haven't selected the triangle");
}
AfxMessageBox(strName);
}
bool CPipeLineView::IntersectTriangle()
{
GLfloat edge1[3];
GLfloat edge2[3];
edge1[0]=V1[0]-V0[0];
edge1[1]=V1[1]-V0[1];
edge1[2]=V1[2]-V0[2];
edge2[0]=V2[0]-V0[0];
edge2[1]=V2[1]-V0[1];
edge2[2]=V2[2]-V0[2];
float dir[3];
dir[0]=rayEnd.x-rayStart.x;
dir[1]=rayEnd.y-rayStart.y;
dir[2]=rayEnd.z-rayStart.z;
GLfloat w = sqrt(pow(dir[0],2)+pow(dir[1],2)+pow(dir[2],2));
dir[0] /= w;
dir[1] /= w;
dir[2] /= w;
GLfloat pvec[3];
pvec[0]= dir[1]*edge2[2] - dir[2]*edge2[1];
pvec[1]= dir[2]*edge2[0] - dir[0]*edge2[2];
pvec[2]= dir[0]*edge2[1] - dir[1]*edge2[0];
GLfloat det ;
det = edge1[0]*pvec[0]+edge1[1]*pvec[1]+edge1[2]*pvec[2];
GLfloat tvec[3];
if( det > 0 )
{
tvec[0] =rayStart.x-V0[0];
tvec[1] =rayStart.y-V0[1];
tvec[2] =rayStart.z-V0[2];
}
else
{
tvec[0] =V0[0] -rayStart.x;
tvec[1] =V0[1] -rayStart.y;
tvec[2] =V0[2] -rayStart.z;
det = -det ;
}
if( det < 0.0001f ) return false;
GLfloat u ;
u = tvec[0]*pvec[0]+ tvec[1]*pvec[1]+ tvec[2]*pvec[2];
if( u < 0.0f || u > det ) return false;
GLfloat qvec[3];
qvec[0]= tvec[1]*edge1[2] - tvec[2]*edge1[1];
qvec[1]= tvec[2]*edge1[0] - tvec[0]*edge1[2];
qvec[2]= tvec[0]*edge1[1] - tvec[1]*edge1[0];
GLfloat v;
v = dir[0]*qvec[0]+dir[1]*qvec[1]+dir[2]*qvec[2];
if( v < 0.0f || u + v > det ) return false;
GLfloat t = edge2[0]*qvec[0]+edge2[1]*qvec[1]+edge2[2]*qvec[2];
GLfloat fInvDet = 1.0f / det;
t *= fInvDet;
u *= fInvDet;
v *= fInvDet;
return true;
}
void CPipeLineView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
pick(point.x,point.y);
DrawScene(GL_RENDER);
CView::OnLButtonDown(nFlags, point);
}
void CPipeLineView::DrawScene(GLint mode)
{
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glColor3f(g_color,0.0,1.0);
glVertex3fv(V0);// 如果加了glTranslatef之类的变换函数,射线应该反向变化
glVertex3fv(V1);
glVertex3fv(V2);
glEnd();
glTranslatef(2.0f,0.0f,-6.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0,g_color,0.0);
glVertex3fv(V1);
glVertex3fv(V0);
glVertex3fv(V2);
glEnd();
glPopMatrix();
SwapBuffers(wglGetCurrentDC());
}
实现的结果如图所示[img=http://bbs.csdn.net/][/img]
如图所示:右边的黄色圆圈的地方明明不是三角形区域,但是点击过后,却显示“你已经选中了三角形”,不知道这个问题,有没有大侠遇到过,谢谢指点!
9 个解决方案
#1
图呢?
#2
这里
pick 和 DrawScene 的调用顺序得掉换一下吧。pick 里面的
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
都是获得当前矩阵的,DrawScene 负责设置这些矩阵,先调用 pick 的话,这些矩阵还没设置好呢,计算结果当然有问题。
void CPipeLineView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
pick(point.x,point.y);
DrawScene(GL_RENDER);
CView::OnLButtonDown(nFlags, point);
}
pick 和 DrawScene 的调用顺序得掉换一下吧。pick 里面的
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
都是获得当前矩阵的,DrawScene 负责设置这些矩阵,先调用 pick 的话,这些矩阵还没设置好呢,计算结果当然有问题。
#3
[img=http://bbs.csdn.net/][/img]
图片显示不出来,网址:http://bbs.csdn.net/
图片显示不出来,网址:http://bbs.csdn.net/
#4
图片显示不出来,网址:http://bbs.csdn.net/
#5
你好,我试着调用了两者的顺序,还是不对,不知道大侠可否给出一点建议或者指点,谢谢!
#6
一时半会没了,得有完整的代码调试一下可能能发现问题,毕竟这里面数学比较多,得看看真正的计算结果才能搞明白。
#7
您好,您的邮箱是多少,我把程序发到您邮箱吧。
#8
我可以帮你调一下,不过你得先整一个能在 ubuntu 下能够用 g++ 独立编译并运行的程序。我看你的代码,应该是 MFC 的,我都没有 Windows。要是这样,我还得重新分区,再装系统,再装 VS,和其他你可能用到的类库,至少也得搞一整天,完事以后还得再删了,太费劲了。你把程序搞好以后,可以在这里通知我。
#9
真的很感谢您!
#1
图呢?
#2
这里
pick 和 DrawScene 的调用顺序得掉换一下吧。pick 里面的
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
都是获得当前矩阵的,DrawScene 负责设置这些矩阵,先调用 pick 的话,这些矩阵还没设置好呢,计算结果当然有问题。
void CPipeLineView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
pick(point.x,point.y);
DrawScene(GL_RENDER);
CView::OnLButtonDown(nFlags, point);
}
pick 和 DrawScene 的调用顺序得掉换一下吧。pick 里面的
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
都是获得当前矩阵的,DrawScene 负责设置这些矩阵,先调用 pick 的话,这些矩阵还没设置好呢,计算结果当然有问题。
#3
[img=http://bbs.csdn.net/][/img]
图片显示不出来,网址:http://bbs.csdn.net/
图片显示不出来,网址:http://bbs.csdn.net/
#4
图片显示不出来,网址:http://bbs.csdn.net/
#5
你好,我试着调用了两者的顺序,还是不对,不知道大侠可否给出一点建议或者指点,谢谢!
#6
一时半会没了,得有完整的代码调试一下可能能发现问题,毕竟这里面数学比较多,得看看真正的计算结果才能搞明白。
#7
您好,您的邮箱是多少,我把程序发到您邮箱吧。
#8
我可以帮你调一下,不过你得先整一个能在 ubuntu 下能够用 g++ 独立编译并运行的程序。我看你的代码,应该是 MFC 的,我都没有 Windows。要是这样,我还得重新分区,再装系统,再装 VS,和其他你可能用到的类库,至少也得搞一整天,完事以后还得再删了,太费劲了。你把程序搞好以后,可以在这里通知我。
#9
真的很感谢您!