Hi,
I’ve put together some code based on the 3D picking example from http://www.gametutorials.com/Tutorials/opengl/OpenGL_Pg3.htm (some excellent tutorials for OpenGl using .NET). The problem is each time I click an object it seems to think all the objects have been selected. I’ve spent some time going over this and can’t see what I’ve done wrong. Please help! Thanks.
#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
int sphereRed = 101, sphereGreen = 102, sphereBlue = 103, sphereBlack = 104;
int oldX, oldY, width, height, mode, clickReleased = 0;
float rotateSceneX = 0, rotateSceneY = 0, rotateSceneZ = 0, sceneSpinX = 0, sceneSpinY = 0, sceneSpinZ = 0;
float zoom = 1.4f, ratio = 1.5f;
void render() {
width = glutGet(GLUT_WINDOW_WIDTH);
height = glutGet(GLUT_WINDOW_HEIGHT);
glInitNames();
glEnable(GL_COLOR_MATERIAL);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-ratio-zoom, ratio+zoom, -ratio -zoom, ratio+zoom, -10, 25);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
//Main Rotation and Translation
glRotatef(rotateSceneX, 1.0f, 0.0f, 0.0f);
glRotatef(rotateSceneY, 0.0f, 1.0f, 0.0f);
glRotatef(rotateSceneZ, 0.0f, 0.0f, -1.0f);
if (mode == GL_SELECT) {
glPushName(sphereRed);
}
glPushMatrix();
glColor3f(1.0f,0.0f,0.0f);
glutSolidSphere(0.5, 10, 10);
glPopMatrix();
if (mode == GL_SELECT) {
glPopName();
}
if (mode == GL_SELECT) {
glPushName(sphereGreen);
}
glPushMatrix();
glColor3f(0.0f,1.0f,0.0f);
glTranslatef(3.2f, 0.1f, 0.2f);
glutSolidSphere(0.5, 10, 10);
glPopMatrix();
if (mode == GL_SELECT) {
glPopName();
}
if (mode == GL_SELECT) {
glPushName(sphereBlue);
}
glPushMatrix();
glColor3f(0.0f,0.0f,1.0f);
glTranslatef(1.4f, 0.0f, 0.0f);
glutSolidSphere(0.6, 10, 10);
glPopMatrix();
if (mode == GL_SELECT) {
glPopName();
}
if (mode == GL_SELECT) {
glPushName(sphereBlack);
}
glPushMatrix();
glColor3f(0.0f,0.0f,0.0f);
glTranslatef(-1.2f, 0.1f, 0.6f);
glutSolidSphere(0.5, 10, 10);
glPopMatrix();
if (mode == GL_SELECT) {
glPopName();
}
glutSwapBuffers();
}
void Display() {
mode = GL_RENDER;
render();
}
void setLighting() {
float diffuse[] = {0.4, 0.4, 0.4, 1.0};
float specular[] = {0.5, 0.5, 1.5};
float position[] = {0.0, 1.0, 1.0, 0.0};
float lightVal = 1.0;
//light model
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_DEPTH_TEST);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glMaterialf(GL_FRONT, GL_SHININESS, 75);
glMaterialfv(GL_BACK, GL_SPECULAR, specular);
glMaterialf(GL_BACK, GL_SHININESS, 75);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT1, GL_POSITION, position);
//glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lightVal);
}
void InitLight() {
float lightPosition0[] = {1.0f, 1.0f, 0.0f, 0.0f};
float lightPosition1[] = {1.0f, -1.0f, -1.0f, 0.0f};
glLightModeli(GL_LIGHT_MODEL_AMBIENT, GL_TRUE);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0);
glLightfv(GL_LIGHT1, GL_POSITION, lightPosition1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
setLighting();
}
void Keyboard(unsigned char key, int x, int y) {
switch(key) {
case 27: //esc
exit(0);
break;
case 97: //a
zoom+=0.1f;
break;
case 122: //z
zoom-=0.1f;
break;
default:
break;
}
glutPostRedisplay();
}
void Motion(int x, int y) {
if (clickReleased == 0) {
rotateSceneZ = y - oldY;
rotateSceneY = x - oldX;
rotateSceneZ += sceneSpinZ;
rotateSceneY += sceneSpinY;
}
glutPostRedisplay();
}
void Reshape(int width, int height) {
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
}
int retrievePickedObject(int x, int y) {
int objectsFound = 0;
int viewportCoords[4];
int i = 0;
unsigned int selectBuffer[32];
glSelectBuffer(32, selectBuffer);
glGetIntegerv(GL_VIEWPORT, viewportCoords);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glRenderMode(GL_SELECT);
glLoadIdentity();
glInitNames();
gluPickMatrix(x, viewportCoords[3] - y, 2, 2, viewportCoords);
gluOrtho2D(0, width, 0, height);
glOrtho(-ratio-zoom, ratio+zoom, -ratio -zoom, ratio+zoom, -10, 25);
mode = GL_SELECT;
glMatrixMode(GL_MODELVIEW);
render();
objectsFound = glRenderMode(GL_RENDER);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
if (objectsFound > 0) {
unsigned int lowestDepth = selectBuffer[1];
int selectedObject = (int)selectBuffer[3];
for(i = 1; i < objectsFound; i++) {
if(selectBuffer[(i * 4) + 1] < lowestDepth) {
lowestDepth = (unsigned int)selectBuffer[(i * 4) + 1];
selectedObject = (int)selectBuffer[(i * 4) + 3];
}
}
return selectedObject;
}
// We didn't click on any objects so return 0
return 0;
}
void Mouse(int button, int state, int x, int y) {
//find object picked
int obj = 0;
obj = retrievePickedObject(x, y);
//x and y track mouse movement on screen
oldX = x;
oldY = y;
if (state == 1) { //click released
sceneSpinX = rotateSceneX;
sceneSpinY = rotateSceneY;
sceneSpinZ = rotateSceneZ;
if (sceneSpinX >= 360.0f) {
sceneSpinX = 0.0f;
}
if (sceneSpinY >= 360.0f) {
sceneSpinY = 0.0f;
}
if (sceneSpinZ >= 360.0f) {
sceneSpinZ = 0.0f;
}
clickReleased = 1;
}
else {
clickReleased = 0;
}
glutPostRedisplay();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(800, 800);
glutInitWindowPosition(50, 50);
glutCreateWindow("Multiple Viewports");
glutDisplayFunc(Display);
glutKeyboardFunc(Keyboard);
glutMotionFunc(Motion);
glutMouseFunc(Mouse);
glutReshapeFunc(Reshape);
InitLight();
glutMainLoop();
return 0;
}