主题:openGL选择中遇到问题
nansure
[专家分:0] 发布于 2010-10-14 10:58:00
void CMiddleView::processSelection(int x , int y)
{
GLdouble modelview[16];
GLdouble projection[16];
GLuint selectBuf[512];
GLint hits;
GLint viewport[4];
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
glSelectBuffer(512,selectBuf);
(void)glRenderMode(GL_SELECT);
//glInitNames();
//glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix((GLdouble)(x), (GLdouble)(viewport[3]-y), 3.0, 3.0, viewport);
glMultMatrixd(projection);
glMultMatrixd(modelview);
//gluPerspective(45,(viewport[2]-viewport[0])/(viewport[3]-viewport[1]),0.1,100);
glMatrixMode(GL_MODELVIEW);
Object(GL_SELECT);
hits = glRenderMode(GL_RENDER);
if ( hits > 0 )
{
processHits(hits,selectBuf);
}else printf("未选中");
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
结果显示总是hit=0,我做的是一个三维网格,想选其中的某个单元,用gluLookAt控制模型的旋转放大等,求教
回复列表 (共4个回复)
沙发
eastcowboy [专家分:25370] 发布于 2010-10-15 17:35:00
看不出问题,我的代码与楼主的差不多,但运行正常。
代码如下:
[code=c]#include <GL/glut.h>
// 在四种颜色之间切换
static const int COLOR_COUNT = 4;
// 四种颜色
static GLfloat s_color_table[COLOR_COUNT][3] = {
{0.5f, 0.0f, 0.0f},
{0.0f, 0.5f, 0.0f},
{0.0f, 0.0f, 0.5f},
{0.5f, 0.5f, 0.0f},
};
// 当前使用的颜色
static int s_color_index = 0;
// 旋转
static GLfloat rotate = 0;
static void draw() {
glPushMatrix();
glRotatef(rotate, 0, 1, 0);
glutSolidTeapot(20);
glPopMatrix();
}
static void display() {
// 设置矩阵
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1, 0.5, 500);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 50, 100, 0, 0, 0, 0, 1, 0);
// 设置颜色
glColor3fv(s_color_table[s_color_index]);
// 绘制
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw();
glutSwapBuffers();
glutPostRedisplay();
glutReportErrors();
// 旋转
rotate += 0.3f;
if (rotate >= 360.0f) {
rotate -= 360.0f;
}
}
static void mouse(int button, int state, int x, int y) {
// 只响应鼠标左键按下的消息,其它一律略过
if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN) {
return;
}
// 纵向坐标需要反转
// 因为GLUT把左上角作为坐标原点,而OpenGL把左下角作为坐标原点
int windowWidth = glutGet(GLUT_WINDOW_WIDTH);
int windowHeight = glutGet(GLUT_WINDOW_HEIGHT);
y = windowHeight - y;
// 取得viewport和projectionMatrix
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
GLfloat modelviewMatrix[16];
GLfloat projectionMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
const int SELECT_BUFFER_SIZE = 256;
GLuint arrSelectBuffer[SELECT_BUFFER_SIZE];
// OpenGL选择模式,代码
glSelectBuffer(SELECT_BUFFER_SIZE, arrSelectBuffer);
glRenderMode(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(x, y, 1, 1, viewport);
glMultMatrixf(projectionMatrix);
glMultMatrixf(modelviewMatrix);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// glInitNames();
// glPushName(0);
draw();
GLint r = glRenderMode(GL_RENDER);
// 如果鼠标点中了物体,修改物体颜色
if (r != 0) {
++s_color_index;
if (s_color_index >= COLOR_COUNT) {
s_color_index = 0;
}
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow("test");
glutDisplayFunc(&display);
glutMouseFunc(&mouse);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glutMainLoop();
return 0;
}[/code]
但我更喜欢不要修改model view矩阵,像这样做:
glSelectBuffer(SELECT_BUFFER_SIZE, arrSelectBuffer);
glRenderMode(GL_SELECT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(x, y, 1, 1, viewport);
glMultMatrixf(projectionMatrix);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// glInitNames();
// glPushName(0);
draw();
GLint r = glRenderMode(GL_RENDER);
// 如果鼠标点中了物体,修改物体颜色
if (r != 0) {
++s_color_index;
if (s_color_index >= COLOR_COUNT) {
s_color_index = 0;
}
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
这样可以避免取回model view矩阵。并且由于使用push/pop,完成之后model view矩阵可以维持不变。
板凳
nansure [专家分:0] 发布于 2010-10-16 09:01:00
我不是用glRotatef这些函数来控制,而是用gluLookAt,是不是在改变视角的时候也要push/pop?
3 楼
eastcowboy [专家分:25370] 发布于 2010-10-16 10:42:00
[quote]我不是用glRotatef这些函数来控制,而是用gluLookAt,是不是在改变视角的时候也要push/pop?[/quote]
用什么函数来控制都无所谓,反正都是操作model view矩阵。这个应该不是重点。
我觉得最关键的一点是,各个矩阵之间应该满足这个关系:选择时所用矩阵,正好就是gluPickMatrix所得矩阵乘以渲染时所用矩阵。
所有需要进行选择的图形,全部都要满足这个关系才行。楼主可以针对这一点进行检查。
楼主的代码中,把原来的model view矩阵乘到projection矩阵里面去了,这时如果绘制物体的代码里还有对projection矩阵的操作的话,就无法满足上述关系(因为矩阵乘法只有结合律,没有交换律),导致选择失败。还有就是model view矩阵,如果执行glGetDoublev(GL_MODELVIEW_MATRIX, modelview);之时它就已经乘过gluLookAt的矩阵,在绘制之时如果再乘一次,也会造成上述关系无法满足。
总之,多多的检查矩阵处理吧。楼主加油。
4 楼
nansure [专家分:0] 发布于 2010-10-17 09:37:00
谢了,再仔细检查下
我来回复