Advertisement
thecplusplusguy

mouse picking in OpenGL - opengl.cpp

Jul 25th, 2012
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.79 KB | None | 0 0
  1. #include <iostream>
  2. #include <SDL/SDL.h>
  3. #include <GL/gl.h>
  4. #include <GL/glu.h>
  5. #include <vector>
  6. #include "camera.h"
  7. #include "vector3d.h"
  8.  
  9.  
  10. GLUquadric* quad;   //this one for drawing spheres, because I don't use objloader now, to load something
  11. float zpos=-3.0;    //light's z position
  12. camera cam;
  13.  
  14. struct sphere{
  15.     vector3d center;
  16.     float rad;  //radius
  17.     int r,g,b;  //color for picking
  18.     bool selected;  //true if it's selected
  19.     sphere(const vector3d& c,float ra,int cr,int cg,int cb) : center(c),rad(ra),r(cr),g(cg),b(cb),selected(false) {};
  20. };
  21. std::vector<sphere> spheres;
  22. int selected=-1;    //-1==nothing selected yet
  23.  
  24. //generate unique colors, like:
  25. //0 0 0
  26. //0 0 1
  27. //...
  28. //0 0 255
  29. //0 1 0
  30. //...
  31. //max 256*256*256
  32. int nextColor(int &r,int& g,int& b)
  33. {
  34.     //be careful, the background clear color should be unique (for me it's not, because it's 0,0,255
  35.     b++;
  36.     if(b>255)
  37.     {
  38.         b=0;
  39.         g++;
  40.         if(g>255)
  41.         {
  42.             g=0;
  43.             r++;
  44.             if(r>255)
  45.             {
  46.                 std::cout << "error too many item" << std::endl;
  47.                 r=255;
  48.             }
  49.         }
  50.     }
  51. }
  52.  
  53. void init()
  54. {
  55.     glClearColor(0,0,1,1);
  56.     glMatrixMode(GL_PROJECTION);
  57.         glLoadIdentity();
  58.         gluPerspective(50,640.0/480.0,0.1,1000);
  59.     glMatrixMode(GL_MODELVIEW);
  60.     quad=gluNewQuadric();   //init the quadric, so we can draw spheres
  61.     gluQuadricNormals(quad,GLU_SMOOTH); //generate smooth normal vector for the sphere
  62.     glEnable(GL_LIGHTING);
  63.     glEnable(GL_LIGHT0);
  64.     float spec[]={1.0,1.0,1.0,1.0};
  65.     glLightfv(GL_LIGHT0,GL_SPECULAR,spec);
  66.     glEnable(GL_CULL_FACE); //gluSphere has a hole in it without this call
  67.     glEnable(GL_DEPTH_TEST);
  68.     glInitNames();
  69.     int curr=0,curg=0,curb=0;
  70.     //generate 100 random spheres
  71.     for(int i=0;i<100;i++)
  72.     {
  73.         spheres.push_back(sphere(vector3d(rand()%100-50,rand()%100-50,-(rand()%200+50)),rand()%20,curr,curg,curb));
  74.         nextColor(curr,curg,curb);  //with unique color
  75.     }
  76. }
  77.  
  78.  
  79. //draw the scene normally
  80. void display()
  81. {
  82.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  83.     glLoadIdentity();
  84.     float pos[]={1.0,1.0,zpos,0.0};
  85.     cam.Control();
  86.     cam.UpdateCamera();
  87.     glLightfv(GL_LIGHT0,GL_POSITION,pos);
  88.     for(int i=0;i<100;i++)
  89.     {
  90.             glPushMatrix();
  91.                 glTranslatef(spheres[i].center.x,spheres[i].center.y,spheres[i].center.z);
  92.                 if(spheres[i].selected)
  93.                 {
  94.                     glDisable(GL_LIGHTING);
  95.                     glColor3f(1.0,0.0,0.0);
  96.                 }else
  97.                 {
  98.                     glEnable(GL_LIGHTING);
  99.                 }
  100.             //  glColor3f(spheres[i].r/255.0,spheres[i].g/255.0,spheres[i].b/255.0);
  101.                 gluSphere(quad,spheres[i].rad,100,100); //generate a sphere, lower the 100,100 parameter, to get lower resolution
  102.                 //but better performance, you may want to store all of the spheres previously, in display lists/VBO's, so you don't
  103.                 //have to generate it in runtime
  104.             glPopMatrix();
  105.     }
  106.    
  107.  
  108. }
  109.  
  110. //if mouse is pressed at x,y coordinates
  111. void selection(int x,int y)
  112. {
  113.     glDisable(GL_LIGHTING); //we don't need lighting
  114.     //glViewport(x,480-y,1,1);  //you need to change the projection as well
  115.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);   //clear the screen
  116.     //draw everything to the screen
  117.     for(int i=0;i<100;i++)
  118.     {
  119.         glPushMatrix();
  120.             glTranslatef(spheres[i].center.x,spheres[i].center.y,spheres[i].center.z);
  121.             glColor3f(spheres[i].r/255.0,spheres[i].g/255.0,spheres[i].b/255.0);    //use the unique color for every sphere
  122.             gluSphere(quad,spheres[i].rad,100,100);
  123.         glPopMatrix();
  124.     }
  125.  
  126.         glFlush();  //might be important, in order, for the drawing to finish, alternatively glFinish(), to ensure that
  127.         unsigned char rgb[3];
  128.         //and read the current color (where the cursor is), without lighting or texturing, just the original color
  129.         glReadPixels(x,480-y,1,1,GL_RGB,GL_UNSIGNED_BYTE,rgb); 
  130.         bool change=false;
  131.         //find the sphere with that color, and that sphere is selected
  132.         for(int i=0;i<100;i++)
  133.         {
  134.             if(spheres[i].r==rgb[0] && spheres[i].g==rgb[1] && spheres[i].b==rgb[2])
  135.             {
  136.                 selected=i;
  137.                 change=true;
  138.                 spheres[i].selected=true;
  139.             }else
  140.                 spheres[i].selected=false;
  141.         }
  142.         if(!change)
  143.             selected=-1;
  144.         glEnable(GL_LIGHTING);
  145.     //  glViewport(0,0,640,480);
  146.  
  147. }
  148.  
  149. int main()
  150. {
  151.     SDL_Init(SDL_INIT_EVERYTHING);
  152.     SDL_SetVideoMode(640,480,32,SDL_OPENGL);
  153.     bool running=true;
  154.     SDL_Event event;
  155.     Uint32 start;
  156.     init();
  157.     int numframes=0;
  158.     Uint32 lastTime=SDL_GetTicks();
  159.     while(running)
  160.     {
  161.         start=SDL_GetTicks();
  162.         while(SDL_PollEvent(&event))
  163.         {
  164.             switch(event.type)
  165.             {
  166.                 case SDL_QUIT:
  167.                     running=false;
  168.                     break;
  169.                 case SDL_KEYDOWN:
  170.                     switch(event.key.keysym.sym)
  171.                     {
  172.                         case SDLK_ESCAPE:
  173.                             running=false;
  174.                             break;
  175.                         case SDLK_UP:
  176.                             zpos+=1.0;
  177.                             break;
  178.                         case SDLK_DOWN:
  179.                             zpos-=1.0;
  180.                             break;
  181.                         case SDLK_RETURN:
  182.                             cam.mouseIn(true);
  183.                             break;
  184.                         case SDLK_BACKSPACE:
  185.                             cam.mouseIn(false);
  186.                             SDL_ShowCursor(SDL_ENABLE);
  187.                             break;
  188.                         //you can use similar approach, to move the sphere
  189.                         case SDLK_a:
  190.                             spheres[selected].center.x-=0.1;
  191.                             break;
  192.                         case SDLK_s:
  193.                             spheres[selected].center.y-=0.1;
  194.                             break;
  195.                         //more case statement                          
  196.                     }
  197.                     break;
  198.                 case SDL_MOUSEBUTTONDOWN:
  199.                     selection(event.button.x,event.button.y);   //if clicked
  200.                     break;
  201.                 case SDL_MOUSEMOTION:
  202.                 //  selection(event.motion.x,event.motion.y);   //slow down a lot, display lists/VBO could help, to not generate sphere again every frame
  203.                     break;
  204.             }
  205.         }
  206.         display();
  207.         SDL_GL_SwapBuffers();
  208.         numframes++;
  209.         //write out the FPS just for curiosity
  210.         if(SDL_GetTicks()-lastTime>=1000)
  211.         {
  212.             std::cout << (float)numframes/((float)(SDL_GetTicks()-lastTime)/1000) << " FPS" << std::endl;
  213.             numframes=0;
  214.             lastTime=SDL_GetTicks();
  215.         }
  216. //      if(1000.0/30>(SDL_GetTicks()-start))
  217. //          SDL_Delay(1000.0/30-(SDL_GetTicks()-start));
  218.     }
  219.     gluDeleteQuadric(quad); //delete the quadric (which draws the sphere)
  220.     SDL_Quit();
  221. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement