/* CPSC 360 Programming Assignment 6 * Solar System * by Chris Bolduc * boldu101@chapman.edu */ #include #include // Constants related to controls #define KEY_STRENGTH 0.1 // Key sensitivity when moving around #define INVERT_PITCH 1.0 // Set to -1.0 to disable // Misc constants #define SPHERE_DETAIL 40 // Multiplier for space between planets. Initially 1/1000 of the "real" size. #define PLANET_SPACE 0.001 // How much of the scene will be rendered. May want a lower value if you have // a slow computer. #define VIEW_DISTANCE 40.0 #define pi 3.1415926535897932384626433832795 // Prototypes void init(); void display(); void reshape(int w, int h); void keypress(unsigned char key, int x, int y); void drawAxis(); void drawPlanets(); void drawPlanet(float r, float g, float b, float angle, float dist_from_sun, float radius); // globals float mercury_orbit_angle = 0; float venus_orbit_angle = 0; float earth_orbit_angle = 0; float mars_orbit_angle = 0; float jupiter_orbit_angle = 0; float saturn_orbit_angle = 0; float uranus_orbit_angle = 0; float neptune_orbit_angle = 0; float pluto_orbit_angle = 0; float speed = 1.0; // Camera position and direction float camera_x = 0.0; float camera_y = 0.0; float camera_z = 25.0; float camera_theta = 0; float camera_pitch = 0; // 1 = freeze planets, 0 = don't int freeze_planets = 0; // Initialize the drawing area void init(){ glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); //glOrtho(-18.0, 18.0, -18.0, 18.0, -18.0, 18.0); } // Handles user menu calls. void menuFunction(int itemNum){ switch(itemNum){ case 1: camera_x = 0.0; camera_y = 0.0; camera_z = 25.0; camera_theta = 0.0; camera_pitch = 0.0; break; case 2: freeze_planets = abs(freeze_planets - 1); break; case 3: speed *= 2.0; break; case 4: speed /= 2.0; break; case 5: speed = 1.0; break; } glutPostRedisplay(); } // Display the scene void display(){ int i, view_x, view_y, view_z; glPushMatrix(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Camera offsets will be subtracted from current position // Remember that y is vertical and z is depth view_x = 5.0 * sin(camera_theta); view_y = camera_pitch; view_z = 5.0 * cos(camera_theta); gluLookAt(camera_x, camera_y, camera_z, camera_x - view_x, camera_y - view_y, camera_z - view_z, 0.0, 1.0, 0.0); glPushMatrix(); // Scale by 100,000 / (distance from sun to pluto) glScalef(0.0169104, 0.0169104, 0.0169104); drawPlanets(); glPopMatrix(); // This REALLY helps with debugging the controls //glutWireTeapot(3.0); drawAxis(); glPopMatrix(); glutSwapBuffers(); //glutPostRedisplay(); } // Draws the XYZ axis void drawAxis(){ glBegin(GL_LINES); // x is red glColor3f(1, 0, 0); glVertex3f(-100, 0, 0); glVertex3f(100, 0, 0); // y is green glColor3f(0, 1, 0); glVertex3f(0, -100, 0); glVertex3f(0, 100, 0); // z is blue glColor3f(0, 0, 1); glVertex3f(0, 0, -100); glVertex3f(0, 0, 100); glEnd(); } // Draws planets void drawPlanets(){ // Draw the Sun // Note that it is 1/10 of its "actual" scale size drawPlanet(1.0, 1.0, 0.0, 0, 0, 139.0); // Draw Mercury drawPlanet(1.0, 0.0, 0.0, mercury_orbit_angle, 157910, 4.880); // Draw Venus drawPlanet(1.0, 1.0, 0.0, venus_orbit_angle, 208200, 12.1036); // Draw Earth drawPlanet(0.0, 0.0, 1.0, earth_orbit_angle, 249600, 12.7563); // Draw Mars drawPlanet(1.0, 0.0, 0.0, mars_orbit_angle, 327940, 6.794); // Draw Jupiter drawPlanet(1.0, 0.5, 0.0, jupiter_orbit_angle, 578330, 152.984); // Draw Saturn drawPlanet(0.2, 0.2, 0.2, saturn_orbit_angle, 729400, 120536); // Draw Uranus drawPlanet(0.0, 0.0, 0.6, uranus_orbit_angle, 870990, 51.118); // Draw Neptune drawPlanet(0.0, 0.0, 8.0, neptune_orbit_angle, 1003903, 49.532); // Draw Pluto drawPlanet(0.3, 0.3, 0.3, pluto_orbit_angle, 1113520, 2.274); //glRotatef(orbit_angle * 2, 0.0, 1.0, 0.0); } // Draws planets using scale distances (doesn't work as well) //void drawPlanets(){ // // Draw the Sun // // Note that it is 1/10 of its "actual" scale size // drawPlanet(1.0, 1.0, 0.0, 0, 0, 13.90); // // // Draw Mercury // drawPlanet(1.0, 0.0, 0.0, mercury_orbit_angle, 57910, 4.880); // // // Draw Venus // drawPlanet(1.0, 1.0, 0.0, venus_orbit_angle, 108200, 12.1036); // // // Draw Earth // drawPlanet(0.0, 0.0, 1.0, earth_orbit_angle, 149600, 12.7563); // // // Draw Mars // drawPlanet(1.0, 0.0, 0.0, mars_orbit_angle, 227940, 6.794); // // // Draw Jupiter // drawPlanet(1.0, 0.5, 0.0, jupiter_orbit_angle, 778330, 152.984); // // // Draw Saturn // drawPlanet(0.2, 0.2, 0.2, saturn_orbit_angle, 1429400, 120536); // // // Draw Uranus // drawPlanet(0.0, 0.0, 0.6, uranus_orbit_angle, 2870990, 51.118); // // // Draw Neptune // drawPlanet(0.0, 0.0, 8.0, neptune_orbit_angle, 4504000, 49.532); // // // Draw Pluto // drawPlanet(0.3, 0.3, 0.3, pluto_orbit_angle, 5913520, 2.274); // // //glRotatef(orbit_angle * 2, 0.0, 1.0, 0.0); //} // Parameters: // rgb = red, green, blue color values // angle = angle of orbit // dist_from_sun in megameters // radius in megameters void drawPlanet(float r, float g, float b, float angle, float dist_from_sun, float radius){ glColor3f(r, g, b); glPushMatrix(); if(!freeze_planets){ glRotatef(angle, 0.0, 1.0, 0.0); } glTranslatef(dist_from_sun * PLANET_SPACE, 0, 0); glutWireSphere(radius, SPHERE_DETAIL, SPHERE_DETAIL); glPopMatrix(); } // Adjusts viewing window when it is resized void reshape(int w, int h){ glViewport(0, 0, (GLsizei)w, (GLsizei)h); glDepthRange(0.0, 100.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, VIEW_DISTANCE); glMatrixMode(GL_MODELVIEW); } // Rotates the scene when idle void rotate(){ mercury_orbit_angle += 1.0 * speed; venus_orbit_angle += 0.7 * speed; earth_orbit_angle += 0.5 * speed; mars_orbit_angle += 0.3 * speed; jupiter_orbit_angle += 0.25 * speed; saturn_orbit_angle += 0.2 * speed; uranus_orbit_angle += 0.15 * speed; neptune_orbit_angle += 0.13 * speed; pluto_orbit_angle += 0.1 * speed; } // Rotate function based on real scales // (Doesn't work well) //void rotate(){ // mercury_orbit_angle += 1.0; // venus_orbit_angle += 0.26102845210127903941529626729313; // earth_orbit_angle += 0.16056518946692357096981374438022; // mars_orbit_angle += 0.085367935803312275909168516305276; // jupiter_orbit_angle += 0.013535646124067732373204834932796; // saturn_orbit_angle += 0.0054505417838533150195129395861949; // uranus_orbit_angle += 0.0019112200081800216350104925978449; // neptune_orbit_angle += 0.00097433883802298855054431439186154; // pluto_orbit_angle += 0.00064601820220886543699255270216494; //} void keypress(unsigned char key, int x, int y){ switch(key){ case 'W': case 'w': camera_z += -KEY_STRENGTH * cos(camera_theta); camera_x += -KEY_STRENGTH * sin(camera_theta); break; case 'S': case 's': camera_z += KEY_STRENGTH * cos(camera_theta); camera_x += KEY_STRENGTH * sin(camera_theta); break; case 'A': case 'a': camera_z += KEY_STRENGTH * cos(camera_theta - pi / 2); camera_x += KEY_STRENGTH * sin(camera_theta - pi / 2); break; case 'D': case 'd': camera_z += KEY_STRENGTH * cos(camera_theta + pi / 2); camera_x += KEY_STRENGTH * sin(camera_theta + pi / 2); break; case 'F': case 'f': camera_y += KEY_STRENGTH; break; case 'V': case 'v': camera_y += -KEY_STRENGTH; break; case 'J': case 'j': camera_theta += 2 * KEY_STRENGTH; if(camera_theta >= 2 * pi){ camera_theta = 0.0; } break; case 'L': case 'l': camera_theta += 2 * -KEY_STRENGTH; if(camera_theta >= 2 * pi){ camera_theta = 0.0; } break; case 'I': case 'i': camera_pitch += INVERT_PITCH * 10 * KEY_STRENGTH; break; case 'K': case 'k': camera_pitch += INVERT_PITCH * 10 * -KEY_STRENGTH; break; } } int main(int argc, char* argv[]){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("Cubestraveganza!"); init(); glutCreateMenu(menuFunction); glutAddMenuEntry("Reset view", 1); glutAddMenuEntry("(Un)Freeze Planets", 2); glutAddMenuEntry("Speed up 2x", 3); glutAddMenuEntry("Slow down 1/2x", 4); glutAddMenuEntry("Normal speed", 5); glutAttachMenu(GLUT_RIGHT_BUTTON); glutDisplayFunc(display); glutReshapeFunc(reshape); glutIdleFunc(rotate); glutKeyboardFunc(keypress); glutMainLoop(); return 0; }