glLoadName(name); //设置名字drawObj();
}else{drawObj();}
2.鼠标处理:
在选择模式下绘制
注意:1.正确的设置拾取视景体;并且还原原始的视景体;
2.正确的使用原始的模型视图变换;不一定需要还原(如果模型视图没有变化);
3.正确的还原原始的渲染状态;注意下划线;
GLuint selectBuff[512];
GLint hits, viewport[4];
glSelectBuffer(512, selectBuff);
glGetIntegerv(GL_VIEWPORT, viewport);
glRenderMode(GL_SELECT);//进入选择模式,一下绘制不再显示;
glInitNames();
glPushName(0);
int n = 3;//拾取浮动范围;
glMatrixMode(GL_PROJECTION);
glPushMatrix(); //保存视图矩阵;
glLoadIdentity();//归零,用于重新计算;
gluPickMatrix((GLdouble) x, (GLdouble) (viewport[3] - y), n, n, viewport);
gluPerspective(60.0,(GLsizei)5 / (GLsizei)5,0.1 , 10.0); //设定失去视景体;
gluOrtho2D(-0.6,0.6,0.6,0.6);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
{
glTranslatef(0,0,-9.0f);
glTranslatef(dx,dy,dz);
glRotatef(angle,0, 1.0f, 0);
glTranslatef(-96.0f,-94.0f,-56.0f);
}//选择模式下的模型视图变化*/
RenderObjects(GL_SELECT);//以选择模式绘制;进入绘制部分
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
hits = glRenderMode (GL_RENDER);
processHits(hits,selectBuff);
3.处理部分:注意每个拾取的数据结构即可;
击中的物件的名字的数目 |
这个物件中最近的点的深度值 |
这个物件中最远的点的深度值 |
击中的物件的名字之一 |
击中的物件的名字之二 (若有多个名字,则如此类推...) |
void processHits(GLint hits,GLuint buffer[]){/**/
printf("hits = %d\n",hits);
GLuint *ptr = (GLuint *)buffer;
GLuint names;
for(int i = 0;i<hits;i++){
names = *ptr;
//printf("numeber of names for this hit = %d ",names);
ptr++;
//printf("\t z1 is %f \n",(float)*ptr/0x7fffffff);
ptr++;
//printf("\t z1 is %f \n",(float)*ptr/0x7fffffff);
ptr++;
//printf("\t name are : %d \n" , *ptr);
hited.push_back(*ptr);
ptr++;
}
glutPostRedisplay();
}
4.gluPickMatrix()的使用;
5.各种矩阵的获取与使用;
其二:射线拾取
第一步: 实现屏幕坐标到三维世界空间坐标的转化,利用函数 gluUnProject直接可以得到屏幕坐标相应的三维空间坐标。
- gluUnProject((GLdouble)xpos,(GLdouble)ypos,1.0,mvmatrix,projmatrix,viewport,&wx,&wy,&wz);
- //xpos,ypos 是以屏幕左下角为原点的屏幕坐标.
- //1.0代表返回zbuffer为1.0处(远剪切面交点)的世界坐标
- //mvmatrix 为视矩阵,通过GetDoublev(GL_MODELVIEW_MATRIX,mvmatrix)得到
- //projmatrix为投影矩阵,通过glGetDoublev(GL_PROJECTION_MATRIX,projmatrix)得到
- //viewport为视口,通过glGetIntegerv(GL_VIEWPORT,viewport)得到
- //wx、wy、wz 就是我们要得到的世界坐标,得到这样两个世界坐标,射线就确定了
- //或者也可以用原点(视点)来代替其中一个点,因为这条射线是从视点出发的。
第二步:
用射线和要检测的三角形求交点,用到的原理和公式如下。 原理一:三角形内的任意一点都可以用变量u、v和其三个顶点坐标来确定- vPoint = V1 + u*(V2-V1) + v*(V3-V1) ;
- //0
- //V1,V2,V3为三角形的三个顶点,是已知量
原理二:射线上的任意一点可以用射线的方向向量(格式化后的)乘以其模(该向量长度)来表示
- vPoint =originPoint+dir * len;
射线和三角形相交则必定同时满足上面的两个条件所以有:
- (-Dir)*len+ (V2-V1)*u + (V3-V1)*v = originPoint-V1;