// Copyright (c) David Kabala // Fall 2009 #include #include class Vec3f{ public: Vec3f(void) { _Data[0] = _Data[1] = _Data[2] = 0.0f; } Vec3f(GLfloat x, GLfloat y, GLfloat z) { _Data[0] = x; _Data[1] = y; _Data[2] = z; } void setdata(GLfloat x, GLfloat y, GLfloat z) { _Data[0] = x; _Data[1] = y; _Data[2] = z; } const GLfloat *getdata(void) const { return _Data; } Vec3f operator+(const Vec3f& Right) const { return Vec3f(_Data[0] + Right._Data[0], _Data[1] + Right._Data[1], _Data[2] + Right._Data[2]); } Vec3f operator*(const GLfloat& Right) const { return Vec3f(_Data[0] * Right, _Data[1] * Right, _Data[2] * Right); } const GLfloat& x(void) const { return _Data[0]; } const GLfloat& y(void) const { return _Data[1]; } const GLfloat& z(void) const { return _Data[2]; } const GLfloat& r(void) const // red { return _Data[0]; } const GLfloat& g(void) const // green { return _Data[1]; } const GLfloat& b(void) const // blue { return _Data[2]; } const GLfloat& h(void) const // hue [0, 360] { return _Data[0]; } const GLfloat& s(void) const // saturation [0.0, 1.0] { return _Data[1]; } const GLfloat& v(void) const // value / brightness [0.0, 1.0] { return _Data[2]; } private: GLfloat _Data[3]; }; Vec3f rgb2hsv(const Vec3f& rgb) { Vec3f hsv; return hsv; } Vec3f hsv2rgb(const Vec3f& hsv) { Vec3f rgb; int i; float f; float p; float q; float t; if(hsv.s() != 0.0f) { f = (hsv.h() == 360) ? 0.0 : (hsv.h() / 60.0); i = int(f); f = f - float(i); p = hsv.v() * (1.0 - hsv.s() ); q = hsv.v() * (1.0 - (hsv.s() * f) ); t = hsv.v() * (1.0 - (hsv.s() * (1 - f))); switch (i) { case 0: rgb.setdata(hsv.v(),t,p); break; case 1: rgb.setdata(q,hsv.v(),p); break; case 2: rgb.setdata(p,hsv.v(),t); break; case 3: rgb.setdata(p,q,hsv.v()); break; case 4: rgb.setdata(t,p,hsv.v()); break; case 5: rgb.setdata(hsv.v(),p,q); break; default: //std::cerr << "ERROR i not in [0, 5] in Color::setHSV()!" //<< std::endl; break; } } else { rgb.setdata(hsv.v(),hsv.v(),hsv.v()); } return rgb; } class SceneManager { protected: GLenum _DrawPrimitiveType; GLfloat _Translation[3]; GLfloat _Rotation[3]; int _MouseLastX, _MouseLastY; bool _LeftButtonDown; bool _DrawRGB; public: SceneManager(void) : _DrawPrimitiveType(GL_POINTS), _MouseLastX(-1), _MouseLastY(-1),_LeftButtonDown(false), _DrawRGB(true) { _Rotation[0] = _Rotation[1] = _Rotation[2] = 0.0f; _Translation[0] = _Translation[1] = 0.0f; _Translation[2] = -6.0f; } void init(void) { glLineWidth(3.0f); //glEnable(GL_CULL_FACE); //glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); } void reshape(int w, int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0f,static_cast(w)/static_cast(h),.1f,100.0f); // gluPerspective(fov, aspect, zNear, zFar) glMatrixMode(GL_MODELVIEW); glutPostRedisplay(); } void drawRGBColorCube(GLfloat size) { glBegin(GL_QUADS); //Positive z glColor3f(0.0,1.0,1.0); glVertex3f(-size, size, size); glColor3f(0.0,0.0,1.0); glVertex3f(-size, -size, size); glColor3f(1.0,0.0,1.0); glVertex3f(size, -size, size); glColor3f(1.0,1.0,1.0); glVertex3f(size, size, size); //Negative z glColor3f(0.0,1.0,0.0); glVertex3f(-size, size, -size); glColor3f(1.0,1.0,0.0); glVertex3f(size, size, -size); glColor3f(1.0,0.0,0.0); glVertex3f(size, -size, -size); glColor3f(0.0,0.0,0.0); glVertex3f(-size, -size, -size); //Positive x glColor3f(1.0,1.0,1.0); glVertex3f(size, size, size); glColor3f(1.0,0.0,1.0); glVertex3f(size, -size, size); glColor3f(1.0,0.0,0.0); glVertex3f(size, -size, -size); glColor3f(1.0,1.0,0.0); glVertex3f(size, size, -size); //Negative x glColor3f(0.0,1.0,1.0); glVertex3f(-size, size, size); glColor3f(0.0,1.0,0.0); glVertex3f(-size, size, -size); glColor3f(0.0,0.0,0.0); glVertex3f(-size, -size, -size); glColor3f(0.0,0.0,1.0); glVertex3f(-size, -size, size); //Positive y glColor3f(0.0,1.0,0.0); glVertex3f(-size, size, -size); glColor3f(0.0,1.0,1.0); glVertex3f(-size, size, size); glColor3f(1.0,1.0,1.0); glVertex3f(size, size, size); glColor3f(1.0,1.0,0.0); glVertex3f(size, size, -size); //Negative y glColor3f(0.0,0.0,0.0); glVertex3f(-size, -size, -size); glColor3f(1.0,0.0,0.0); glVertex3f(size, -size, -size); glColor3f(1.0,0.0,1.0); glVertex3f(size, -size, size); glColor3f(0.0,0.0,1.0); glVertex3f(-size, -size, size); glEnd(); Vec3f origin(-size-.0001,-size-.0001,-size-.0001); drawAxis(origin,Vec3f(1.0,0.0,0.0), Vec3f(1.0,0.0,0.0),2.0f); drawAxis(origin,Vec3f(0.0,1.0,0.0), Vec3f(0.0,1.0,0.0),2.0f); drawAxis(origin,Vec3f(0.0,0.0,1.0), Vec3f(0.0,0.0,1.0),2.0f); } // draw a HSV disk void drawHSVColorSpace(GLfloat height, GLfloat radius) { float PI(3.14159f); float Segments(180.0); //Draw the Top cap glBegin(GL_TRIANGLE_FAN); //Center glColor3fv(hsv2rgb(Vec3f(0.0,0.0,1.0)).getdata()); glVertex3f(0.0f,1.0f,0.0f); //Radius for(float seg(0) ; seg<=Segments; ++seg) { glColor3fv(hsv2rgb(Vec3f((seg/Segments)*360.0f,1.0,1.0)).getdata()); glVertex3f(radius * cos((seg/Segments)*2.0*PI),height,radius * sin((seg/Segments)*2.0*PI)); } glEnd(); //Draw the Bottom cap glBegin(GL_TRIANGLE_FAN); //Center glColor3fv(hsv2rgb(Vec3f(0.0,0.0,1.0)).getdata()); glVertex3f(0.0f,0.0f,0.0f); //Radius for(float seg(0) ; seg<=Segments; ++seg) { glColor3fv(hsv2rgb(Vec3f((seg/Segments)*360.0f,1.0,0.0)).getdata()); glVertex3f(radius * cos((seg/Segments)*2.0*PI),0.0f,radius * sin((seg/Segments)*2.0*PI)); } glEnd(); //Draw the Tube glBegin(GL_QUAD_STRIP); //Radius for(float seg(0) ; seg<=Segments; ++seg) { glColor3fv(hsv2rgb(Vec3f((seg/Segments)*360.0f,1.0,0.0)).getdata()); glVertex3f(radius * cos((seg/Segments)*2.0*PI),0.0f,radius * sin((seg/Segments)*2.0*PI)); glColor3fv(hsv2rgb(Vec3f((seg/Segments)*360.0f,1.0,1.0)).getdata()); glVertex3f(radius * cos((seg/Segments)*2.0*PI),height,radius * sin((seg/Segments)*2.0*PI)); } glEnd(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(_Translation[0], _Translation[1], _Translation[2]); glRotatef(_Rotation[0],1.0f,0.0f,0.0f); glRotatef(_Rotation[1],0.0f,1.0f,0.0f); glRotatef(_Rotation[2],0.0f,0.0f,1.0f); if(_DrawRGB) { //Draw a RGB Color cube drawRGBColorCube(1.0); } else { //Draw HSV Color Space drawHSVColorSpace(1.5,3.0); } glPopMatrix(); glutSwapBuffers(); } void drawAxis(Vec3f origin, Vec3f direction, Vec3f color, GLfloat Length) { glBegin(GL_LINES); glColor3fv(color.getdata()); glVertex3fv(origin.getdata()); Vec3f v(origin + (direction * Length)); glVertex3fv(v.getdata()); glEnd(); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 's': //Toggle Draw RGB _DrawRGB = !_DrawRGB; break; } glutPostRedisplay(); } void mouse(int button, int state, int x, int y) { if(button == GLUT_LEFT_BUTTON) { _LeftButtonDown = state == GLUT_DOWN; } _MouseLastX = x; _MouseLastY = y; } void mouseDrag(int x, int y) { float MouseDragRotationScale(0.5); if(_MouseLastX >= 0 && _MouseLastY >= 0 && _LeftButtonDown) { int XDiff(x - _MouseLastX), YDiff(y - _MouseLastY); // rotations about y-axis (vertical) and x-axis (horizontal) _Rotation[1] += static_cast(XDiff) * MouseDragRotationScale; _Rotation[0] += static_cast(YDiff) * MouseDragRotationScale; glutPostRedisplay(); } _MouseLastX = x; _MouseLastY = y; } }; SceneManager mgr; void reshape(int w, int h) { mgr.reshape(w,h); } void display(void) { mgr.display(); } void keyboard(unsigned char key, int x, int y) { mgr.keyboard(key,x,y); } void mouse(int button, int state, int x, int y) { mgr.mouse(button, state,x,y); } void mouseDrag(int x, int y) { mgr.mouseDrag(x,y); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("Color Spaces"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMotionFunc(mouseDrag); glutMouseFunc(mouse); glutReshapeWindow(800,600); mgr.init(); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }