我有以下代码:
#define GLUT_DISABLE_ATEXIT_HACK
#include <GL/glut.h>
#include <GL/gl.h>
#include <math.h>
#include <stdio.h>
GLfloat ctrlptsBezier[4][4][3] =
{
{
{-2.0, -2.0, 1.0},
{-0.5, -2.0, 0.0},
{0.5, -2.0, 0.0},
{2.0, -2.0, 1.0}},
{
{-2, -0.5, -1.0},
{-0.5, -0.5, 0.0},
{0.5, -0.5, 0.0},
{2.0, -0.5, 0.0}},
{
{-2, 0.5, 0.0},
{-0.5, 0.5, -2.0},
{0.5, 0.5, 0.0},
{2.0, 0.5, 0.0}},
{
{-2.0, 2.0, 1.0},
{-0.5, 2.0, 0.0},
{0.5, 2.0, 0.0},
{2.0, 2.0, 1.0}}
};
int uSteps = 30;
int vSteps = 30;
bool shade = false;
GLfloat black [] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 };
GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
GLfloat peach[] = { 1.0, 0.5, 0.5, 1.0 };
GLfloat purple[] = { 0.5, 0.0, 0.5, 1.0 };
GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
//Initial eye/viewpoint coords.
double xPos = -20.0, zPos = -20.0;
double eyeHeight = 4.5;
double eyeIncline = -0.5;
double theta = 0.0; //Rotation angle in rads
//Movement params (camera)
double posIncr = 0.25;
double thetaIncr = 0.1;
#define BUFSIZE 512 //Pick buffer size
void setObjLight( bool s )
{
int shadeNumber = GL_FLAT;
if ( shade == true )
shadeNumber = GL_SMOOTH;
glShadeModel(shadeNumber);
}
void setLights(void)
{
setObjLight(shade);
}
void drawRoom(void)
{
GLfloat floor_color[] = { 0.5, 0.5, 0.5, 1.0 }; //Grey floor
GLfloat blue_wall[] = { 0.0, 0.0, 1.0, 1.0 };
GLfloat green_wall[] = { 0.0, 1.0, 0.0, 1.0 };
GLfloat purple_wall[] = { 0.5, 0.0, 0.5, 1.0 };
//FLOOR
glMaterialfv(GL_FRONT, GL_DIFFUSE, floor_color);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0, 0.0, -25.0);
glVertex3f( 25.0, 0.0, -25.0);
glVertex3f( 25.0, 0.0, 25.0);
glVertex3f(-25.0, 0.0, 25.0);
glEnd();
//WALLS
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, blue_wall);
glPushMatrix();
glTranslatef(0.0, 0.0, 25.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0,-25.0,0.0);
glVertex3f(25,-25.0,0);
glVertex3f(25, 25, 0);
glVertex3f(-25, 25, 0);
glEnd();
glPopMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, green_wall);
glPushMatrix();
glTranslatef(0.0, 0.0, -25.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0,-25.0,0.0);
glVertex3f(25,-25.0,0);
glVertex3f(25, 25, 0);
glVertex3f(-25, 25, 0);
glEnd();
glPopMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, purple_wall);
glPushMatrix();
glTranslatef(25.0, 0.0, 0.0);
glRotatef(90.0, 0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-25.0,-25.0,0.0);
glVertex3f(25,-25.0,0);
glVertex3f(25, 25, 0);
glVertex3f(-25, 25, 0);
glEnd();
glPopMatrix();
}
void drawShapes()
{
//SPHERE
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, blue);
glNormal3f(0.0, 1.0, 0.0);
glTranslatef(0.0, 2.0, 0.0);
glLoadName(1);
glutSolidSphere (2.0, 20, 16);
glPopMatrix();
glFlush();
//CONE
glPushMatrix();
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, purple);
glNormal3f(0.0, 1.0, 0.0);
glTranslatef(5.0, 0.0, 0.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glLoadName(2);
glutSolidCone (2.0, 3, 20, 16);
glPopMatrix();
glFlush();
glLoadName(0);
}
void drawBezier()
{
glEnable(GL_MAP2_VERTEX_3);
glPushMatrix();
glTranslatef(10, 2, 15);
glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(13, 2, 18);
glRotatef(-90, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, red);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(7, 2, 18);
glRotatef(90, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(10, 2, 21);
glRotatef(180, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, peach);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
glPushMatrix();
glTranslatef(10, 5, 18);
glRotatef(90.0, 1.0, 0.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, black);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlptsBezier[0][0][0]);
glMapGrid2f(uSteps, 0.0, 1.0, vSteps, 0.0, 1.0);
glEvalMesh2(GL_FILL, 0, uSteps, 0, vSteps);
glPopMatrix();
//Sphere for filler
glPushMatrix();
glTranslatef(10, 2, 18);
glRotatef(90.0, 1.0, 0.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
glutSolidSphere(3.0, 20, 16);
glPopMatrix();
glFlush();
}
void drawScene(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
double atx = xPos + cos(theta);
double atz = zPos + sin(theta);
double atHeight = eyeHeight + eyeIncline;
gluLookAt(xPos, eyeHeight, zPos, atx, atHeight, atz, 0.0, 1.0, 0.0);
glPushMatrix();
setLights();
drawRoom();
drawShapes();
glLoadName(3);
drawBezier();
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawScene();
glutSwapBuffers();
}
void setProjection(void)
{
gluPerspective(60.0, 1.0, 0.1, 100.0);
}
void init(void)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_LIGHTING);
glEnable(GL_FLAT); //Flat shading initially
glShadeModel(GL_FLAT);
//LIGHTING
GLfloat specular[]= {1.0, 1.0, 1.0, 1.0};
GLfloat diffuse[]= {1.0, 1.0, 1.0, 1.0};
GLfloat ambient[]= {1.0, 1.0, 1.0, 1.0};
GLfloat shininess= {100.0};
GLfloat light_ambient[]= {0.0, 0.0, 0.0, 1.0};
GLfloat light_diffuse[]= {1.0, 1.0, 1.0, 1.0};
GLfloat light_specular[]= {1.0, 1.0, 1.0, 1.0};
GLfloat light_position[]= {10.0, 10.0, 10.0, 0.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
// /LIGHTING
glEnable(GL_NORMALIZE);
glClearColor (0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
}
void specialKey(int k, int x, int y) //Camera movement commands with arrow keys
{
switch (k) {
case GLUT_KEY_UP:
xPos += posIncr * cos(theta);
zPos += posIncr * sin(theta);
break;
case GLUT_KEY_DOWN:
xPos -= posIncr * cos(theta);
zPos -= posIncr * sin(theta);
break;
case GLUT_KEY_LEFT:
theta -= thetaIncr;
break;
case GLUT_KEY_RIGHT:
theta += thetaIncr;
break;
case GLUT_KEY_PAGE_UP:
eyeIncline += 0.5;
break;
case GLUT_KEY_PAGE_DOWN:
eyeIncline -= 0.5;
break;
case GLUT_KEY_HOME:
eyeHeight += 0.5;
break;
case GLUT_KEY_END:
eyeHeight -= 0.5;
break;
default:
return;
}
glutPostRedisplay();
}
void key(unsigned char k, int x, int y)
{
if ( k == 27 ) //ESC to close
exit(0);
glutPostRedisplay();
}
void processHits(GLint hits, GLuint buffer[])
{
unsigned int j;
GLuint names, *ptr;
float z1, z2;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
shade = !shade;
setLights();
glutPostRedisplay();
for (int i = 0; i < hits; i++)
{ /* for each hit */
names = *ptr;
printf (" number of names for hit = %d\n", names); ptr++;
z1 = (float) *ptr/0x7fffffff; ptr++;
z2 = (float) *ptr/0x7fffffff; ptr++;
printf(" z1 is %g;",z1);
printf(" z2 is %g\n", z2);
printf (" the name is ");
for (j = 0; j < names; j++) { /* for each name */
printf ("%d ", *ptr); ptr++;
}
printf ("\n");
}
}
void pick( int button, int state, int x, int y )
{
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN) {
return;
}
glSelectBuffer(BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport); //5x5 pixel area around the mouse for selecting
gluPerspective(75, 1.0, 0.1, 100); //NEED
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glInitNames();
glPushName(0);
drawScene();
glPopMatrix();
glFlush();
hits = glRenderMode(GL_RENDER); //# of hits assigned
processHits(hits, selectBuf);
}
void reshape(int w, int h){
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75, w/h,1,150);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow("Room");
init();
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutSpecialFunc(specialKey);
glutReshapeFunc(reshape);
glutMouseFunc(pick);
glutMainLoop();
return 0;
}
原谅我的长度。我正在尝试选择工作,以便我可以一次选择一个对象来做事。根据我的打印输出,除了一个障碍外,它正如我所期望的那样运作:当你选择一个物体时,你最终会放大,基本上在选定的形状内。我已经梳理了我的代码,并进行了一些更改/调试工作,但我无法找到问题。任何人都可以指出我正确的方向,为什么采摘会产生这种奇怪的行为?
答案 0 :(得分:2)
您的函数pick
使用gluperspective
更改投影矩阵(以放大拾取区域),但无法恢复之前的矩阵状态:可以通过包装绘图部分轻松修复它在矩阵glPushMatrix
模式下具有glPopMatrix
和GL_PROJECTION
集合的函数。
void pick( int button, int state, int x, int y )
{
GLuint selectBuf[BUFSIZE];
GLint hits;
GLint viewport[4];
if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN) {
return;
}
glSelectBuffer(BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix(); // save projection settings
glLoadIdentity();
glGetIntegerv(GL_VIEWPORT, viewport);
gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport); //5x5 pixel area around the mouse for selecting
gluPerspective(75, 1.0, 0.1, 100); //NEED
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glInitNames();
glPushName(0);
drawScene();
// restore previous projection settings
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glFlush();