//! GLU Picker /*! * A class to perform picking in a (hopefully) easier manner * Instructions: * * 1) Use glLoadName with a different number when rendering each "pickable" object * * 2) Use picker's PerformPicking() in ProcessEvent method. The returned object will be the closest * * 3) If you want you can look at App.currentlyPicking in your Redraw method * (e.g. to simplify graphics, not draw ignored objects, etc. when in picking mode) * * * Based in a great tutorial by gpWiki: http://gpwiki.org/index.php/OpenGL:Tutorials:Picking * */ /* * Copyright (C) 2010 Alejandro Valenzuela Roca, , http://lj9.mexinetica.com/ * * This file is part of MotorJ, a free framework for videogame development. * * * * MotorJ is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MotorJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with MotorJ. If not, see . */ #include "picker-class.h" extern mjApplication App; mjPicker::mjPicker() { // Init using the default size selBuffer = NULL; SetBufferSize(MJ_SEL_BUFF_SIZE); } mjPicker::mjPicker(GLuint selBufferSize) { selBuffer = NULL; SetBufferSize(selBufferSize); } void mjPicker::SetBufferSize(GLuint selBufferSize) { bufferSize = selBufferSize; if (selBuffer) delete selBuffer; selBuffer = new GLuint[bufferSize]; selRadius = 3.0; App.currentlyPicking = false; glSelectBuffer(bufferSize, selBuffer); } int mjPicker::PerformPicking(GLfloat x, GLfloat y) { int i; int minZ; int selected; GLfloat M[16]; GLint view[4]; App.currentlyPicking = true; glRenderMode(GL_SELECT); glInitNames(); glPushName(99); // Get a default object inside the picking stack glGetFloatv(GL_PROJECTION_MATRIX, M); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Load the identity matrix /* restrict the draw to an area around the cursor */ glGetIntegerv(GL_VIEWPORT, view); gluPickMatrix(x, y, 3.0, 3.0, view); glGetFloatv(GL_PROJECTION_MATRIX, pickingMatrix); // Multiply the picking matrix glMultMatrixf(M); // Multiply the projection matrix glMatrixMode(GL_MODELVIEW); // Return to modelview mode App.currentUniverse->Redraw(); // Draw glMatrixMode(GL_PROJECTION); // Return to projection mode glLoadMatrixf(M); // Restore the original projection matrix selHits = glRenderMode(GL_RENDER); // Get the number of hits glMatrixMode(GL_MODELVIEW); // return to modelview mode App.currentlyPicking = false; //printf("\n\n*************"); if (selHits > 0) { for (i = 0; i < selHits; i++) { if (i == 0) { minZ = selBuffer[i * 4 + 1]; selected = selBuffer[i * 4 + 3]; } else if (selBuffer[i * 4 + 1] < minZ) { minZ = selBuffer[i * 4 + 1]; selected = selBuffer[i * 4 + 3]; } /*printf( "Number: %d\n" "Min Z: %d\n" "Max Z: %d\n" "Name on stack: %d\n", (GLubyte)selBuffer[i * 4], (GLubyte)selBuffer[i * 4 + 1], (GLubyte)selBuffer[i * 4 + 2], (GLubyte)selBuffer[i * 4 + 3] );*/ } //printf("selected: %d\n\n", selected); return selected; } return 0; } mjPicker::~mjPicker() { printf("Calling destructor\n"); delete selBuffer; }