// Sphere.cpp : // Program to draw a sphere // Illustrates depth buffer, how to build a simple solid of revolution, and 3-D polygon drawing /* Programmed by Geovany A. Ramirez and Olac Fuentes October 23, 2009 CS3370 NOTE: Parts of the code are based on: [1] D. Hearn and M. P. Baker, "Computer Graphics with OpenGL", 3rd edition, Pearson. 2004 [2] R.S. Wright and B. Lipchak, "OpenGL SuperBible" 3rd edition, Sams. 2004 */ #include "stdafx.h" #include #include #include "glut.h" using namespace std; // Define a constant for the value of PI, from [2] #define GL_PI 3.1415926535f // Rotation amounts, from [2] static GLfloat xRot =25.0; static GLfloat yRot =-25.0; GLfloat nRange = 80.0f; // display window size int winWidth=600; int winHeight=600; float frx=winWidth/(2*nRange); float fry=winHeight/(2*nRange); // converts from degrees to radians #define d2r(t) (3.1415926535*t/180) struct wcPt2D { // adapted from [1] GLfloat x, y; }; struct wcPt3D { // adapted from [1] GLfloat x, y, z; }; // vertices counter int vx_c=0; // Modes int op_mode=1; // 0: Points, 1: Polygons int fill_poly=1; // 0: wire, 1: filled float axis_size=70.0; int axis_on=1; int smooth_color_on=0; /**************************************/ void draw_axis() { glBegin (GL_LINES); glColor3f (1.0, 0.0, 0.0); // X: Red glVertex3f (-axis_size*0.2, 0.0, 0.0); glVertex3f (axis_size, 0.0, 0.0); glColor3f (0.0, 1.0, 0.0); // Y: Green glVertex3f (0.0, -axis_size*0.2, 0.0); glVertex3f (0.0, axis_size, 0.0); glColor3f (0.0, 0.0, 1.0); // Z: Blue glVertex3f (0.0, 0.0, -axis_size*0.2); glVertex3f (0.0, 0.0, axis_size); glEnd ( ); } // Keyboard Functions void operations(GLubyte sizeFactor, GLint xMouse, GLint yMouse) { switch (sizeFactor) { case ('q' | 'Q') : exit(0); break; case ('f' | 'F'): fill_poly=!fill_poly; break; case ('p' | 'P') : op_mode=!op_mode; break; case ('s' | 'S') : smooth_color_on=!smooth_color_on; break; case ('a' | 'A') : axis_on=!axis_on; break; default: break; } glutPostRedisplay(); } wcPt3D *sphere_compute_points(float r,float step) { GLfloat theta,phi; GLfloat phi1=-0.5*GL_PI; GLfloat phi2=0.5*GL_PI; GLfloat theta1=-1.0*GL_PI; GLfloat theta2=GL_PI; GLfloat num_points=ceil((phi2-phi1)/step)*ceil((theta2-theta1)/step); wcPt3D *sphere=new wcPt3D[num_points]; vx_c=0; for(phi = phi1; phi <= phi2; phi +=step) for(theta = theta1; theta <= theta2; theta += step) { sphere[vx_c].x = r*cos(phi)*cos(theta); sphere[vx_c].y = r*sin(phi); sphere[vx_c].z = r*cos(phi)*sin(theta); vx_c++; } printf("num: %f, vx_c %d\n",num_points,vx_c); return sphere; } // Draw a sphere with points respect Y axis void sphere_points(float r,float step) { GLfloat x,y,z,theta,phi; glColor3f (1.0, 1.0, 1.0); glBegin(GL_POINTS); for(phi = (-0.5*GL_PI); phi <= (0.5*GL_PI); phi +=step) for(theta = -1.0*GL_PI; theta <= (GL_PI); theta += step) { x = r*cos(phi)*cos(theta); y = r*sin(phi); z = r*cos(phi)*sin(theta); glVertex3f(x, y, z); } glEnd(); } // Draw a sphere with polygons respect Y axis void sphere_poly(float r,float step) { GLfloat theta,phi; wcPt3D vert[4]; glColor3f (1.0, 0, 0); GLfloat step_a[]={0.0,step,step, 0.0}; GLfloat step_b[]={0.0, 0.0,step,step}; for(phi = (-0.5*GL_PI); phi <= (0.5*GL_PI); phi +=step) for(theta = -1.0*GL_PI; theta <= (GL_PI); theta += step) { glBegin(GL_POLYGON); for (int i=0; i<4; i++) { if (smooth_color_on) glColor3f (.5+cos(phi+step_a[i])*.5, 0, .5+cos(theta+step_b[i])*.5); //Use this for smooth coloring of polygons else glColor3f (.5+cos(phi)*.5, 0, .5+cos(theta)*.5); //Use this for single-colored polygons vert[i].x = r*cos(phi+step_a[i])*cos(theta+step_b[i]); vert[i].y = r*sin(phi+step_a[i]); vert[i].z = r*cos(phi+step_a[i])*sin(theta+step_b[i]); glVertex3f(vert[i].x, vert[i].y, vert[i].z); } glEnd(); } } /**********************************************************************/ // Called to draw scene, adapted from [2] void RenderScene(void) { // Storeage for coordinates and angles // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Save matrix state and do the rotation glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); if (axis_on) draw_axis(); if (fill_poly==0) { glPolygonMode(GL_BACK,GL_LINE); glPolygonMode(GL_FRONT,GL_LINE); } else { //op_mode=1; glPolygonMode(GL_BACK,GL_FILL); glPolygonMode(GL_FRONT,GL_FILL); } GLfloat step = GL_PI/20.; GLfloat r=50.0; // GLfloat step=0.2; //printf(" p: %d\n",op_mode); if (op_mode==0) sphere_points(r,step); else sphere_poly(r,step); // Restore transformations glPopMatrix(); // Flush drawing commands glutSwapBuffers(); } // This function does any needed initialization on the rendering // context. from [2] void SetupRC() { // Black background glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); // Set drawing color to green glColor3f(0.0f, 1.0f, 0.0f); glEnable(GL_DEPTH_TEST); } // adapted from [2] void SpecialKeys(int key, int x, int y) { if(key == GLUT_KEY_UP) xRot-= 5.0f; if(key == GLUT_KEY_DOWN) xRot += 5.0f; if(key == GLUT_KEY_LEFT) yRot -= 5.0f; if(key == GLUT_KEY_RIGHT) yRot += 5.0f; glutPostRedisplay(); } // adapted from [2] void ChangeSize(int w, int h) { // Prevent a divide by zero if(h == 0) h = 1; // Set Viewport to window dimensions glViewport(0, 0, w, h); // Reset projection matrix stack glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Establish clipping volume (left, right, bottom, top, near, far) if (w <= h) glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange); else glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange); // Reset Model view matrix stack glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void display_commands() { cout << "Use the direction keys to rotate the sphere\n"; cout << "Keyboard Function:\n"; cout << " F: Toggle between displaying a filled polygon and wire polygon\n"; cout << " P: Toggle between displaying the sphere based in points or in polygons\n"; cout << " S: Toggle between smooth coloring and single-colored polygons\n"; cout << " A: Toggle between displaying axes and not displaying axes\n"; cout << " Q: quit the program\n"; cout << "\n"; } // adapted from [2] int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition (800, 200); glutInitWindowSize(winWidth, winHeight); display_commands(); glutCreateWindow("Points Example"); glutReshapeFunc(ChangeSize); glutKeyboardFunc (operations); glutSpecialFunc(SpecialKeys); glutDisplayFunc(RenderScene); SetupRC(); glutMainLoop(); return 0; }