int OGLWidget::getObjectAtScreenPos(int x, int y) { // set up the selection buffer GLuint buffer[512]; glSelectBuffer(512, buffer); // Get the viewport values GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); // Go into Selection Mode glRenderMode(GL_SELECT); glInitNames(); // Initializes The Name Stack glPushName(-1); // Push at least one entry // go to projection matrix and limit the area around the mouse to be 'drawn' glMatrixMode(GL_PROJECTION); glPushMatrix(); // Push The Projection Matrix glLoadIdentity(); // Resets The Matrix gluPickMatrix((GLdouble) x, (GLdouble) (viewport[3]-y), 1.0f, 1.0f, viewport); // also set the perspective to ensure the new aspect ratio is correct gluPerspective(45.0f, (GLfloat) (viewport[2]-viewport[0])/(GLfloat) (viewport[3]-viewport[1]), 0.1f, 1500.0f); // now paint the objects glMatrixMode(GL_MODELVIEW); parentView_->drawNodes(); // switch everything back glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); // check for hits by switching render mode GLint hits=glRenderMode(GL_RENDER); // do we have any? if (hits > 0) { // note: selection buffer has 4 values per hit: # of hits at time, min depth, max depth, name // start by picking the first hit int choose = buffer[3]; int depth = buffer[1]; // now loop over the rest for (int loop = 1; loop < hits; loop++) { // is this object closer? if (buffer[loop*4+1] < GLuint(depth)) { choose = buffer[loop*4+3]; depth = buffer[loop*4+1]; } } return choose; } return -1; }
static COMMAND_FUNC( do_slct_obj ) { int x, y; const char *s; GLuint n_names, *ptr; GLint hits; GLuint this_hit=0; /* initialize to silence compiler */ GLuint the_hit; float z1,z2; float z_this,z_min; int clickWindowSize = 1; GLint viewport[4]; GLint i; GLuint j; char ret_str[32]; x=(int)HOW_MANY("x location"); y=(int)HOW_MANY("y location"); s=NAMEOF("scene render command"); s=savestr(s); //glPushMatrix(); glSelectBuffer(MAX_SELECT,selectBuf); check_gl_error("glSelectBuffer"); glRenderMode(GL_SELECT); check_gl_error("glRenderMode"); glMatrixMode(GL_PROJECTION); check_gl_error("glMatrixMode"); glPushMatrix(); check_gl_error("glPushMatrix"); glLoadIdentity(); check_gl_error("glLoadIdentity"); glGetIntegerv(GL_VIEWPORT,viewport); check_gl_error("glGetIntegerv"); gluPickMatrix(x,viewport[3]-y, clickWindowSize,clickWindowSize,viewport); check_gl_error("gluPickMatrix"); // Setup camera. //drawer.setupCamera(&manager); //glMatrixMode(GL_MODELVIEW); glInitNames(); check_gl_error("glInitNames"); glPushName(0); check_gl_error("glPushName"); //drawer.drawAirspace(&manager, &table); /* Call the user's draw routine here... */ chew_text(s, "(gl object selection)" ); rls_str(s); // Restoring the original projection matrix. glMatrixMode(GL_PROJECTION); check_gl_error("glMatrixMode GL_PROJECTION"); glPopMatrix(); check_gl_error("glPopMatrix"); glMatrixMode(GL_MODELVIEW); check_gl_error("glMatrixMode GL_MODELVIEW"); glFlush(); check_gl_error("glFlush"); // Returning to normal rendering mode. hits = glRenderMode(GL_RENDER); //printf ("hits = %d\n", hits); // Red book example. // When there are multiple objects, the hits are recorded // in drawing order, we have to check the z values to know // which is the foreground object. z_min=100000; ptr = (GLuint *) selectBuf; for (i = 0; i < hits; i++) { n_names = *ptr++; z1= ((float)*ptr++)/0x7fffffff; z2= ((float)*ptr++)/0x7fffffff; if( z1 < z2 ) z_this = z1; else z_this=z2; if( z_this < z_min ) z_min=z_this; for(j=0;j<n_names;j++){ this_hit=*ptr++; } // sprintf(ERROR_STRING,"Hit %d, %d from %g to %g, last is %d", // i,n_names,z1,z2,this_hit); // advise(ERROR_STRING); } the_hit=0; ptr = (GLuint *) selectBuf; for (i = 0; i < hits; i++) { n_names = *ptr++; z1= ((float)*ptr++)/0x7fffffff; z2= ((float)*ptr++)/0x7fffffff; if( z1 < z2 ) z_this = z1; else z_this=z2; for(j=0;j<n_names;j++){ this_hit=*ptr++; } if( z_this == z_min ) the_hit=this_hit; } //sprintf(ERROR_STRING,"front-most hit is %d",the_hit); //advise(ERROR_STRING); sprintf(ret_str,"%d",the_hit); assign_reserved_var("selection_index",ret_str); //if (hits != 0) { //manager.advanceTrial(processHits()); //} //glPopMatrix(); /* Set a variable to indicate what happened */ }
//================================================================ int GLBT_sel_sel (int *sTyp, long *sDbi, int *stat, int sx, int sy) { //================================================================ // start GL-selection only for selectors. // see GL_sel_rect int hits; long *ia; float fz; GLuint *selectBuf, BUF_SIZ; // printf("GLBT_sel_sel ============================\n"); // switch to ProjectionMode glMatrixMode (GL_PROJECTION); // save active matrix glPushMatrix (); // load Defaultmat. glLoadIdentity (); //---------------------------------------------------------------- // Init Sel. Buffer (BEFORE switching to select) selectBuf = (int*)memspc501; BUF_SIZ = sizeof(memspc501) / sizeof(GLuint); glSelectBuffer (BUF_SIZ, selectBuf); // start select glRenderMode (GL_SELECT); GL_mode_draw_select = GR_MODE_2DSELECT; // Init NameStack. glInitNames(); glPushName((GLuint)0); // Muss sein. Damit ein Name am Stack ist, // define pick-window (rectangle 5x5 pixels) // - changes active (PROJECTION)-matrix ! gluPickMatrix ((double)sx, (double)sy, 5., 5., GL_Viewp); //---------------------------------------------------------------- // redraw all objs to be picked / selectors, buttons // set glOrtho - 2D, GLBT_ori GLBT_view__ (); // fz = GL_Scr_Siz_X * 10.f; // glOrtho (0.f, (float)GL_Scr_Siz_X, 0.f, (float)GL_Scr_Siz_Y, -fz, fz); // UT3D_pt_3db (&GLBT_ori, GL_Scr_Siz_X - GLBT_POS_ORI, GLBT_POS_ORI, 0.); // redraw if(GLBT_vcSelStat >= 0) GLBT_disp_vc (); if(GLBT_plnSelStat >= 0) GLBT_disp_Pln (); if(I2D_iNr > 0) GLBT_but_disp (); // close, fill buffer hits = glRenderMode (GL_RENDER); // printf(" GLBT-hits=%d\n",hits); // restore GL_mode_draw_select = GR_MODE_DRAW; if(hits < 1) { if(hits < 0) TX_Print("ERROR: selectbuffer overflow ..."); goto Fertig; } //---------------------------------------------------------------- // decode hits, add hits into selectionBuffer ia = (long*)MEM_alloc_tmp ((int)(hits * sizeof(long))); GL_sel_hits (ia, selectBuf, hits); // 1-9 are vectors if(ia[0] < 10) { *sTyp = Typ_VC; // test specialVector GLBT_vcSelStat if(ia[0] == 7) *sDbi = GLBT_vcSelStat; else *sDbi = -ia[0]; // stdVector negativ (DB_VCX_IND ..) goto Fertig; } // 11,12,13 = stdPlanes *sTyp = Typ_PLN; *sDbi = 10L - ia[0]; //---------------------------------------------------------------- Fertig: // replace saved matrix glMatrixMode (GL_PROJECTION); glPopMatrix (); // back to normal rendering glMatrixMode (GL_MODELVIEW); return 0; }
void get_3d_object_under_mouse() { //ok, first of all, let's see what objects we have in range... int i, count, x, y, dist1, dist2, hits; GLint viewport[4]; GLuint *buffer, z_coordinate; double matrix[16]; selected_3d_object = -1; x = (int)-camera_x; y = (int)-camera_y; count = 0; for (i = 0; i < MAX_OBJ_3D; i++) { if (objects_list[i] && objects_list[i]->blended != 20) { dist1 = x - (int)objects_list[i]->x_pos; dist2 = y - (int)objects_list[i]->y_pos; if (dist1 * dist1 + dist2 * dist2 <= ((40 * 40) * (zoom_level / 15.75f))) { count++; } } } #ifndef EYE_CANDY if (count == 0) { return; } #endif count++; count *= 4; glGetIntegerv(GL_VIEWPORT, viewport); buffer = malloc(count * sizeof(GLuint)); glSelectBuffer(count, buffer); glGetDoublev(GL_PROJECTION_MATRIX, matrix); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix(mouse_x, window_height-mouse_y, 1.0, 1.0, viewport); glMultMatrixd(matrix); glMatrixMode(GL_MODELVIEW); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glEnable(GL_CULL_FACE); glEnableClientState(GL_VERTEX_ARRAY); glPushMatrix(); glLoadIdentity(); // Reset The Matrix Move(); for (i = 0; i < MAX_OBJ_3D; i++) { if (objects_list[i] && objects_list[i]->blended != 20) { dist1 = x - (int)objects_list[i]->x_pos; dist2 = y - (int)objects_list[i]->y_pos; if (dist1 * dist1 + dist2 * dist2 <= ((40 * 40) * (zoom_level / 15.75f))) { glLoadName(i); draw_3d_object(objects_list[i]); } } } #ifdef EYE_CANDY if (cur_mode == mode_eye_candy) { draw_eye_candy_selectors(); } #endif glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glDisable(GL_CULL_FACE); glDisableClientState(GL_VERTEX_ARRAY); hits = glRenderMode(GL_RENDER); z_coordinate = 0xFFFFFFFF; for (i = 0; i < hits; i++) { if (buffer[(i * 4) + 1] < z_coordinate) { selected_3d_object = buffer[(i*4)+3]; z_coordinate = buffer[(i*4)+1]; } } free(buffer); }
int GLWidget::getObjectID(int x, int y) { // This will hold the amount of objects clicked int objectsFound = 0; // We need an array to hold our view port coordinates int viewportCoords[4] = {0}; // This will hold the ID's of the objects we click on. // We make it an arbitrary number of 32 because openGL also stores other information // that we don't care about. There is about 4 slots of info for every object ID taken up. GLuint selectBuffer[32] = {0}; // glSelectBuffer is what we register our selection buffer with. The first parameter // is the size of our array. The next parameter is the buffer to store the information found. // More information on the information that will be stored in selectBuffer is further below. // Setup our selection buffer to accept object ID's glSelectBuffer(32, selectBuffer); // This function returns information about many things in OpenGL. We pass in GL_VIEWPORT // to get the view port coordinates. It saves it like a RECT with {top, left, bottom, right} // Get the current view port coordinates glGetIntegerv(GL_VIEWPORT, viewportCoords); // Now we want to get out of our GL_MODELVIEW matrix and start effecting our // GL_PROJECTION matrix. This allows us to check our X and Y coords against 3D space. // We now want to effect our projection matrix glMatrixMode(GL_PROJECTION); // We push on a new matrix so we don't effect our 3D projection glPushMatrix(); // This makes it so it doesn't change the frame buffer if we render into it, instead, // a record of the names of primitives that would have been drawn if the render mode was // GL_RENDER are now stored in the selection array (selectBuffer). // Allows us to render the objects without changing framebuffer glRenderMode(GL_SELECT); // Reset our projection matrix glLoadIdentity(); // gluPickMatrix allows us to create a projection matrix that is around our // cursor. This basically only allows rendering in the region that we specify. // If an object is rendered into that region, then it saves that objects ID for us (The magic). // The first 2 parameters are the X and Y position to start from, then the next 2 // are the width and height of the region from the starting point. The last parameter is // of course our view port coordinates. You will notice we subtract "y" from the // BOTTOM view port coordinate. We do this to flip the Y coordinates around. The 0 y // coordinate starts from the bottom, which is opposite to window's coordinates. // We also give a 2 by 2 region to look for an object in. This can be changed to preference. gluPickMatrix(x, viewportCoords[3] - y, 2, 2, viewportCoords); // Next, we just call our normal gluPerspective() function, exactly as we did on startup. // This is to multiply the perspective matrix by the pick matrix we created up above. //Perspective view or Orthogonal View. Multiply by current projection matrix if(m_bPerspective) { GLfloat fov = 60.0f; gluPerspective(fov, (GLdouble)width()/height(), 1, 3000); } else glOrtho(-1.0, +1.0, -1.0, 1.0, -1.0, 1.0); // Go back into our model view matrix glMatrixMode(GL_MODELVIEW); m_cylinder.drawCurveControlPoints(true); // If we return to our normal render mode from select mode, glRenderMode returns // the number of objects that were found in our specified region (specified in gluPickMatrix()) // Return to render mode and get the number of objects found objectsFound = glRenderMode(GL_RENDER); // Put our projection matrix back to normal. glMatrixMode(GL_PROJECTION); // Stop effecting our projection matrix glPopMatrix(); // Go back to our normal model view matrix glMatrixMode(GL_MODELVIEW); if (objectsFound > 0) { // 1 is the first object's minimum Z value. // We use an unsigned int so we don't get a warning with selectBuffer below. unsigned int lowestDepth = selectBuffer[1]; // Set the selected object to the first object to start it off. // 3 is the first object's object ID we passed into glLoadName(). int selectedObject = selectBuffer[3]; // Go through all of the objects found, but start at the second one for(int i = 1; i < objectsFound; i++) { // Check if the current objects depth is lower than the current lowest // Notice we times i by 4 (4 values for each object) and add 1 for the depth. if(selectBuffer[(i * 4) + 1] < lowestDepth) { // Set the current lowest depth lowestDepth = selectBuffer[(i * 4) + 1]; // Set the current object ID selectedObject = selectBuffer[(i * 4) + 3]; } } // Return the selected object return selectedObject; } // We didn't click on any objects so return nothing return -1; }
void PerspectiveGLWidget::rectangularSelection (int preX, int preY, int curX, int curY, QList<Model *> &selectedModels, QList<Vector *> &selectedVertices) { GLuint selectBuffer[1024]; glSelectBuffer(1024, selectBuffer); glRenderMode(GL_SELECT); glClear(GL_DEPTH_BUFFER_BIT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float xCenter = (preX + curX) / 2; float yCenter = (preY + curY) / 2; float widthOfSelection = fabs(preX - curX); if(widthOfSelection < 5) widthOfSelection = 5; float heightOfSelection = fabs(preY - curY); if(heightOfSelection < 5) heightOfSelection = 5; int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); gluPickMatrix(xCenter, viewport[3] - yCenter, widthOfSelection, heightOfSelection, viewport); gluPerspective(45, aspectRatio, 1.0, 1000); int i = 0; while(i != ModelManager::getInstance ()->size ()) { if(ModelManager::getInstance ()->at (i)->getDrawingMode () == ObjectMode) { glLoadName(i + 1); Model *s = ModelManager::getInstance ()->at(i); ModelManager::getInstance ()->at(i)->setSelectionIdentifier(i + 1); s->drawObjectModeSelect(); i++; } else if(ModelManager::getInstance ()->at (i)->getDrawingMode () == VertexMode) { int t = 0; int j = 0; while(j != ModelManager::getInstance ()->size()) { int vertexCount = ModelManager::getInstance ()->at(j)->getVertexManager()->size(); for(int k = 0; k < vertexCount; k++) { glLoadName(t + 1); ModelManager::getInstance ()->at(j)->getVertexManager()->at(k)->setSelectionIdentifier(t + 1); ModelManager::getInstance ()->at(j)->drawVertexModeSelect(k); t++; } j++; } } } GLint hits = glRenderMode(GL_RENDER); GLuint names, *ptr; ptr = (GLuint *)selectBuffer; GLuint selectedObject = 0; for (int i = 0; i < hits; i++) { names = *ptr++; ptr++; ptr++; while(names--) { selectedObject = *ptr; for(int k = 0 ; k < ModelManager::getInstance ()->size() ; k++) { if(ModelManager::getInstance ()->at (k)->getDrawingMode () == ObjectMode) { GLuint modelID = ModelManager::getInstance ()->at(k)->getSelectionIdentifier(); if(modelID == selectedObject) { selectedModels.append (ModelManager::getInstance ()->at(k)); } } else if(ModelManager::getInstance ()->at (k)->getDrawingMode () == VertexMode) { int j = 0; while(j != ModelManager::getInstance ()->size()) { int vertexCount = ModelManager::getInstance ()->at(j)->getVertexManager()->size(); for(int k = 0; k < vertexCount; k++) { if(selectedObject == (GLuint)ModelManager::getInstance ()->at(j)->getVertexManager()->at(k)->getID()) { selectedVertices.append (ModelManager::getInstance ()->at(j)->getVertexManager()->at(k)); } } j++; } } ptr++; } } } }
unsigned int C3dView::EndSelect ( void ) { if (!m_bDrawing) return 0xffffffff; GLint hits = 0; long iTopName = -1; float LastZ = 0.0f; bool bFirstShot = true; long i; unsigned int j; GLuint names = 0, *ptr = NULL; float z1 = 0,z2 = 0; long iName = 0; glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glFlush(); // end render hits = glRenderMode(GL_RENDER); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (m_fov,m_fAspect,m_xNearZ,m_xFarZ); glViewport (0, 0, m_iViewportX, m_iViewportY); glMatrixMode(GL_MODELVIEW); glLoadIdentity (); char msg[255]; if (hits >0) { ptr = (GLuint *) m_uiSelectBuf; for (i = 0; i < hits; i++) { /* for each hit */ names = *ptr; ptr++; z1 = (float) *ptr/0x7fffffff; ptr++; z2 = (float) *ptr/0x7fffffff; ptr++; // stupid compiler bug sprintf(msg,"names %u f1 %f f2 %f",(unsigned int)names,z1,z2); if (bFirstShot) { LastZ = z1; bFirstShot = false; } for (j = 0; j < names; j++) { /* for each name */ iName = *ptr; ptr++; } if (z1 <= LastZ) { LastZ = z1; iTopName = iName; } } } m_bDrawing = false; m_bOverlayMode = false; m_bForcedDrawing = false; if (iTopName == -1) return 0; else return iTopName; }
static Icon *_cairo_dock_pick_icon_on_opengl_desklet (CairoDesklet *pDesklet) { GLuint selectBuf[4]; GLint hits=0; GLint viewport[4]; if (! gldi_gl_container_make_current (CAIRO_CONTAINER (pDesklet))) return NULL; glGetIntegerv (GL_VIEWPORT, viewport); glSelectBuffer (4, selectBuf); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity (); gluPickMatrix ((GLdouble) pDesklet->container.iMouseX, (GLdouble) (viewport[3] - pDesklet->container.iMouseY), 2.0, 2.0, viewport); gluPerspective (60.0, 1.0*(GLfloat)pDesklet->container.iWidth/(GLfloat)pDesklet->container.iHeight, 1., 4*pDesklet->container.iHeight); glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); _set_desklet_matrix (pDesklet); if (pDesklet->iLeftSurfaceOffset != 0 || pDesklet->iTopSurfaceOffset != 0 || pDesklet->iRightSurfaceOffset != 0 || pDesklet->iBottomSurfaceOffset != 0) { glTranslatef ((pDesklet->iLeftSurfaceOffset - pDesklet->iRightSurfaceOffset)/2, (pDesklet->iBottomSurfaceOffset - pDesklet->iTopSurfaceOffset)/2, 0.); glScalef (1. - (double)(pDesklet->iLeftSurfaceOffset + pDesklet->iRightSurfaceOffset) / pDesklet->container.iWidth, 1. - (double)(pDesklet->iTopSurfaceOffset + pDesklet->iBottomSurfaceOffset) / pDesklet->container.iHeight, 1.); } glPolygonMode (GL_FRONT, GL_FILL); glColor4f (1., 1., 1., 1.); pDesklet->iPickedObject = 0; if (pDesklet->render_bounding_box != NULL) // surclasse la fonction du moteur de rendu. { pDesklet->render_bounding_box (pDesklet); } else if (pDesklet->pRenderer && pDesklet->pRenderer->render_bounding_box != NULL) { pDesklet->pRenderer->render_bounding_box (pDesklet); } else // on le fait nous-memes a partir des coordonnees des icones. { glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, 0.); double x, y, w, h; Icon *pIcon; pIcon = pDesklet->pIcon; if (pIcon != NULL && pIcon->image.iTexture != 0) { w = pIcon->fWidth/2; h = pIcon->fHeight/2; x = pIcon->fDrawX + w; y = pDesklet->container.iHeight - pIcon->fDrawY - h; glLoadName(pIcon->image.iTexture); glBegin(GL_QUADS); glVertex3f(x-w, y+h, 0.); glVertex3f(x+w, y+h, 0.); glVertex3f(x+w, y-h, 0.); glVertex3f(x-w, y-h, 0.); glEnd(); } GList *ic; for (ic = pDesklet->icons; ic != NULL; ic = ic->next) { pIcon = ic->data; if (pIcon->image.iTexture == 0) continue; w = pIcon->fWidth/2; h = pIcon->fHeight/2; x = pIcon->fDrawX + w; y = pDesklet->container.iHeight - pIcon->fDrawY - h; glLoadName(pIcon->image.iTexture); glBegin(GL_QUADS); glVertex3f(x-w, y+h, 0.); glVertex3f(x+w, y+h, 0.); glVertex3f(x+w, y-h, 0.); glVertex3f(x-w, y-h, 0.); glEnd(); } } glPopName(); hits = glRenderMode (GL_RENDER); glMatrixMode (GL_PROJECTION); glPopMatrix (); glMatrixMode(GL_MODELVIEW); glPopMatrix (); Icon *pFoundIcon = NULL; if (hits != 0) { GLuint id = selectBuf[3]; Icon *pIcon; if (pDesklet->render_bounding_box != NULL) { pDesklet->iPickedObject = id; //g_print ("iPickedObject <- %d\n", id); pFoundIcon = pDesklet->pIcon; // il faut mettre qqch, sinon la notification est filtree par la macro CD_APPLET_ON_CLICK_BEGIN. } else { pIcon = pDesklet->pIcon; if (pIcon != NULL && pIcon->image.iTexture != 0) { if (pIcon->image.iTexture == id) { pFoundIcon = pIcon; } } if (pFoundIcon == NULL) { GList *ic; for (ic = pDesklet->icons; ic != NULL; ic = ic->next) { pIcon = ic->data; if (pIcon->image.iTexture == id) { pFoundIcon = pIcon; break ; } } } } } return pFoundIcon; }
void GLwidget::mousePressEvent(QMouseEvent *ev) { float posX = ev->x(); float posy = ev->y(); GLuint buff[64] = {0}; GLint hits, view[4]; /* This choose the buffer where store the values for the selection data */ glSelectBuffer(64, buff); /* This retrieve info about the viewport */ glGetIntegerv(GL_VIEWPORT, view); /* Switching in selecton mode */ glRenderMode(GL_SELECT); /* Clearing the name's 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 vieving volume, restricting selection area around the cursor */ glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); /* restrict the draw to an area around the cursor */ gluPickMatrix(posX, posy, 1.0, 1.0, view); gluPerspective(60.0, this->width()/this->height(), 0.0001, 1000.0); /* Draw the objects onto the screen */ glMatrixMode(GL_MODELVIEW); /* draw only the names in the stack, and fill the array */ //glutSwapBuffers(); swapBuffers(); //gl_draw(); paintGL(); /* Do you remeber? We do pushMatrix in PROJECTION mode */ glMatrixMode(GL_PROJECTION); glPopMatrix(); /* get number of objects drawed in that area and return to render mode */ hits = glRenderMode(GL_RENDER); qDebug() << hits; /* Print a list of the objects */ list_hits(hits, buff); /* uncomment this to show the whole buffer * / gl_selall(hits, buff); */ glMatrixMode(GL_MODELVIEW); }
static void glgdGraphComputeHoverData(glgdGraph *graph, GLdouble mx, GLdouble my) { int i, j; GLint nameCount; GLint hitCount; GLuint selectBuf[64]; GLuint *ptr; if (graph->nodeHead) { glSelectBuffer(64, selectBuf); glRenderMode(GL_SELECT); glInitNames(); glgdGraphPushAttributes(); glgdCamBeginPick(&graph->ctrlCam, mx, my); glgdGraphRender(graph, GL_SELECT); glgdCamEnd(&graph->ctrlCam); glgdGraphPopAttributes(); glFlush(); hitCount = glRenderMode(GL_RENDER); if (hitCount > 0) { ptr = &selectBuf[0]; for (i=0; i<hitCount; i++) { nameCount = *ptr; ptr++; glgdTrace(3, "%3d: nameCount: %d\n", i, nameCount); glgdTrace(3, " zMin: %g\n", (GLdouble)*ptr/0x7fffffff); ptr++; glgdTrace(3, " zMax: %g\n", (GLdouble)*ptr/0x7fffffff); ptr++; if (*ptr == GLGDGRAPH_NODENAME) { graph->hoverNode = glgdNodeByID(graph->nodeHead, ptr[1]); graph->hoverLink = NULL; } else if (*ptr == GLGDGRAPH_LINKNAME) { graph->hoverLink = glgdGraphLinkByNdx(graph, ptr[1]); if (nameCount > 2) { graph->hoverNode = glgdNodeByID(graph->nodeHead, ptr[2]); } } if (s_verbosity >= 3) { for (j=0; j<nameCount; j++) { glgdTrace(3, " name[%1d]: %d\n", j, ptr[j]); } } ptr += nameCount; } } else { graph->hoverNode = NULL; graph->hoverLink = NULL; } } }
/* picking */ int pick(int x, int y) { GLuint hits = 0; GLint viewport[4]; GLuint selectBuf[512]; GLuint *ptr; GLuint i,j; GLint k; GLint picked = -1; real mv_matrix[16]; GLuint names, z1, z2, zmax; glMatrixMode(GL_MODELVIEW); glGetDoublev( GL_MODELVIEW_MATRIX, mv_matrix); glGetIntegerv( GL_VIEWPORT, viewport); glSelectBuffer(sizeof(selectBuf)/sizeof(selectBuf[0]), selectBuf); glRenderMode(GL_SELECT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix( (GLdouble) x, (GLdouble) (viewport[3] - y), 2.0,2.0, viewport); glOrtho(ViewCenter[0]-ViewSize,ViewCenter[0]+ViewSize, ViewCenter[1]-ViewSize,ViewCenter[1]+ViewSize, -3*ViewDepth*ViewSize, 3*ViewDepth*ViewSize); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadMatrixd(mv_matrix); glTranslated(-ObjectCenter[0], -ObjectCenter[1], -ObjectCenter[2]); glInitNames(); glPushName((unsigned) -1); for (k= 1; k <=patch_num ; k++) { glLoadName(k); // glCallList(patchList(k)); } glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); hits = glRenderMode(GL_RENDER); //printf("hits %d \n", hits); ptr = selectBuf; for (i = 0; i < hits; i++) { /* for each hit */ names = *ptr; if(names !=1 ){ //printf("something wrong?\n"); break; // wierd case, openGL bug? } ptr++; z1 = *ptr; ptr++; z2 = *ptr; ptr++; // printf("names %d \n", names); if( i ==0 || z2 > zmax ) { //printf("z: %ud \n", z2); zmax = z2; for (j = 0; j < names; j++) { /* for each name */ if ( (*ptr <= (GLuint) patch_num) && (*ptr >= 1) ) { picked = *ptr; // return picked; } ptr++; } } } return picked; }
// `使用OpenGL來繪圖` void RenderFrameOpenGL(void) { // `取得視窗大小` int w, h; GutGetWindowSize(w, h); // `清除畫面` glClearColor(0.4f, 0.4f, 0.4f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // `在螢幕上畫出行星運動` RenderSolarSystemOpenGL(false); /* `啟動Selection Buffer, 硬體會試著去重畫一次3D物件,` `但不會更新畫面, 只會記錄下落在畫面中某個范圍內所有3D物件.` */ int x,y,buttons[3]; GutGetMouseState(x, y, buttons); if ( buttons[0] ) { GLint viewport[4]; glSelectBuffer(BUFSIZE,selectBuf); glRenderMode(GL_SELECT); glInitNames(); glGetIntegerv(GL_VIEWPORT,viewport); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); // `設定Selection Buffer的檢查范圍` gluPickMatrix(x, viewport[3]-y, 3, 3, viewport); float fRatio = (viewport[2]+0.0) / viewport[3]; glMultMatrixf( (float *)&g_projection_matrix ); // `在Selection Buffer中畫出3D物件` RenderSolarSystemOpenGL(true); int hits = glRenderMode(GL_RENDER); GLuint *ptr = selectBuf; GLuint Zmin = 0xffffffff; GLuint SelectedObject = 0; // `找出檢查范圍中, 距離鏡頭最近的物體.` for ( int i=0; i<hits; i++, ptr+=4 ) { if ( ptr[1] < Zmin ) { Zmin = ptr[1]; SelectedObject = ptr[3]; } } switch(SelectedObject) { default: case 0: printf("Nothing\r"); break; case 1: printf("Sun \r"); break; case 2: printf("Earth \r"); break; } glMatrixMode(GL_PROJECTION); glPopMatrix(); } // `把背景backbuffer的畫面呈現出來` GutSwapBuffersOpenGL(); }
void MakeSelection(int nChoice) { // Space for the feedback buffer GLfloat feedBackBuff[FEED_BUFF_SIZE]; // Storeage for counters, etc. int size,i,j,count; // Initial minimum and maximum values bRect.right = bRect.bottom = -999999.0f; bRect.left = bRect.top = 999999.0f; // Set the feedback buffer glFeedbackBuffer(FEED_BUFF_SIZE,GL_2D, feedBackBuff); // Enter feedback mode glRenderMode(GL_FEEDBACK); // Redraw the scene DrawObjects(); // Leave feedback mode size = glRenderMode(GL_RENDER); // Parse the feedback buffer and get the // min and max X and Y window coordinates i = 0; while(i < size) { // Search for appropriate token if(feedBackBuff[i] == GL_PASS_THROUGH_TOKEN) if(feedBackBuff[i+1] == (GLfloat)nChoice) { i+= 2; // Loop until next token is reached while(i < size && feedBackBuff[i] != GL_PASS_THROUGH_TOKEN) { // Just get the polygons if(feedBackBuff[i] == GL_POLYGON_TOKEN) { // Get all the values for this polygon count = (int)feedBackBuff[++i]; // How many vertices i++; for(j = 0; j < count; j++) // Loop for each vertex { // Min and Max X if(feedBackBuff[i] > bRect.right) bRect.right = feedBackBuff[i]; if(feedBackBuff[i] < bRect.left) bRect.left = feedBackBuff[i]; i++; // Min and Max Y if(feedBackBuff[i] > bRect.bottom) bRect.bottom = feedBackBuff[i]; if(feedBackBuff[i] < bRect.top) bRect.top = feedBackBuff[i]; i++; } } else i++; // Get next index and keep looking } break; } i++; } }
guint Render::find_object_at(gdouble x, gdouble y) { // Render everything in selection mode GdkGLContext *glcontext = gtk_widget_get_gl_context (get_widget()); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (get_widget()); const GLsizei BUFSIZE = 256; GLuint select_buffer[BUFSIZE]; if (!gldrawable || !gdk_gl_drawable_gl_begin (gldrawable, glcontext)) return 0; glSelectBuffer(BUFSIZE, select_buffer); (void)glRenderMode(GL_SELECT); GLint viewport[4]; glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity (); glGetIntegerv(GL_VIEWPORT,viewport); gluPickMatrix(x,viewport[3]-y,2,2,viewport); // 2x2 pixels around the cursor gluPerspective (45.0f, (float)get_width()/(float)get_height(),1.0f, 1000000.0f); glMatrixMode (GL_MODELVIEW); glInitNames(); glPushName(0); glLoadIdentity (); glTranslatef (0.0, 0.0, -2.0 * m_zoom); glMultMatrixf (m_transform.M); CenterView(); glPushMatrix(); glColor3f(0.75f,0.75f,1.0f); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); Gtk::TreeModel::iterator no_object; m_view->Draw (no_object); // restor projection and model matrices glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); // restore rendering mode GLint hits = glRenderMode(GL_RENDER); if (gdk_gl_drawable_is_double_buffered(gldrawable)) gdk_gl_drawable_swap_buffers (gldrawable); else glFlush(); gdk_gl_drawable_gl_end (gldrawable); // Process the selection hits GLuint *ptr = select_buffer; GLuint name = 0; GLuint minZ = G_MAXUINT; for (GLint i = 0; i < hits; i++) { /* for each hit */ GLuint n = *ptr++; // number of hits in this record GLuint z1 = *ptr++; // Minimum Z in the hit record ptr++; // Skip Maximum Z coord if (n > 0 && z1 < minZ) { // Found an object further forward. name = *ptr; minZ = z1; } ptr += n; // Skip n name records; } return name; }
bool Viewer::on_button_press_event(GdkEventButton* event) { DEBUG_MSG( "Stub: Button " << event->button << " pressed" ); m_lastMouse = Point2D(event->x, event->y); // pick here if (m_mode == JOINTS && event->button == 1) { GLuint buffer[512]; GLint viewport[4]; glSelectBuffer (512, buffer); // don't actually draw glRenderMode(GL_SELECT); glInitNames(); //init the name buffer GLint hits; glMatrixMode(GL_PROJECTION); glLoadIdentity(); //glViewport(0, 0, get_width(), get_height glGetIntegerv(GL_VIEWPORT, viewport); for (int i = 0; i < 4; i++) { DEBUG_MSG("Viewport[i]: " << viewport[i]); } gluPickMatrix(event->x, viewport[3] - event->y, 1, 1, viewport); gluPerspective(40.0, (GLfloat)get_width()/(GLfloat)get_height(), 0.1, 1000.0); // change to model view for drawing glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); //Matrix4x4 daT = translation(Vector3D(5.0, 0.0, 0.0)); //glMultMatrixd(daT.transpose().begin()); // gl use column order matrix, m4x4 is row order Matrix4x4 trackballM = m_trackballTranslation * m_trackballRotation; glMultMatrixd(trackballM.transpose().begin()); // draw model m_root->walk_gl(true); glPopMatrix(); hits = glRenderMode(GL_RENDER); DEBUG_MSG("picked: " << hits << "=========================="); //parse the hits int c = 0; // buffer counter for (int h = 0; h < hits; h++) { int qStack = buffer[c++]; int minZ = buffer[c++]; int maxZ = buffer[c++]; DEBUG_MSG("HIT(" << h << ")" << qStack << " (" << minZ << "," << maxZ << ")"); for (int q = 0; q < qStack; q++) { int id = buffer[c++]; DEBUG_MSG("\tname " << id); SceneNode *selNode = m_root->find(id); if (selNode == NULL) { *(int*)0=0; DEBUG_MSG("IMPOSSIBLE"); exit(-1); } // check if selNode is selectable (has a joint parent) if (selNode->jointParent()) { bool selected = selNode->toggleSelected(); if (selected) { m_selected.push_back(selNode); } else { m_selected.remove(selNode); } } } } // select the primitives if they have joint owners // when dragging, move the joints of the parents // able to get GemeotryNode from id // tree or global arraylist // get parent from child } invalidate(); return true; }
void GLWidget::processFindingObject(double p_xPos, double p_yPos) { int view[4]; uint selectionBuffer[32] = {0}; int numberOfSelectedObjects = 0; // For selected objects glSelectBuffer(32, selectionBuffer); glGetIntegerv(GL_VIEWPORT, view); glRenderMode(GL_SELECT); // Clearing object names for identifying objects glInitNames(); glPushName(0); // Backup projection matrix in order restore it after view restriction around cursor area glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); // Restrict the draw to an area around the cursor gluPickMatrix(p_xPos, p_yPos, 10.0, 10.0, view); gluPerspective(30.0, 1.0, 1.0, 10000.0); // Redraw with restricted view area glMatrixMode(GL_MODELVIEW); m_mapRenderer.setSelectionMode(); m_mapRenderer.render(this); // Restore projection matrix glMatrixMode(GL_PROJECTION); glPopMatrix(); numberOfSelectedObjects = glRenderMode(GL_RENDER); glMatrixMode(GL_MODELVIEW); std::vector<int> selectedObjects; if(numberOfSelectedObjects > 0) { Hit* pHitArray = reinterpret_cast<Hit*>(selectionBuffer); for(int i = 0; i < numberOfSelectedObjects; i++) { if(m_mapRenderer.getTurnMapId() == pHitArray[i].id && m_moveMap) { m_turnMap = true; return; } selectedObjects.push_back(pHitArray[i].id); } } else { selectedObjects.push_back(0); } if(m_moveMap) { return; } m_mapRenderer.selectObjects(selectedObjects); updateGL(); int selectionNumber = selectedObjects.front(); if(0 != selectionNumber && m_mapRenderer.getTurnMapId() != selectionNumber) { showPlaceDetailsWidget(selectionNumber); } }
void PerspectiveGLWidget::pointSelection (int x, int y, QList<Model *> &selectedModels, QList<Vector *> &selectedVertices) { GLuint selectBuffer[1024]; glSelectBuffer(1024, selectBuffer); glRenderMode(GL_SELECT); glClear(GL_DEPTH_BUFFER_BIT); glInitNames(); glPushName(0); glMatrixMode (GL_PROJECTION); glLoadIdentity (); int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); gluPickMatrix(x, viewport[3] - y, 10.0, 10.0, viewport); gluPerspective(45, aspectRatio, 1.0, 1000); int i = 0; while(i != ModelManager::getInstance ()->size ()) { if(ModelManager::getInstance ()->at (i)->getDrawingMode () == ObjectMode) { glLoadName(i + 1); Model *s = ModelManager::getInstance ()->at(i); ModelManager::getInstance ()->at(i)->setSelectionIdentifier(i + 1); s->drawObjectModeSelect(); i++; } else if(ModelManager::getInstance ()->at (i)->getDrawingMode () == VertexMode) { int i = 0; int j = 0; while(j != ModelManager::getInstance ()->size()) { int vertexCount = ModelManager::getInstance ()->at(j)->getVertexManager()->size(); for(int k = 0; k < vertexCount; k++) { glLoadName(i + 1); ModelManager::getInstance ()->at(j)->getVertexManager()->at(k)->setSelectionIdentifier(i + 1); ModelManager::getInstance ()->at(j)->drawVertexModeSelect(k); i++; } j++; } } } GLint hits = glRenderMode(GL_RENDER); GLuint names, *ptr; ptr = (GLuint *)selectBuffer; GLuint selectedObject = 0; for (int i = 0; i < hits; i++) { names = *ptr++; ptr++; ptr++; while(names--) { selectedObject = *ptr; ptr++; } } for(int k = 0 ; k < ModelManager::getInstance ()->size() ; k++) { if(ModelManager::getInstance ()->at (k)->getDrawingMode () == ObjectMode) { GLuint modelID = ModelManager::getInstance ()->at(k)->getSelectionIdentifier(); if(modelID == selectedObject) { selectedModels.append (ModelManager::getInstance ()->at(k)); } } else if(ModelManager::getInstance ()->at (i)->getDrawingMode () == VertexMode) { int j = 0; while(j != ModelManager::getInstance ()->size()) { int vertexCount = ModelManager::getInstance ()->at(j)->getVertexManager()->size(); for(int k = 0; k < vertexCount; k++) { if(selectedObject == (GLuint)ModelManager::getInstance ()->at(j)->getVertexManager()->at(k)->getID()) { selectedVertices.append (ModelManager::getInstance ()->at(j)->getVertexManager()->at(k)); } } j++; } } } }
// Select void bwindow_pick(BWindow self){ static GLuint selectionBuffer[256]; GLuint *ptr, *selection, num_obj, z1,z2,z; GLint hits; int num, i,j; raster_hit =0; current_window = self; draw_status = SELECT; self->event.pos.y = self->height - self->event.pos.y; self->event.dpos.y *=-1; pick_dx = self->event.pos.x - pick_x; pick_dy = self->event.pos.y - pick_y; pick_x = self->event.pos.x; pick_y = self->event.pos.y; // initialize selection buffer glSelectBuffer(256,selectionBuffer); //-------------------------------------------------------------------------------------------- glViewport(0,0,self->width,self->height); current_viewport[0] = 0; current_viewport[1] = 0; current_viewport[2] = self->width; current_viewport[3] = self->height; //-------------------------------------------------------------------------------------------- /* * Hit stack looks like this: * * num_obj (GLuint)- number of objects on stack * z1 (GLuint) - value of closest point in hit * z2 (GLuint) - value of farthest point in hit * first object in hit - this is the id (or in this case pointer) of the first object in hit * . * . * n object in hit - this is the id (or in this case pointer) of the n object in hit */ ptr = selectionBuffer; num_obj = z1 = z2 = z=0; selection=NULL; glRenderMode(GL_SELECT); glInitNames(); // iterate window's items and draw them im_draw( self->items); hits = glRenderMode(GL_RENDER); //number of hit stacks if (hits){ // initialize values for first hit num_obj = num = *ptr++; // number of objects in stack z = z1 = *ptr++; // min depth of hit z2 = *ptr++; // max depth of hit selection = ptr; // selection remembers closest hit // if there is more than one hit selection will be the one with the nearest point for (i = 1; i<hits ; i++){ ptr+=num; // increment ahead to next hit num = *ptr++; z1 = *ptr++; z2 = *ptr++; if (z1 < z){ selection = ptr; z = z1; num_obj=num; } } // num is the number of hits in this stack // j = 0 is the view Layer lay = NULL; Link child = NULL; Binding binding = NULL; view_transform(current_view); for (j = 0 ; j< num_obj ; j++){ child=(Link) index_get(bound_layers, *selection++); lay = child->value.vptr; layer_transform(child->value.vptr); binding = lay->bindings; while(binding){ if( ((binding->event.state & current_window->event.state) == binding->event.state) && (binding->event.key == current_window->event.key)) { callback(child,binding->callback); } binding = binding->next; } } } if (self->update) bwindow_paint(self); }
/* Mouse hit detection */ static void find_mouse_gear (ModeInfo *mi) { pinion_configuration *pp = &pps[MI_SCREEN(mi)]; int screen_width = MI_WIDTH (mi); int screen_height = MI_HEIGHT (mi); GLfloat h = (GLfloat) screen_height / (GLfloat) screen_width; int x, y; int hits; pp->mouse_gear_id = 0; /* Poll mouse position */ { Window r, c; int rx, ry; unsigned int m; XQueryPointer (MI_DISPLAY (mi), MI_WINDOW (mi), &r, &c, &rx, &ry, &x, &y, &m); } if (x < 0 || y < 0 || x > screen_width || y > screen_height) return; /* out of window */ /* Run OpenGL hit detector */ { GLint vp[4]; GLuint selbuf[512]; glSelectBuffer (sizeof(selbuf), selbuf); /* set up "select" mode */ glRenderMode (GL_SELECT); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glGetIntegerv (GL_VIEWPORT, vp); /* save old vp */ gluPickMatrix (x, vp[3]-y, 5, 5, vp); gluPerspective (30.0, 1/h, 1.0, 100.0); /* must match reshape_pinion() */ glMatrixMode (GL_MODELVIEW); draw_gears (mi); /* render into "select" buffer */ glMatrixMode (GL_PROJECTION); /* restore old vp */ glPopMatrix (); glMatrixMode (GL_MODELVIEW); glFlush(); hits = glRenderMode (GL_RENDER); /* done selecting */ if (hits > 0) { int i; GLuint name_count = 0; GLuint *p = (GLuint *) selbuf; GLuint *pnames = 0; GLuint min_z = ~0; for (i = 0; i < hits; i++) { int names = *p++; if (*p < min_z) /* find match closest to screen */ { name_count = names; min_z = *p; pnames = p+2; } p += names+2; } if (name_count > 0) /* take first hit */ pp->mouse_gear_id = pnames[0]; } } }
gint buttonpress(GtkWidget *glarea, GdkEventButton *event) { int x = (int) event->x; int y = (int) event->y; GLuint *buffer; GLint hits; GLint viewport[4]; switch(event->button) { case 1: // button 1, do picking glGetIntegerv(GL_VIEWPORT, viewport); buffer = new GLuint[doc->world.list.size() * 4]; glSelectBuffer(doc->world.list.size() * 4, buffer); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix((double) x, (double) (viewport[3] - y), 1.0, 1.0, viewport); gluPerspective(45.0, (float) (viewport[2] - viewport[0]) / (float) (viewport[3] - viewport[1]), 3.0, 2500.0); glMatrixMode(GL_MODELVIEW); doc->world.render_targets(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); if(hits > 0) { int choose = buffer[3]; int depth = buffer[1]; for(int i = 0; i < hits; i++) { if(buffer[i * 4 + 1] < depth) { choose = buffer[i * 4 + 3]; depth = buffer[i * 4 + 1]; } } choose--; mainwin->select(choose); } else { mainwin->unselectAll(); } delete buffer; break; case 2: // button 2, pick and center glGetIntegerv(GL_VIEWPORT, viewport); buffer = new GLuint[doc->world.list.size() * 4]; glSelectBuffer(doc->world.list.size() * 4, buffer); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix((double) x, (double) (viewport[3] - y), 1.0, 1.0, viewport); gluPerspective(45.0, (float) (viewport[2] - viewport[0]) / (float) (viewport[3] - viewport[1]), 3.0, 2500.0); glMatrixMode(GL_MODELVIEW); doc->world.render_targets(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); if(hits > 0) { int choose = buffer[3]; int depth = buffer[1]; for(int i = 0; i < hits; i++) { if(buffer[i * 4 + 1] < depth) { choose = buffer[i * 4 + 3]; depth = buffer[i * 4 + 1]; } } choose--; if(doc->world.list[choose].type != LINK) { doc->camera.fx = doc->world.list[choose].obj->get_px(); doc->camera.fy = doc->world.list[choose].obj->get_py(); doc->camera.fz = doc->world.list[choose].obj->get_pz(); doc->camera.fcamera = true; } mainwin->select(choose); } else { doc->camera.fx = 0; doc->camera.fy = 0; doc->camera.fz = 0; doc->camera.fcamera = true; mainwin->unselectAll(); } delete buffer; break; case 3: // button 3, start roaming mainwin->mouse_x = event->x_root; mainwin->mouse_y = event->y_root; break; case 4: // button 4, mouse wheel up, zoom in break; case 5: // button 5, mouse wheel down, zoom out break; } return TRUE; }
void get_light_under_mouse() { //ok, first of all, let's see what objects we have in range... int i, count, x, y, dist1, dist2, hits; GLint viewport[4]; GLuint *buffer, z_coordinate; double matrix[16]; selected_light = -1; x = (int)-camera_x; y = (int)-camera_y; count = 0; for (i = 0; i < MAX_LIGHTS; i++) { if (lights_list[i]) { dist1 = x - (int)lights_list[i]->pos_x; dist2 = y - (int)lights_list[i]->pos_y; if (dist1 * dist1 + dist2 * dist2 <= ((40 * 40) * (zoom_level / 15.75f))) { count++; } } } if (count == 0) { return; } count++; count *= 4; glGetIntegerv(GL_VIEWPORT, viewport); buffer = malloc(count * sizeof(GLuint)); glSelectBuffer(count, buffer); glGetDoublev(GL_PROJECTION_MATRIX, matrix); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix(mouse_x, window_height-mouse_y, 1.0, 1.0, viewport); glMultMatrixd(matrix); glMatrixMode(GL_MODELVIEW); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glPushMatrix(); glLoadIdentity(); // Reset The Matrix Move(); for (i = 0; i < MAX_LIGHTS; i++) { if (lights_list[i]) { dist1 = x - (int)lights_list[i]->pos_x; dist2 = y - (int)lights_list[i]->pos_y; if (dist1 * dist1 + dist2 * dist2 <= ((40 * 40) * (zoom_level / 15.75f))) { glLoadName(i); draw_light_source(lights_list[i]); } } } glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); z_coordinate = 0xFFFFFFFF; for (i = 0; i < hits; i++) { if (buffer[(i * 4) + 1] < z_coordinate) { selected_light = buffer[(i*4)+3]; z_coordinate = buffer[(i*4)+1]; } } free(buffer); }
static void zprPick(GLdouble x, GLdouble y,GLdouble delX, GLdouble delY) { GLuint buffer[1024]; const int bufferSize = sizeof(buffer)/sizeof(GLuint); GLint viewport[4]; GLdouble projection[16]; GLint hits; GLint i,j,k; GLint min = -1; GLuint minZ = -1; glSelectBuffer(bufferSize,buffer); /* Selection buffer for hit records */ glRenderMode(GL_SELECT); /* OpenGL selection mode */ glInitNames(); /* Clear OpenGL name stack */ glMatrixMode(GL_PROJECTION); glPushMatrix(); /* Push current projection matrix */ glGetIntegerv(GL_VIEWPORT,viewport); /* Get the current viewport size */ glGetDoublev(GL_PROJECTION_MATRIX,projection); /* Get the projection matrix */ glLoadIdentity(); /* Reset the projection matrix */ gluPickMatrix(x,y,delX,delY,viewport); /* Set the picking matrix */ glMultMatrixd(projection); /* Apply projection matrix */ glMatrixMode(GL_MODELVIEW); if (selection) selection(); /* Draw the scene in selection mode */ hits = glRenderMode(GL_RENDER); /* Return to normal rendering mode */ /* Diagnostic output to stdout */ #ifndef NDEBUG if (hits!=0) { printf("hits = %d\n",hits); for (i=0,j=0; i<hits; i++) { printf("\tsize = %u, min = %u, max = %u : ",buffer[j],buffer[j+1],buffer[j+2]); for (k=0; k < (GLint) buffer[j]; k++) printf("%u ",buffer[j+3+k]); printf("\n"); j += 3 + buffer[j]; } } #endif /* Determine the nearest hit */ if (hits) { for (i=0,j=0; i<hits; i++) { if (buffer[j+1]<minZ) { /* If name stack is empty, return -1 */ /* If name stack is not empty, return top-most name */ if (buffer[j]==0) min = -1; else min = buffer[j+2+buffer[j]]; minZ = buffer[j+1]; } j += buffer[j] + 3; } } glMatrixMode(GL_PROJECTION); glPopMatrix(); /* Restore projection matrix */ glMatrixMode(GL_MODELVIEW); if (pick) pick(min); /* Pass pick event back to application */ }
int RetrieveObjectID(int x, int y) { int objectsFound = 0; // This will hold the amount of objects clicked int viewportCoords[4] = {0}; // We need an array to hold our view port coordinates // This will hold the ID's of the objects we click on. // We make it an arbitrary number of 32 because openGL also stores other information // that we don't care about. There is about 4 slots of info for every object ID taken up. unsigned int selectBuffer[32] = {0}; // glSelectBuffer is what we register our selection buffer with. The first parameter // is the size of our array. The next parameter is the buffer to store the information found. // More information on the information that will be stored in selectBuffer is further below. glSelectBuffer(32, selectBuffer); // Setup our selection buffer to accept object ID's // This function returns information about many things in OpenGL. We pass in GL_VIEWPORT // to get the view port coordinates. It saves it like a RECT with {top, left, bottom, right} glGetIntegerv(GL_VIEWPORT, viewportCoords); // Get the current view port coordinates // Now we want to get out of our GL_MODELVIEW matrix and start effecting our // GL_PROJECTION matrix. This allows us to check our X and Y coords against 3D space. glMatrixMode(GL_PROJECTION); // We want to now effect our projection matrix glPushMatrix(); // We push on a new matrix so we don't effect our 3D projection // This makes it so it doesn't change the frame buffer if we render into it, instead, // a record of the names of primitives that would have been drawn if the render mode was // GL_RENDER are now stored in the selection array (selectBuffer). glRenderMode(GL_SELECT); // Allows us to render the objects, but not change the frame buffer glLoadIdentity(); // Reset our projection matrix // gluPickMatrix allows us to create a projection matrix that is around our // cursor. This basically only allows rendering in the region that we specify. // If an object is rendered into that region, then it saves that objects ID for us (The magic). // The first 2 parameters are the X and Y position to start from, then the next 2 // are the width and height of the region from the starting point. The last parameter is // of course our view port coordinates. You will notice we subtract "y" from the // BOTTOM view port coordinate. We do this to flip the Y coordinates around. The 0 y // coordinate starts from the bottom, which is opposite to window's coordinates. // We also give a 2 by 2 region to look for an object in. This can be changed to preference. gluPickMatrix(x, viewportCoords[3] - y, 2, 2, viewportCoords); // Next, we just call our normal gluPerspective() function, exactly as we did on startup. // This is to multiply the perspective matrix by the pick matrix we created up above. gluPerspective(45.0f,(float)g_rRect.right/(float)g_rRect.bottom,0.1f,150.0f); glMatrixMode(GL_MODELVIEW); // Go back into our model view matrix RenderScene(); // Now we render into our selective mode to pinpoint clicked objects // If we return to our normal render mode from select mode, glRenderMode returns // the number of objects that were found in our specified region (specified in gluPickMatrix()) objectsFound = glRenderMode(GL_RENDER); // Return to render mode and get the number of objects found glMatrixMode(GL_PROJECTION); // Put our projection matrix back to normal. glPopMatrix(); // Stop effecting our projection matrix glMatrixMode(GL_MODELVIEW); // Go back to our normal model view matrix // PHEW! That was some stuff confusing stuff. Now we are out of the clear and should have // an ID of the object we clicked on. objectsFound should be at least 1 if we found an object. if (objectsFound > 0) { // If we found more than one object, we need to check the depth values // of all the objects found. The object with the LEAST depth value is // the closest object that we clicked on. Depending on what you are doing, // you might want ALL the objects that you clicked on (if some objects were // behind the closest one), but for this tutorial we just care about the one // in front. So, how do we get the depth value? Well, The selectionBuffer // holds it. For every object there is 4 values. The first value is // "the number of names in the name stack at the time of the event, followed // by the minimum and maximum depth values of all vertices that hit since the // previous event, then followed by the name stack contents, bottom name first." - MSDN // The only ones we care about are the minimum depth value (the second value) and // the object ID that was passed into glLoadName() (This is the fourth value). // So, [0 - 3] is the first object's data, [4 - 7] is the second object's data, etc... // Be carefull though, because if you are displaying 2D text in front, it will // always find that as the lowest object. So make sure you disable text when // rendering the screen for the object test. I use a flag for RenderScene(). // So, lets get the object with the lowest depth! // Set the lowest depth to the first object to start it off. // 1 is the first object's minimum Z value. // We use an unsigned int so we don't get a warning with selectBuffer below. unsigned int lowestDepth = selectBuffer[1]; // Set the selected object to the first object to start it off. // 3 is the first object's object ID we passed into glLoadName(). int selectedObject = selectBuffer[3]; // Go through all of the objects found, but start at the second one for(int i = 1; i < objectsFound; i++) { // Check if the current objects depth is lower than the current lowest // Notice we times i by 4 (4 values for each object) and add 1 for the depth. if(selectBuffer[(i * 4) + 1] < lowestDepth) { // Set the current lowest depth lowestDepth = selectBuffer[(i * 4) + 1]; // Set the current object ID selectedObject = selectBuffer[(i * 4) + 3]; } } // Return the selected object return selectedObject; } // We didn't click on any objects so return 0 return 0; }
void Selection(void) // This Is Where Selection Is Done { GLuint buffer[512]; // Set Up A Selection Buffer GLint hits; // The Number Of Objects That We Selected if (game) // Is Game Over? return; // If So, Don't Bother Checking For Hits PlaySound("data/shot.wav",NULL,SND_ASYNC); // Play Gun Shot Sound // The Size Of The Viewport. [0] Is <x>, [1] Is <y>, [2] Is <length>, [3] Is <width> GLint viewport[4]; // This Sets The Array <viewport> To The Size And Location Of The Screen Relative To The Window glGetIntegerv(GL_VIEWPORT, viewport); glSelectBuffer(512, buffer); // Tell OpenGL To Use Our Array For Selection // Puts OpenGL In Selection Mode. Nothing Will Be Drawn. Object ID's and Extents Are Stored In The Buffer. (void) glRenderMode(GL_SELECT); glInitNames(); // Initializes The Name Stack glPushName(0); // Push 0 (At Least One Entry) Onto The Stack glMatrixMode(GL_PROJECTION); // Selects The Projection Matrix glPushMatrix(); // Push The Projection Matrix glLoadIdentity(); // Resets The Matrix // This Creates A Matrix That Will Zoom Up To A Small Portion Of The Screen, Where The Mouse Is. gluPickMatrix((GLdouble) mouse_x, (GLdouble) (viewport[3]-mouse_y), 1.0f, 1.0f, viewport); // Apply The Perspective Matrix gluPerspective(45.0f, (GLfloat) (viewport[2]-viewport[0])/(GLfloat) (viewport[3]-viewport[1]), 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix DrawTargets(); // Render The Targets To The Selection Buffer glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glPopMatrix(); // Pop The Projection Matrix glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix hits=glRenderMode(GL_RENDER); // Switch To Render Mode, Find Out How Many // Objects Were Drawn Where The Mouse Was if (hits > 0) // If There Were More Than 0 Hits { int choose = buffer[3]; // Make Our Selection The First Object int depth = buffer[1]; // Store How Far Away It Is for (int loop = 1; loop < hits; loop++) // Loop Through All The Detected Hits { // If This Object Is Closer To Us Than The One We Have Selected if (buffer[loop*4+1] < GLuint(depth)) { choose = buffer[loop*4+3]; // Select The Closer Object depth = buffer[loop*4+1]; // Store How Far Away It Is } } if (!object[choose].hit) // If The Object Hasn't Already Been Hit { object[choose].hit=TRUE; // Mark The Object As Being Hit score+=1; // Increase Score kills+=1; // Increase Level Kills if (kills>level*5) // New Level Yet? { miss=0; // Misses Reset Back To Zero kills=0; // Reset Level Kills level+=1; // Increase Level if (level>30) // Higher Than 30? level=30; // Set Level To 30 (Are You A God?) } } } }
int GLWidget::hitObjects(int x, int y, const int nMaxObjectsHit) { int nFoundObjects = 0; int viewport[4] = {0}; GLuint selectBuffer[32]; int N = 6; glInitNames(); glPushName(0); //Register selection buffer glSelectBuffer(32, selectBuffer); //Get Viewport from OpenGL. Can use this function to obtain many info glGetIntegerv(GL_VIEWPORT, viewport); //Need to change projection matrix glMatrixMode(GL_PROJECTION); //Save current projection matrix glPushMatrix(); //load identity to top matrix glLoadIdentity(); //Pick Matrix for receiving points gluPickMatrix((double)x, (double)(viewport[3] - y), N, N, viewport); //Perspective view or Orthogonal View. Multiply by current projection matrix if(m_bPerspective) { GLfloat fov = 60.0f; gluPerspective(fov, (GLdouble)width()/height(), 1, 3000); } else glOrtho(-1.0, +1.0, -1.0, 1.0, -1.0, 1.0); //Set render mode to select objects //glRenderMode(GL_SELECT); //Goto Model View to draw objects glMatrixMode(GL_MODELVIEW); //Draw with names m_cylinder.drawCurveControlPoints(true); //Revert to previous projection matrix glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); nFoundObjects = glRenderMode(GL_RENDER); if(nFoundObjects > 0) { //Minimum Depth GLuint minDepth = selectBuffer[1]; //Selection ID int selectID = selectBuffer[3]; for(int i=1; i < nFoundObjects; i++) { if(selectBuffer[i*4 + 1] < minDepth) { minDepth = selectBuffer[i*4 + 1]; selectID = selectBuffer[i*4 + 3]; } } return selectID; } return -1; }
void VisualSceneOCCGeometry :: MouseDblClick (int px, int py) { int hits; // select surface triangle by mouse click GLuint selbuf[10000]; glSelectBuffer (10000, selbuf); glRenderMode (GL_SELECT); GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); glMatrixMode (GL_PROJECTION); glPushMatrix(); GLdouble projmat[16]; glGetDoublev (GL_PROJECTION_MATRIX, projmat); glLoadIdentity(); gluPickMatrix (px, viewport[3] - py, 1, 1, viewport); glMultMatrixd (projmat); glClearColor(backcolor, backcolor, backcolor, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glMultMatrixf (transformationmat); glInitNames(); glPushName (1); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glDisable(GL_CLIP_PLANE0); // Philippose - 30/01/2009 // Enable clipping planes for Selection mode in OCC Geometry if (vispar.clipenable) { Vec<3> n(clipplane[0], clipplane[1], clipplane[2]); double len = Abs(n); double mu = -clipplane[3] / (len*len); Point<3> p (mu * n); n /= len; Vec<3> t1 = n.GetNormal (); Vec<3> t2 = Cross (n, t1); double xi1mid = (center - p) * t1; double xi2mid = (center - p) * t2; glLoadName (0); glBegin (GL_QUADS); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid-rad) * t2); glVertex3dv (p + (xi1mid+rad) * t1 + (xi2mid+rad) * t2); glVertex3dv (p + (xi1mid-rad) * t1 + (xi2mid+rad) * t2); glEnd (); } glCallList (trilists.Get(1)); glDisable (GL_POLYGON_OFFSET_FILL); glPopName(); glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (GL_MODELVIEW); glPopMatrix(); glFlush(); hits = glRenderMode (GL_RENDER); int minname = 0; GLuint mindepth = 0; // find clippingplane GLuint clipdepth = 0; // GLuint(-1); for (int i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; if (!curname) clipdepth = selbuf[4*i+1]; } for (int i = 0; i < hits; i++) { int curname = selbuf[4*i+3]; GLuint curdepth = selbuf[4*i+1]; if (curname && (curdepth> clipdepth) && (curdepth < mindepth || !minname)) { mindepth = curdepth; minname = curname; } } occgeometry->LowLightAll(); if (minname) { occgeometry->fvispar[minname-1].Highlight(); if (vispar.occzoomtohighlightedentity) occgeometry->changed = OCCGEOMETRYVISUALIZATIONFULLCHANGE; else occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; cout << "Selected face: " << minname << endl; } else { occgeometry->changed = OCCGEOMETRYVISUALIZATIONHALFCHANGE; } glDisable(GL_CLIP_PLANE0); SelectFaceInOCCDialogTree (minname); // Philippose - 30/01/2009 // Set the currently selected face in the array // for local face mesh size definition occgeometry->SetSelectedFace(minname); // selecttimestamp = NextTimeStamp(); }
void Gource::mousetrace(Frustum& frustum, float dt) { GLuint buffer[512]; GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); glSelectBuffer(512, buffer); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); (void) glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPickMatrix((GLdouble) mousepos.x, (GLdouble) (viewport[3]-mousepos.y), 1.0f, 1.0f, viewport); gluPerspective(90.0f, (GLfloat)display.width/(GLfloat)display.height, 0.1f, camera.getZFar()); camera.look(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); for(std::map<std::string,RUser*>::iterator it = users.begin(); it!=users.end(); it++) { it->second->drawSimple(dt); } glDisable(GL_TEXTURE_2D); glColor4f(1.0, 1.0, 1.0, 1.0); root->drawSimple(frustum, dt); glMatrixMode(GL_MODELVIEW); mouse_hits = glRenderMode(GL_RENDER); RFile* fileSelection = 0; RUser* userSelection = 0; if (mouse_hits > 0) { int choice = buffer[3]; GLuint depth = buffer[1]; for (int loop = 1; loop < mouse_hits; loop++) { if (buffer[loop*4+1] < depth) { choice = buffer[loop*4+3]; depth = buffer[loop*4+1]; } } if(choice != 0) { selectionDepth = depth; std::map<int, RFile*>::iterator filetest; std::map<int, RUser*>::iterator usertest; if((filetest = tagfilemap.find(choice)) != tagfilemap.end()) { fileSelection = filetest->second; } else if((usertest = tagusermap.find(choice)) != tagusermap.end()) { userSelection = usertest->second; } } } glDisable(GL_DEPTH_TEST); // is over a file if(fileSelection != 0) { // un hover a user if(hoverUser != 0) { hoverUser->setMouseOver(false); hoverUser = 0; } if(fileSelection != hoverFile) { //deselect previous selection if(hoverFile !=0) hoverFile->setMouseOver(false); //select new fileSelection->setMouseOver(true); hoverFile = fileSelection; } // is over a user } else if(userSelection != 0) { // un hover a file if(hoverFile != 0) { hoverFile->setMouseOver(false); hoverFile = 0; } if(userSelection != hoverUser) { //deselect previous selection if(hoverUser !=0) hoverUser->setMouseOver(false); //select new userSelection->setMouseOver(true); hoverUser = userSelection; } } else { if(hoverFile!=0) hoverFile->setMouseOver(false); if(hoverUser!=0) hoverUser->setMouseOver(false); hoverFile=0; hoverUser=0; } if(mouseclicked) { if(hoverUser!=0) selectUser(hoverUser); else if(hoverFile!=0) selectFile(hoverFile); else selectUser(0); } }
int __glXDispSwap_RenderMode(__GLXclientState * cl, GLbyte * pc) { ClientPtr client = cl->client; __GLXcontext *cx; xGLXRenderModeReply reply; GLint nitems = 0, retBytes = 0, retval, newModeCheck; GLubyte *retBuffer = NULL; GLenum newMode; __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; int error; REQUEST_FIXED_SIZE(xGLXSingleReq, 4); __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; } pc += __GLX_SINGLE_HDR_SIZE; __GLX_SWAP_INT(pc); newMode = *(GLenum *) pc; retval = glRenderMode(newMode); /* Check that render mode worked */ glGetIntegerv(GL_RENDER_MODE, &newModeCheck); if (newModeCheck != newMode) { /* Render mode change failed. Bail */ newMode = newModeCheck; goto noChangeAllowed; } /* ** Render mode might have still failed if we get here. But in this ** case we can't really tell, nor does it matter. If it did fail, it ** will return 0, and thus we won't send any data across the wire. */ switch (cx->renderMode) { case GL_RENDER: cx->renderMode = newMode; break; case GL_FEEDBACK: if (retval < 0) { /* Overflow happened. Copy the entire buffer */ nitems = cx->feedbackBufSize; } else { nitems = retval; } retBytes = nitems * __GLX_SIZE_FLOAT32; retBuffer = (GLubyte *) cx->feedbackBuf; __GLX_SWAP_FLOAT_ARRAY((GLbyte *) retBuffer, nitems); cx->renderMode = newMode; break; case GL_SELECT: if (retval < 0) { /* Overflow happened. Copy the entire buffer */ nitems = cx->selectBufSize; } else { GLuint *bp = cx->selectBuf; GLint i; /* ** Figure out how many bytes of data need to be sent. Parse ** the selection buffer to determine this fact as the ** return value is the number of hits, not the number of ** items in the buffer. */ nitems = 0; i = retval; while (--i >= 0) { GLuint n; /* Parse select data for this hit */ n = *bp; bp += 3 + n; } nitems = bp - cx->selectBuf; } retBytes = nitems * __GLX_SIZE_CARD32; retBuffer = (GLubyte *) cx->selectBuf; __GLX_SWAP_INT_ARRAY((GLbyte *) retBuffer, nitems); cx->renderMode = newMode; break; } /* ** First reply is the number of elements returned in the feedback or ** selection array, as per the API for glRenderMode itself. */ noChangeAllowed:; reply = (xGLXRenderModeReply) { .type = X_Reply, .sequenceNumber = client->sequence, .length = nitems, .retval = retval, .size = nitems, .newMode = newMode }; __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.retval); __GLX_SWAP_INT(&reply.size); __GLX_SWAP_INT(&reply.newMode); WriteToClient(client, sz_xGLXRenderModeReply, &reply); if (retBytes) { WriteToClient(client, retBytes, retBuffer); } return Success; } int __glXDispSwap_Flush(__GLXclientState * cl, GLbyte * pc) { ClientPtr client = cl->client; __GLXcontext *cx; int error; __GLX_DECLARE_SWAP_VARIABLES; REQUEST_SIZE_MATCH(xGLXSingleReq); __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; } glFlush(); return Success; }
/* Tesselates a high order rectangular patch into single triangles using gl evaluators * * The problem is that OpenGL does not offer a direct way to return the tesselated primitives, * and they can't be sent off for rendering directly either. Tesselating is slow, so we want * to cache the patches in a vertex buffer. But more importantly, gl can't bind generated * attributes to numbered shader attributes, so we have to store them and rebind them as needed * in drawprim. * * To read back, the opengl feedback mode is used. This creates a problem because we want * untransformed, unlit vertices, but feedback runs everything through transform and lighting. * Thus disable lighting and set identity matrices to get unmodified colors and positions. * To overcome clipping find the biggest x, y and z values of the vertices in the patch and scale * them to [-1.0;+1.0] and set the viewport up to scale them back. * * Normals are more tricky: Draw white vertices with 3 directional lights, and calculate the * resulting colors back to the normals. * * NOTE: This function activates a context for blitting, modifies matrices & viewport, but * does not restore it because normally a draw follows immediately afterwards. The caller is * responsible of taking care that either the gl states are restored, or the context activated * for drawing to reset the lastWasBlit flag. */ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, struct WineD3DRectPatch *patch) { unsigned int i, j, num_quads, out_vertex_size, buffer_size, d3d_out_vertex_size; float max_x = 0.0f, max_y = 0.0f, max_z = 0.0f, neg_z = 0.0f; struct wined3d_stream_info stream_info; struct wined3d_stream_info_element *e; struct wined3d_context *context; const BYTE *data; const WINED3DRECTPATCH_INFO *info = &patch->RectPatchInfo; DWORD vtxStride; GLenum feedback_type; GLfloat *feedbuffer; /* Simply activate the context for blitting. This disables all the things we don't want and * takes care of dirtifying. Dirtifying is preferred over pushing / popping, since drawing the * patch (as opposed to normal draws) will most likely need different changes anyway. */ context = context_acquire(This, NULL, CTXUSAGE_BLIT); /* First, locate the position data. This is provided in a vertex buffer in the stateblock. * Beware of vbos */ device_stream_info_from_declaration(This, FALSE, &stream_info, NULL); e = &stream_info.elements[WINED3D_FFP_POSITION]; if (e->buffer_object) { struct wined3d_buffer *vb; vb = (struct wined3d_buffer *)This->stateBlock->streamSource[e->stream_idx]; e->data = (BYTE *)((unsigned long)e->data + (unsigned long)buffer_get_sysmem(vb)); } vtxStride = e->stride; data = e->data + vtxStride * info->Stride * info->StartVertexOffsetHeight + vtxStride * info->StartVertexOffsetWidth; /* Not entirely sure about what happens with transformed vertices */ if (stream_info.position_transformed) FIXME("Transformed position in rectpatch generation\n"); if(vtxStride % sizeof(GLfloat)) { /* glMap2f reads vertex sizes in GLfloats, the d3d stride is in bytes. * I don't see how the stride could not be a multiple of 4, but make sure * to check it */ ERR("Vertex stride is not a multiple of sizeof(GLfloat)\n"); } if(info->Basis != WINED3DBASIS_BEZIER) { FIXME("Basis is %s, how to handle this?\n", debug_d3dbasis(info->Basis)); } if(info->Degree != WINED3DDEGREE_CUBIC) { FIXME("Degree is %s, how to handle this?\n", debug_d3ddegree(info->Degree)); } /* First, get the boundary cube of the input data */ for(j = 0; j < info->Height; j++) { for(i = 0; i < info->Width; i++) { const float *v = (const float *)(data + vtxStride * i + vtxStride * info->Stride * j); if(fabs(v[0]) > max_x) max_x = fabs(v[0]); if(fabs(v[1]) > max_y) max_y = fabs(v[1]); if(fabs(v[2]) > max_z) max_z = fabs(v[2]); if(v[2] < neg_z) neg_z = v[2]; } } /* This needs some improvements in the vertex decl code */ FIXME("Cannot find data to generate. Only generating position and normals\n"); patch->has_normals = TRUE; patch->has_texcoords = FALSE; ENTER_GL(); glMatrixMode(GL_PROJECTION); checkGLcall("glMatrixMode(GL_PROJECTION)"); glLoadIdentity(); checkGLcall("glLoadIndentity()"); glScalef(1.0f / (max_x), 1.0f / (max_y), max_z == 0.0f ? 1.0f : 1.0f / (2.0f * max_z)); glTranslatef(0.0f, 0.0f, 0.5f); checkGLcall("glScalef"); glViewport(-max_x, -max_y, 2 * (max_x), 2 * (max_y)); checkGLcall("glViewport"); /* Some states to take care of. If we're in wireframe opengl will produce lines, and confuse * our feedback buffer parser */ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_FILLMODE)); if(patch->has_normals) { static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f}; static const GLfloat red[] = {1.0f, 0.0f, 0.0f, 0.0f}; static const GLfloat green[] = {0.0f, 1.0f, 0.0f, 0.0f}; static const GLfloat blue[] = {0.0f, 0.0f, 1.0f, 0.0f}; static const GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f}; glEnable(GL_LIGHTING); checkGLcall("glEnable(GL_LIGHTING)"); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black); checkGLcall("glLightModel for MODEL_AMBIENT"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_AMBIENT)); for (i = 3; i < context->gl_info->limits.lights; ++i) { glDisable(GL_LIGHT0 + i); checkGLcall("glDisable(GL_LIGHT0 + i)"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i)); } IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(0)); glLightfv(GL_LIGHT0, GL_DIFFUSE, red); glLightfv(GL_LIGHT0, GL_SPECULAR, black); glLightfv(GL_LIGHT0, GL_AMBIENT, black); glLightfv(GL_LIGHT0, GL_POSITION, red); glEnable(GL_LIGHT0); checkGLcall("Setting up light 1"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(1)); glLightfv(GL_LIGHT1, GL_DIFFUSE, green); glLightfv(GL_LIGHT1, GL_SPECULAR, black); glLightfv(GL_LIGHT1, GL_AMBIENT, black); glLightfv(GL_LIGHT1, GL_POSITION, green); glEnable(GL_LIGHT1); checkGLcall("Setting up light 2"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(2)); glLightfv(GL_LIGHT2, GL_DIFFUSE, blue); glLightfv(GL_LIGHT2, GL_SPECULAR, black); glLightfv(GL_LIGHT2, GL_AMBIENT, black); glLightfv(GL_LIGHT2, GL_POSITION, blue); glEnable(GL_LIGHT2); checkGLcall("Setting up light 3"); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_MATERIAL); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORVERTEX)); glDisable(GL_COLOR_MATERIAL); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, white); checkGLcall("Setting up materials"); } /* Enable the needed maps. * GL_MAP2_VERTEX_3 is needed for positional data. * GL_AUTO_NORMAL to generate normals from the position. Do not use GL_MAP2_NORMAL. * GL_MAP2_TEXTURE_COORD_4 for texture coords */ num_quads = ceilf(patch->numSegs[0]) * ceilf(patch->numSegs[1]); out_vertex_size = 3 /* position */; d3d_out_vertex_size = 3; glEnable(GL_MAP2_VERTEX_3); if(patch->has_normals && patch->has_texcoords) { FIXME("Texcoords not handled yet\n"); feedback_type = GL_3D_COLOR_TEXTURE; out_vertex_size += 8; d3d_out_vertex_size += 7; glEnable(GL_AUTO_NORMAL); glEnable(GL_MAP2_TEXTURE_COORD_4); } else if(patch->has_texcoords) { FIXME("Texcoords not handled yet\n"); feedback_type = GL_3D_COLOR_TEXTURE; out_vertex_size += 7; d3d_out_vertex_size += 4; glEnable(GL_MAP2_TEXTURE_COORD_4); } else if(patch->has_normals) { feedback_type = GL_3D_COLOR; out_vertex_size += 4; d3d_out_vertex_size += 3; glEnable(GL_AUTO_NORMAL); } else { feedback_type = GL_3D; } checkGLcall("glEnable vertex attrib generation"); buffer_size = num_quads * out_vertex_size * 2 /* triangle list */ * 3 /* verts per tri */ + 4 * num_quads /* 2 triangle markers per quad + num verts in tri */; feedbuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffer_size * sizeof(float) * 8); glMap2f(GL_MAP2_VERTEX_3, 0.0f, 1.0f, vtxStride / sizeof(float), info->Width, 0.0f, 1.0f, info->Stride * vtxStride / sizeof(float), info->Height, (const GLfloat *)data); checkGLcall("glMap2f"); if(patch->has_texcoords) { glMap2f(GL_MAP2_TEXTURE_COORD_4, 0.0f, 1.0f, vtxStride / sizeof(float), info->Width, 0.0f, 1.0f, info->Stride * vtxStride / sizeof(float), info->Height, (const GLfloat *)data); checkGLcall("glMap2f"); } glMapGrid2f(ceilf(patch->numSegs[0]), 0.0f, 1.0f, ceilf(patch->numSegs[1]), 0.0f, 1.0f); checkGLcall("glMapGrid2f"); glFeedbackBuffer(buffer_size * 2, feedback_type, feedbuffer); checkGLcall("glFeedbackBuffer"); glRenderMode(GL_FEEDBACK); glEvalMesh2(GL_FILL, 0, ceilf(patch->numSegs[0]), 0, ceilf(patch->numSegs[1])); checkGLcall("glEvalMesh2"); i = glRenderMode(GL_RENDER); if(i == -1) { LEAVE_GL(); ERR("Feedback failed. Expected %d elements back\n", buffer_size); HeapFree(GetProcessHeap(), 0, feedbuffer); context_release(context); return WINED3DERR_DRIVERINTERNALERROR; } else if(i != buffer_size) { LEAVE_GL(); ERR("Unexpected amount of elements returned. Expected %d, got %d\n", buffer_size, i); HeapFree(GetProcessHeap(), 0, feedbuffer); context_release(context); return WINED3DERR_DRIVERINTERNALERROR; } else { TRACE("Got %d elements as expected\n", i); } HeapFree(GetProcessHeap(), 0, patch->mem); patch->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_quads * 6 * d3d_out_vertex_size * sizeof(float) * 8); i = 0; for(j = 0; j < buffer_size; j += (3 /* num verts */ * out_vertex_size + 2 /* tri marker */)) { if(feedbuffer[j] != GL_POLYGON_TOKEN) { ERR("Unexpected token: %f\n", feedbuffer[j]); continue; } if(feedbuffer[j + 1] != 3) { ERR("Unexpected polygon: %f corners\n", feedbuffer[j + 1]); continue; } /* Somehow there are different ideas about back / front facing, so fix up the * vertex order */ patch->mem[i + 0] = feedbuffer[j + out_vertex_size * 2 + 2]; /* x, triangle 2 */ patch->mem[i + 1] = feedbuffer[j + out_vertex_size * 2 + 3]; /* y, triangle 2 */ patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 2 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 3 */ if(patch->has_normals) { patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 2 + 5]; patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 2 + 6]; patch->mem[i + 5] = feedbuffer[j + out_vertex_size * 2 + 7]; } i += d3d_out_vertex_size; patch->mem[i + 0] = feedbuffer[j + out_vertex_size * 1 + 2]; /* x, triangle 2 */ patch->mem[i + 1] = feedbuffer[j + out_vertex_size * 1 + 3]; /* y, triangle 2 */ patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 1 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 2 */ if(patch->has_normals) { patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 1 + 5]; patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 1 + 6]; patch->mem[i + 5] = feedbuffer[j + out_vertex_size * 1 + 7]; } i += d3d_out_vertex_size; patch->mem[i + 0] = feedbuffer[j + out_vertex_size * 0 + 2]; /* x, triangle 1 */ patch->mem[i + 1] = feedbuffer[j + out_vertex_size * 0 + 3]; /* y, triangle 1 */ patch->mem[i + 2] = (feedbuffer[j + out_vertex_size * 0 + 4] - 0.5f) * 4.0f * max_z; /* z, triangle 1 */ if(patch->has_normals) { patch->mem[i + 3] = feedbuffer[j + out_vertex_size * 0 + 5]; patch->mem[i + 4] = feedbuffer[j + out_vertex_size * 0 + 6]; patch->mem[i + 5] = feedbuffer[j + out_vertex_size * 0 + 7]; } i += d3d_out_vertex_size; } if(patch->has_normals) { /* Now do the same with reverse light directions */ static const GLfloat x[] = {-1.0f, 0.0f, 0.0f, 0.0f}; static const GLfloat y[] = { 0.0f, -1.0f, 0.0f, 0.0f}; static const GLfloat z[] = { 0.0f, 0.0f, -1.0f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, x); glLightfv(GL_LIGHT1, GL_POSITION, y); glLightfv(GL_LIGHT2, GL_POSITION, z); checkGLcall("Setting up reverse light directions"); glRenderMode(GL_FEEDBACK); checkGLcall("glRenderMode(GL_FEEDBACK)"); glEvalMesh2(GL_FILL, 0, ceilf(patch->numSegs[0]), 0, ceilf(patch->numSegs[1])); checkGLcall("glEvalMesh2"); i = glRenderMode(GL_RENDER); checkGLcall("glRenderMode(GL_RENDER)"); i = 0; for(j = 0; j < buffer_size; j += (3 /* num verts */ * out_vertex_size + 2 /* tri marker */)) { if(feedbuffer[j] != GL_POLYGON_TOKEN) { ERR("Unexpected token: %f\n", feedbuffer[j]); continue; } if(feedbuffer[j + 1] != 3) { ERR("Unexpected polygon: %f corners\n", feedbuffer[j + 1]); continue; } if(patch->mem[i + 3] == 0.0f) patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 2 + 5]; if(patch->mem[i + 4] == 0.0f) patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 2 + 6]; if(patch->mem[i + 5] == 0.0f) patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 2 + 7]; normalize_normal(patch->mem + i + 3); i += d3d_out_vertex_size; if(patch->mem[i + 3] == 0.0f) patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 1 + 5]; if(patch->mem[i + 4] == 0.0f) patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 1 + 6]; if(patch->mem[i + 5] == 0.0f) patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 1 + 7]; normalize_normal(patch->mem + i + 3); i += d3d_out_vertex_size; if(patch->mem[i + 3] == 0.0f) patch->mem[i + 3] = -feedbuffer[j + out_vertex_size * 0 + 5]; if(patch->mem[i + 4] == 0.0f) patch->mem[i + 4] = -feedbuffer[j + out_vertex_size * 0 + 6]; if(patch->mem[i + 5] == 0.0f) patch->mem[i + 5] = -feedbuffer[j + out_vertex_size * 0 + 7]; normalize_normal(patch->mem + i + 3); i += d3d_out_vertex_size; } } glDisable(GL_MAP2_VERTEX_3); glDisable(GL_AUTO_NORMAL); glDisable(GL_MAP2_NORMAL); glDisable(GL_MAP2_TEXTURE_COORD_4); checkGLcall("glDisable vertex attrib generation"); LEAVE_GL(); context_release(context); HeapFree(GetProcessHeap(), 0, feedbuffer); vtxStride = 3 * sizeof(float); if(patch->has_normals) { vtxStride += 3 * sizeof(float); } if(patch->has_texcoords) { vtxStride += 4 * sizeof(float); } memset(&patch->strided, 0, sizeof(patch->strided)); patch->strided.position.format = WINED3DFMT_R32G32B32_FLOAT; patch->strided.position.lpData = (BYTE *) patch->mem; patch->strided.position.dwStride = vtxStride; if(patch->has_normals) { patch->strided.normal.format = WINED3DFMT_R32G32B32_FLOAT; patch->strided.normal.lpData = (BYTE *) patch->mem + 3 * sizeof(float) /* pos */; patch->strided.normal.dwStride = vtxStride; } if(patch->has_texcoords) { patch->strided.texCoords[0].format = WINED3DFMT_R32G32B32A32_FLOAT; patch->strided.texCoords[0].lpData = (BYTE *) patch->mem + 3 * sizeof(float) /* pos */; if(patch->has_normals) { patch->strided.texCoords[0].lpData += 3 * sizeof(float); } patch->strided.texCoords[0].dwStride = vtxStride; } return WINED3D_OK; }
int sftcpy(pScene sc,pMesh mesh) { FILE *file; GLfloat *fbbuffer; GLint nvalues; GLsizei size; char *ptr,data[128]; static int nfree=0; /* default */ if ( ddebug ) printf("soft copy\n"); //#ifdef IGL //#define SFT_EXT "ps" //#define GL2PS_EXT GL2PS_EPS //#else #define SFT_EXT "ps" //#endif /* get file name */ strcpy(data,mesh->name); ptr = (char*)strstr(data,".mesh"); if ( ptr ) *ptr = '\0'; nfree = filnum(data,nfree,SFT_EXT); if ( nfree == -1 ) return(0); /* open PS file */ sprintf(data,"%s.%.3d." SFT_EXT,data,nfree); file = fopen(data,"w"); if ( !file ) { fprintf(stdout," Unable to open %s\n",data); return(0); } //#ifdef IGL // // http://www.geuz.org/gl2ps/#tth_sEc3 // GLint buffsize = 0, state = GL2PS_OVERFLOW; // GLint viewport[4]; // // glGetIntegerv(GL_VIEWPORT, viewport); // // while( state == GL2PS_OVERFLOW ){ // buffsize += 1024*1024; // gl2psBeginPage (mesh->name, "medit", viewport, // GL2PS_EXT, GL2PS_BSP_SORT, GL2PS_SILENT | // GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT, // GL_RGBA, 0, NULL, 0, 0, 0, buffsize, // file, data ); // drawModel(sc); // if ( sc->type & S_DECO ) redrawStatusBar(sc); // state = gl2psEndPage(); // } // // fclose(file); // //#else /* size for feedback buffer */ size = 0; nvalues = -1; do { size += 1024*1024; fbbuffer = (GLfloat *)calloc(1+size,sizeof(GLfloat)); if ( !fbbuffer ) { return(0); } if ( ddebug ) printf("feedback pointer = %p\n",fbbuffer); /* draw scene in back buffer */ glFeedbackBuffer(size,GL_3D_COLOR,fbbuffer); (void)glRenderMode(GL_FEEDBACK); /* glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.,0.,-sc->persp->depth, 0.,0.,0., 0.0,1.0,0.0); setupView(sc); glMultMatrixf(sc->view->matrix); glTranslatef(sc->cx,sc->cy,sc->cz); */ drawModel(sc); if ( sc->type & S_DECO ) redrawStatusBar(sc); /*drawModel(sc);*/ nvalues = (GLint)glRenderMode(GL_RENDER); if ( nvalues < 0 ) free(fbbuffer); } while ( nvalues < 0 ); if ( nvalues < 1 ) { return(0); } else if ( ddebug ) printf("nvalues = %d size = %d\n",nvalues,size); /* write EPS file */ glutSetCursor(GLUT_CURSOR_WAIT); headps(file); coreps(file,size,fbbuffer); tailps(file); if ( ddebug ) fprintf(stdout,"%s written\n",data); glutSetCursor(GLUT_CURSOR_INHERIT); //#endif return(1); }