/* * ACM/SIGGRAPH University of Michigan Student Chapter * OpenGL Workshop * * Rendering 3D Objects in OpenGL * * This program demonstrate rendering some simple 3D objects in OpenGL. * It does this both using individual calls to glVertex and using vertex * arrays. * */ #include #include #include using namespace std; /* Constants */ const double PI = acos(-1.0); /* Global Variables */ GLfloat rho = 2.5; GLfloat phi = 45 * (PI/180); GLfloat theta = 45 * (PI/180); /* Function Prototypes */ bool initOpenGL(); // GLUT Callback Functions: void reshape(int new_width, int new_height); void display(); void key(unsigned char key, int x, int y); // Some drawing functions: void myDrawCube(float side_length); void myDrawCone(float radius, float height, int slices); void myDrawSphere(float radius, int stacks, int slices); int main(int argc, char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutCreateWindow("Drawing 3D Objects in OpenGL"); glutReshapeFunc(reshape); glutDisplayFunc(display); glutKeyboardFunc(key); initOpenGL(); glutMainLoop(); } bool initOpenGL(){ cout << "OpenGL Vender:\t\t" << glGetString(GL_VENDOR) << endl; cout << "OpenGL Renderer:\t" << glGetString(GL_RENDERER) << endl; cout << "OpenGL Version:\t\t" << glGetString(GL_VERSION) << endl; glEnable(GL_DEPTH_TEST); // Call our reshape function to setup the viewport and projection matrix: // (Actually we don't need to do this, the GLUT does it for us) // reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)); return true; } void reshape(int new_width, int new_height){ glViewport(0, 0, new_width, new_height); // Setup the projeciton matrix: glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( 60.0, // Field of view in degrees // Calculate the aspect ratio from the width and height of the window: static_cast(new_width)/static_cast(new_height), // Aspect ratio 1.0, // Position of near clipping plane 10.0); // Position of far clipping plane } void display(){ // Set our clear color: glClearColor(0.0, 0.0, 0.0, 0.0); // Clear the previously drawn scene: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Draw the new scene: glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Setup the model view matrix: glLoadIdentity(); gluLookAt(// Position the camera's eye based on current angles and distance: -rho*sin(theta)*sin(phi), rho*cos(theta), -rho*sin(theta)*cos(phi), 0.0, 0.0, 0.0, // Set the center of the scene to be at (0,0,0) 0.0, 1.0, 0.0); // Set the up vector of the camera to the positive Y direction glColor3f(1.0, 0.0, 0.0); myDrawCube(1.0); glColor3f(0.0, 1.0, 0.0); glTranslatef(1.0, 0.0, 0.0); myDrawCone(0.5, 1.0, 10); glColor3f(0.0, 0.0, 1.0); glTranslatef(-2.0, 0.0, 0.0); glutSolidSphere(0.5, 10, 10); myDrawSphere(1.0, 10, 10); glPopMatrix(); glutSwapBuffers(); } void key(unsigned char key, int x, int y){ switch(key){ // Left and right rotation: case '4': phi = fmod(phi - 0.1, 2*PI); break; case '6': phi = fmod(phi + 0.1, 2*PI); break; // Up and down rotation: case '2': theta += 0.1; theta = (theta > (PI-0.1))? PI - 0.1 : theta; break; case '8': theta -= 0.1; theta = (theta < 0.1)? 0.1 : theta; break; // Zoom in and out: case '1': rho -= 0.1; rho = (rho < 0)? 0 : rho; break; case '5': rho += 0.1; break; } glutPostRedisplay(); } void myDrawCube(float side_length){ // Draws a simple cube with side length equal to side_length at the origin. // Compute half the side length (hsl => half side length): float hsl = 0.5 * side_length; glFrontFace(GL_CW); glBegin(GL_QUADS); // The following labels are with respect to a coordinate system where // the y-axis is up/down, the x-axis is right/left, and the z-axis // is forward/backward (into/out of the screen). // Top (note that the vertices are in CCW order): glVertex3f(hsl, hsl, hsl); glVertex3f(-hsl, hsl, hsl); glVertex3f(-hsl, hsl, -hsl); glVertex3f(hsl, hsl, -hsl); // Bottom (note that the order of the verices changes because this quad // if facing down): glVertex3f(hsl, -hsl, hsl); glVertex3f(-hsl, -hsl, hsl); glVertex3f(-hsl, -hsl, -hsl); glVertex3f(hsl, -hsl, -hsl); // Left: glVertex3f(-hsl, hsl, hsl); glVertex3f(-hsl, -hsl, hsl); glVertex3f(-hsl, -hsl, -hsl); glVertex3f(-hsl, hsl, -hsl); // Right (agian, notice the order of the vertices has changed): glVertex3f(hsl, hsl, hsl); glVertex3f(hsl, hsl, -hsl); glVertex3f(hsl, -hsl, -hsl); glVertex3f(hsl, -hsl, hsl); // Front: glVertex3f(hsl, hsl, -hsl); glVertex3f(-hsl, hsl, -hsl); glVertex3f(-hsl, -hsl, -hsl); glVertex3f(hsl, -hsl, -hsl); // Back (agian, notice the order of the vertices has changed): glVertex3f(hsl, hsl, hsl); glVertex3f(hsl, -hsl, hsl); glVertex3f(-hsl, -hsl, hsl); glVertex3f(-hsl, hsl, hsl); glEnd(); } void myDrawCone(float radius, float height, int slices){ float half_height = 0.5 * height; GLfloat top_vertex[3] = {0.0, half_height, 0.0}; GLfloat bottom_center_vertex[3] = {0.0, -half_height, 0.0}; GLfloat prev_vertex[3] = {radius, -half_height, 0.0}; GLfloat cur_vertex[3] = {0.0, -half_height, 0.0}; glBegin(GL_TRIANGLES); for(double angle = ((2*PI)/slices); angle < 2*PI; angle += ((2*PI)/slices)){ // Compute x and z coordinates of current vertex: cur_vertex[0] = radius*cos(angle); cur_vertex[2] = radius*sin(angle); // Draw a side: glVertex3fv(top_vertex); glVertex3fv(prev_vertex); glVertex3fv(cur_vertex); // Draw a slice of the bottom: glVertex3fv(bottom_center_vertex); glVertex3fv(cur_vertex); glVertex3fv(prev_vertex); // Copy cur_vertex into prev_vertex: prev_vertex[0] = cur_vertex[0]; prev_vertex[2] = cur_vertex[2]; } // Draw the last side and bottom slice: cur_vertex[0] = radius; cur_vertex[2] = 0.0; glVertex3fv(top_vertex); glVertex3fv(prev_vertex); glVertex3fv(cur_vertex); glVertex3fv(bottom_center_vertex); glVertex3fv(cur_vertex); glVertex3fv(prev_vertex); glEnd(); } void myDrawSphere(float radius, int stacks, int slices){ // You write this... }