PDA

View Full Version : Picking problem



steppo
01-10-2010, 03:28 AM
hi, there i'm new to this forum and also to opengl
programming also im very frustrated because i made a loooong thread overlooked it serveral times, want to submit it ,
forget to fill in the subject clicked the back button on
the report form and voila the whole post is gone. so here i go again.

im doin a simple 3d shooter which should be ableto "shoot"
boxes through picking. but this doesnt work. the selection
method does not return any hit here are some snippets. hope
you guys can help. im creating 3 viewports in my window one for the game view one for the game map in the upper right corner and one for the text in the lower right.

this is my display callback function



void display(void) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
createGameViewports(selection);

glLoadIdentity();

glutSwapBuffers();
}





/*
* creates viewports and displays relevant objects in the corresponding viewports
* Three viewports: 1 game view; 2 map view; 3 score/time view.
**/
void createGameViewports(bool selection) {
for (int loop = 0; loop < 3; loop++) {
if (loop == 0) { // This is the game view
glViewport(0, 0, (GLsizei) width - MAP_X, (GLsizei) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, ((GLfloat) width - MAP_X) / (GLfloat) height, 1.0, 1500.0);
}
if (loop == 1) { // This is the map view
glViewport(width - MAP_X, height - MAP_Y, MAP_X, MAP_Y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, (GLfloat) MAP_X / (GLfloat) MAP_Y, 1.0, 1500.0);
}
if (loop == 2) { // This is the score view
glViewport(width - MAP_X, 0, MAP_X, height - MAP_Y);
util.View2D();
}

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_DEPTH_BUFFER_BIT);
if (loop == 0) {

glLoadIdentity();
glEnable(GL_LIGHTING);

showCameraGameView(GL_RENDER);
hField.Render();
environment.displaySky();
glCallList(render);
boxes.displayBoxes(hField, GL_RENDER);
tree.buildTrees(hField);
showLight();

weapon->displayCrosshair();//just a quadric
// fancy animation
if (fired == true) {
weapon.fireWeaponAnimation();
}

}
if (loop == 1) {
show2DMap();
hField.Render();
boxes.displayBoxes(hField, GL_RENDER);
tree.buildTrees(hField);

}
if (loop == 2) {
glLoadIdentity();
glColor3f(1.0f, 1.0f, 0.0f);
util.writeString("Game Information", 160, 250);
myDisplay.writePlayerInfo(player->getName());
myDisplay.writePointInfo(player->getPoints());
myDisplay.writeTimeInfo(player->getTime());
checkGameStatus();
glColor3f(1.0f, 1.0f, 1.0f);
util.View3D();
}
}
}

now this is the selection method wich is invoked via mouse click x and y are the mouse coordinates


void processSelection(int x, int y) {
// Selection stuff
GLuint nameBuffer[500];
GLint hits;
GLint viewport[4];
glSelectBuffer(500, nameBuffer);
// Get the vieport
glGetIntegerv(GL_VIEWPORT, viewport);
// Render in selection mode (this will draw only object which lie in the picked matrix)
glRenderMode(GL_SELECT);
// clearing the names' stack This stack contains all the info about the objects
glInitNames();
//Now fill the stack with one element (or glLoadName will generate an error)
glPushName(0);
//now modify the viewing volume
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();


this is the party im talking about dunno if
im choosing the right pick matrix and the right perspective.
i thought i have to use the perspective im using as the
main game window. but i am not sure about that.


// Pick only a small part around the mouse click
gluPickMatrix(x, ((GLdouble) viewport[3] - y), 50, 50, viewport);

gluPerspective(60, ((GLfloat) width - MAP_X) / (GLfloat) height, 1.0, 1500.0);
//////////////////////////////////////

//draw the objects onto the screen
glMatrixMode(GL_MODELVIEW);

// Draw boxes
boxes.displayBoxes(hField, GL_SELECT);
glMatrixMode(GL_PROJECTION);

glPopMatrix();
hits = glRenderMode(GL_RENDER);

list_hits(hits, nameBuffer);
// Check hit boxes
boxes.checkHitBox(hits, nameBuffer);

if (boxes.getHitBox() != -1) {
char buffer2 [255];
snprintf(buffer2, (size_t) 255, "%d", boxes.getHitBox());
printf("hitbox : %s\n", buffer2);
}
selection = false;
}


this method draws the boxes that should be pickable


/*
* display boxes, currently without selection.
*@param map is needed to figure out how hight the object has to be placed.
**/
void Boxes::displayBoxes(HeightField map, GLenum mode) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, boxTexture);
for (int i = 0; i < NUMBER_OF_BOXES; i++) {

// For selection load the name
if (mode == GL_SELECT) {
glLoadName(i + 1);
}
if (boxStates[i]) {
glPushMatrix();
// Move to the coordinates
glTranslated(boxCoordinates[i][0], (map.getYPos(boxCoordinates[i][0], boxCoordinates[i][1])) + 4.5, boxCoordinates[i][1]);

// Draw the box
displayCubeTextures(&amp;boxTexture);
glPopMatrix();
}
}
glDisable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
}


this checks the hit box


// Method to proof hits

void Boxes::checkHitBox(GLint hits, GLuint* nameBuffer) {
// Returns if the a box was hit and sets it
this->hitBox = this->picker->pick(hits, nameBuffer);
}

and this is the picking method



// This is the picking method which returns the picked object number

GLint Picker::pick(GLint hits, GLuint* nameBuffer) {
// This code was developed with help of the Tuorial of Mr. Dorssers on elo and the
// book OpenGL - A primer by Edward Angel
struct hitRecord *hitRecords = (struct hitRecord*) malloc(sizeof (struct hitRecord) * hits);
GLint* ptr = (GLint *) nameBuffer;
for (int i = 0; i < hits; i++) {
hitRecords[i].names = *ptr;
ptr++;
hitRecords[i].z1 = (GLdouble) * ptr;
ptr++;
hitRecords[i].z2 = (GLdouble) * ptr;
ptr++;
if (hitRecords[i].names >= 1) hitRecords[i].name = *ptr;
for (int j = 0; j < hitRecords[i].names; j++) {
ptr++;
}
}

if (hits != 0) {
GLdouble lowestZValue = (hitRecords[0].z1 + hitRecords[0].z2) / 2;
int nameLowestZValue = hitRecords[0].name;
int i = 1;
while (i < hits) {
GLfloat newZValue = (hitRecords[i].z1 + hitRecords[i].z2) / 2;
if (newZValue < lowestZValue) {
lowestZValue = newZValue;
nameLowestZValue = hitRecords[i].name;
}
i++;
}
return nameLowestZValue - 1;
}
return -1;
}


well i hope u could help me with this. terrain and environment are displayed correctly, but i think am getting something very wrong here with the picking i think =)

thanks in advance

steppo
01-10-2010, 06:49 AM
ok i think i found the problem myself i just used the createViewport() method instead of boxes.drawBoxes()