Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <SDL/SDL.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <vector>
- #include "camera.h"
- #include "vector3d.h"
- GLUquadric* quad; //this one for drawing spheres, because I don't use objloader now, to load something
- float zpos=-3.0; //light's z position
- camera cam;
- struct sphere{
- vector3d center;
- float rad; //radius
- int r,g,b; //color for picking
- bool selected; //true if it's selected
- sphere(const vector3d& c,float ra,int cr,int cg,int cb) : center(c),rad(ra),r(cr),g(cg),b(cb),selected(false) {};
- };
- std::vector<sphere> spheres;
- int selected=-1; //-1==nothing selected yet
- //generate unique colors, like:
- //0 0 0
- //0 0 1
- //...
- //0 0 255
- //0 1 0
- //...
- //max 256*256*256
- int nextColor(int &r,int& g,int& b)
- {
- //be careful, the background clear color should be unique (for me it's not, because it's 0,0,255
- b++;
- if(b>255)
- {
- b=0;
- g++;
- if(g>255)
- {
- g=0;
- r++;
- if(r>255)
- {
- std::cout << "error too many item" << std::endl;
- r=255;
- }
- }
- }
- }
- void init()
- {
- glClearColor(0,0,1,1);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(50,640.0/480.0,0.1,1000);
- glMatrixMode(GL_MODELVIEW);
- quad=gluNewQuadric(); //init the quadric, so we can draw spheres
- gluQuadricNormals(quad,GLU_SMOOTH); //generate smooth normal vector for the sphere
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- float spec[]={1.0,1.0,1.0,1.0};
- glLightfv(GL_LIGHT0,GL_SPECULAR,spec);
- glEnable(GL_CULL_FACE); //gluSphere has a hole in it without this call
- glEnable(GL_DEPTH_TEST);
- glInitNames();
- int curr=0,curg=0,curb=0;
- //generate 100 random spheres
- for(int i=0;i<100;i++)
- {
- spheres.push_back(sphere(vector3d(rand()%100-50,rand()%100-50,-(rand()%200+50)),rand()%20,curr,curg,curb));
- nextColor(curr,curg,curb); //with unique color
- }
- }
- //draw the scene normally
- void display()
- {
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
- glLoadIdentity();
- float pos[]={1.0,1.0,zpos,0.0};
- cam.Control();
- cam.UpdateCamera();
- glLightfv(GL_LIGHT0,GL_POSITION,pos);
- for(int i=0;i<100;i++)
- {
- glPushMatrix();
- glTranslatef(spheres[i].center.x,spheres[i].center.y,spheres[i].center.z);
- if(spheres[i].selected)
- {
- glDisable(GL_LIGHTING);
- glColor3f(1.0,0.0,0.0);
- }else
- {
- glEnable(GL_LIGHTING);
- }
- // glColor3f(spheres[i].r/255.0,spheres[i].g/255.0,spheres[i].b/255.0);
- gluSphere(quad,spheres[i].rad,100,100); //generate a sphere, lower the 100,100 parameter, to get lower resolution
- //but better performance, you may want to store all of the spheres previously, in display lists/VBO's, so you don't
- //have to generate it in runtime
- glPopMatrix();
- }
- }
- //if mouse is pressed at x,y coordinates
- void selection(int x,int y)
- {
- glDisable(GL_LIGHTING); //we don't need lighting
- //glViewport(x,480-y,1,1); //you need to change the projection as well
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //clear the screen
- //draw everything to the screen
- for(int i=0;i<100;i++)
- {
- glPushMatrix();
- glTranslatef(spheres[i].center.x,spheres[i].center.y,spheres[i].center.z);
- glColor3f(spheres[i].r/255.0,spheres[i].g/255.0,spheres[i].b/255.0); //use the unique color for every sphere
- gluSphere(quad,spheres[i].rad,100,100);
- glPopMatrix();
- }
- glFlush(); //might be important, in order, for the drawing to finish, alternatively glFinish(), to ensure that
- unsigned char rgb[3];
- //and read the current color (where the cursor is), without lighting or texturing, just the original color
- glReadPixels(x,480-y,1,1,GL_RGB,GL_UNSIGNED_BYTE,rgb);
- bool change=false;
- //find the sphere with that color, and that sphere is selected
- for(int i=0;i<100;i++)
- {
- if(spheres[i].r==rgb[0] && spheres[i].g==rgb[1] && spheres[i].b==rgb[2])
- {
- selected=i;
- change=true;
- spheres[i].selected=true;
- }else
- spheres[i].selected=false;
- }
- if(!change)
- selected=-1;
- glEnable(GL_LIGHTING);
- // glViewport(0,0,640,480);
- }
- int main()
- {
- SDL_Init(SDL_INIT_EVERYTHING);
- SDL_SetVideoMode(640,480,32,SDL_OPENGL);
- bool running=true;
- SDL_Event event;
- Uint32 start;
- init();
- int numframes=0;
- Uint32 lastTime=SDL_GetTicks();
- while(running)
- {
- start=SDL_GetTicks();
- while(SDL_PollEvent(&event))
- {
- switch(event.type)
- {
- case SDL_QUIT:
- running=false;
- break;
- case SDL_KEYDOWN:
- switch(event.key.keysym.sym)
- {
- case SDLK_ESCAPE:
- running=false;
- break;
- case SDLK_UP:
- zpos+=1.0;
- break;
- case SDLK_DOWN:
- zpos-=1.0;
- break;
- case SDLK_RETURN:
- cam.mouseIn(true);
- break;
- case SDLK_BACKSPACE:
- cam.mouseIn(false);
- SDL_ShowCursor(SDL_ENABLE);
- break;
- //you can use similar approach, to move the sphere
- case SDLK_a:
- spheres[selected].center.x-=0.1;
- break;
- case SDLK_s:
- spheres[selected].center.y-=0.1;
- break;
- //more case statement
- }
- break;
- case SDL_MOUSEBUTTONDOWN:
- selection(event.button.x,event.button.y); //if clicked
- break;
- case SDL_MOUSEMOTION:
- // selection(event.motion.x,event.motion.y); //slow down a lot, display lists/VBO could help, to not generate sphere again every frame
- break;
- }
- }
- display();
- SDL_GL_SwapBuffers();
- numframes++;
- //write out the FPS just for curiosity
- if(SDL_GetTicks()-lastTime>=1000)
- {
- std::cout << (float)numframes/((float)(SDL_GetTicks()-lastTime)/1000) << " FPS" << std::endl;
- numframes=0;
- lastTime=SDL_GetTicks();
- }
- // if(1000.0/30>(SDL_GetTicks()-start))
- // SDL_Delay(1000.0/30-(SDL_GetTicks()-start));
- }
- gluDeleteQuadric(quad); //delete the quadric (which draws the sphere)
- SDL_Quit();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement