Hi,
I’m working on an application that enables the user to drag a sphere with the mouse. The application has two subwindows, one containing a front view and the other a top view (these divide the main window in half horizontally). The viewing position cannot be changed by the user. The app also includes three cubes that can be selected but which cannot be moved. I’m using OpenGLUT.
I’ve run into several problems:
-
I initially developed the application with only a single window. In this case, the QUAD representing the ground appeared as expected. However, when I split the display into two subwindows the ground QUAD disappeared. The drawing code is definitely being reached however the QUAD is not appearing. Any idea why this is happeing?
-
When the user selects an object with the mouse, all of the objects in the subwindow disappear. However, as soon as the window is resized they appear correctly. Something is obviously going wrong in either the pickObjects or the proces****s functions. The basic approach I’m using here is to detect a hit, and then set a variable in a global array that represents a hit on the object. This array is tested in the display function so that an object that has registered a hit is drawn in red. I’m not sure why the objects in the subwindow are disappearing.
Here’s the code I’m using (which is a combination of the Lighthouse Subwindows tutorial and the Redbook pickdepth example):
#include <GL/openglut.h>
#include <stdlib.h>
#include <stdio.h>
#define BUFSIZE 512
#define ESC 27
#define WINDOW_WIDTH 900
#define WINDOW_HEIGHT 700
#define BORDER 5
float gObjx = 0.0; // X coordinate of dragged object.
float gObjy = 3.0; // Y coordinate of dragged object.
float gObjz; // Z coordinate of dragged object.
float gRedColour[3] = {0.75, 0.0, 0.0};
float gGreenColour[3] = {0.0, 0.75, 0.0};
float gBlueColour[3] = {0.0, 0.0, 0.75};
float gOrangeColour[3] = {0.75f, 0.6f, 0.0f};
double gRatio;
int gHitArray[BUFSIZE] = {0}; // Hit array.
int gMainWindow, gSubWindow1, gSubWindow2;
int h = WINDOW_WIDTH, w = WINDOW_HEIGHT;
//*********************************************************************\\
void init(void)
{
glClearColor(0.5f, 0.5f, 0.5f, 0.0f); // Grey clear colour.
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glShadeModel(GL_FLAT);
gRatio = (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT;
}
//*********************************************************************\\
void drawScene(GLenum mode)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(mode != GL_SELECT) // These objects are not selectable.
{
glColor3fv(gBlueColour); // Ground.
glBegin(GL_QUADS);
glVertex3i(-5, 0, -5);
glVertex3i(5, 0, -5);
glVertex3i(5, 0, 5);
glVertex3i(-5, 0, 5);
glEnd();
}
if(mode == GL_SELECT) // Object 1.
glLoadName(1);
if(gHitArray[0] == TRUE)
glColor3fv(gRedColour);
else
glColor3fv(gGreenColour);
glPushMatrix();
glTranslatef(-3.0, 1.0, 0.0);
glutSolidCube(2.0);
glPopMatrix();
if(mode == GL_SELECT) // Object 2.
glLoadName(2);
if(gHitArray[1] == TRUE)
glColor3fv(gRedColour);
else
glColor3fv(gGreenColour);
glPushMatrix();
glTranslatef(0.0, 1.0, 0.0);
glutSolidCube(2.0);
glPopMatrix();
if(mode == GL_SELECT) // Object 3.
glLoadName(3);
if(gHitArray[2] == TRUE)
glColor3fv(gRedColour);
else
glColor3fv(gGreenColour);
glPushMatrix();
glTranslatef(3.0, 1.0, 0.0);
glutSolidCube(2.0);
glPopMatrix();
if(mode == GL_SELECT) // Object 4.
glLoadName(4);
if(gHitArray[3] == TRUE)
glColor3fv(gRedColour);
else
glColor3fv(gOrangeColour);
glPushMatrix(); // Sphere for drag testing.
glTranslatef(gObjx, gObjy, 0.0f);
glutSolidSphere(0.5, 32, 32);
glPopMatrix();
glutSwapBuffers();
}
//*********************************************************************\\
void processHits(GLint hits, GLuint buffer[])
{
int i;
unsigned j;
GLuint names, *ptr;
printf("hits = %d
", hits);
ptr = (GLuint *) buffer;
for(i = 0; i < hits; i++) // For each hit.
{
names = *ptr;
printf("Number of objects selected: %d
", names);
ptr++;
//printf("z1 is %g
", (float) *ptr/0x7fffffff);
ptr++;
//printf("z2 is %g
", (float) *ptr/0x7fffffff);
ptr++;
printf("The selected object is: ");
for (j = 0; j < names; j++) // For each name.
{
printf("%d ", *ptr);
gHitArray[*ptr - 1] = TRUE; // Set the hit array here.
ptr++;
}
printf("
");
}
}
//*********************************************************************\\
void pickObjects(int button, int state, int x, int y)
{
GLuint selectBuf[BUFSIZE];
GLint hits = 0;
GLint viewport[4];
int i;
if(button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)
{
for(i = 0; i < BUFSIZE; i++)
gHitArray[i] = FALSE;
glutPostRedisplay();
return;
}
glGetIntegerv(GL_VIEWPORT, viewport);
glSelectBuffer(BUFSIZE, selectBuf);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix((GLdouble) x, (GLdouble) ((viewport[3]) - y), 5.0, 5.0, viewport); // Create 5x5 pixel picking region near cursor location.
gluPerspective(45, gRatio, 1.0, 1000);
drawScene(GL_SELECT);
glPopMatrix();
glFlush();
hits = glRenderMode(GL_RENDER);
if(hits)
{
processHits(hits, selectBuf);
glutPostRedisplay();
}
}
//*********************************************************************\\
void moveMouse(int x, int y)
{
if(gHitArray[3] == TRUE)
{
GLint viewport[4];
GLdouble mvmatrix[16], projmatrix[16];
GLint realy; // OpenGL y coordinate position.
GLdouble wx, wy, wz; // returned world x, y, z coords.
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
realy = viewport[3] - (GLint)y - 1; // viewport[3] is height of window in pixels.
printf("Coordinates at cursor are (%4d, %4d)
", x, realy);
gluUnProject((GLdouble) x, (GLdouble) realy, 0.935, mvmatrix, projmatrix, viewport, &wx, &wy, &wz);
printf("World coords at z = 0.5: (%f, %f, %f)
", wx, wy, wz);
gObjx = (GLfloat)wx;
gObjy = (GLfloat)wy;
glutPostRedisplay();
}
}
//*********************************************************************\\
void renderScene(void)
{
glutSetWindow(gMainWindow);
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
}
//*********************************************************************\\
void renderScenesw1(void) // Front view.
{
glutSetWindow(gSubWindow1);
glLoadIdentity();
gluLookAt(0.0, 1.0, 20.0,
0.0, 0.0, -1.0,
0.0, 1.0, 0.0);
drawScene(GL_RENDER);
}
//*********************************************************************\\
void renderScenesw2(void) // Top view.
{
glutSetWindow(gSubWindow2);
glLoadIdentity();
gluLookAt(0.0, 20.0, 0.0,
0.0, -1.0, 0.0,
0.0, 0.0, -1.0);
drawScene(GL_RENDER);
}
//*********************************************************************\\
void renderSceneAll(void)
{
renderScenesw1();
renderScenesw2();
}
//*********************************************************************\\
void changeSize2(int w1, int h1)
{
gRatio = 1.0f * w1 / h1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w1, h1);
gluPerspective(45, gRatio, 1.0, 1000);
glMatrixMode(GL_MODELVIEW);
}
//*********************************************************************\\
void changeSize1(int w1, int h1)
{
if(h1 == 0)
h1 = 1;
w = w1;
h = h1;
glutSetWindow(gSubWindow1);
glutPositionWindow(0, 0);
glutReshapeWindow(w / 2, h);
changeSize2(w / 2, h);
glutSetWindow(gSubWindow2);
glutPositionWindow(0 + (w / 2), 0);
glutReshapeWindow(w / 2, h);
changeSize2(w / 2, h);
}
//*********************************************************************\\
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case ESC:
exit(0);
break;
}
}
//*********************************************************************\\
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutInitWindowPosition(100, 100);
gMainWindow = glutCreateWindow("Test");
init();
glutReshapeFunc(changeSize1);
glutDisplayFunc(renderScene);
glutIdleFunc(renderSceneAll);
glutMouseFunc(pickObjects);
//glutMotionFunc(moveMouse);
glutKeyboardFunc(keyboard);
gSubWindow1 = glutCreateSubWindow(gMainWindow, 0, 0, WINDOW_WIDTH / 2, WINDOW_HEIGHT);
init();
glutDisplayFunc(renderScenesw1);
glutMouseFunc(pickObjects);
//glutMotionFunc(moveMouse);
glutKeyboardFunc(keyboard);
gSubWindow2 = glutCreateSubWindow(gMainWindow, WINDOW_WIDTH / 20, 0, WINDOW_WIDTH / 2, WINDOW_HEIGHT);
init();
glutDisplayFunc(renderScenesw2);
glutMouseFunc(pickObjects);
//glutMotionFunc(moveMouse);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Any help with this would be much appreciated.
Cheers,
Chris