// Peter Bui // CSE 40166 Computer Graphics (Fall 2010) // Example 12: orbit #include #include #include #ifdef __APPLE__ #include #else #include #endif using namespace std; // Constants ------------------------------------------------------------------- #define WHEEL_UP 3 #define WHEEL_DOWN 4 #define CAMERA_DISTANCE_MIN 50.0 #define CAMERA_DISTANCE_MAX 500.0 // Global variables ------------------------------------------------------------ static size_t WindowWidth = 640; static size_t WindowHeight = 480; static GLint MouseX = 0; static GLint MouseY = 0; static double CameraLatitude = 45.0; static double CameraLongitude = 25.0; static double CameraDistance = 175.0; static double EyeX = -100.0; static double EyeY = 50.0; static double EyeZ = 100.0; static double SunAngle = 0.0; static double SunScale = 25.0; static double EarthRevAngle = 0.0; static double EarthSpinAngle = 0.0; static double EarthScale = 10.0; static double EarthDistance = 2.0 * SunScale; static double MoonRevAngle = 0.0; static double MoonSpinAngle = 0.0; static double MoonScale = 2.5; static double MoonDistance = 1.25 * EarthScale; static GLint FrameRate = 30; static bool AnimationOn = true; // Update camera --------------------------------------------------------------- void update_camera_location() { // Based on some magical math: // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_spherical_coordinates // and some help from Dr. John Stewman double L = CameraDistance * cos(M_PI*CameraLongitude/180.0); EyeX = L * -sin(M_PI*CameraLatitude/180.0); EyeY = CameraDistance * sin(M_PI*CameraLongitude/180.0); EyeZ = L * cos(M_PI*CameraLatitude/180.0); glutPostRedisplay(); } // Initialize scene ------------------------------------------------------------ void init_scene() { glEnable(GL_DEPTH_TEST); glViewport(0, 0, WindowWidth, WindowHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLdouble)WindowWidth/(GLdouble)WindowHeight, 1.0, 750.0); glMatrixMode(GL_MODELVIEW); GLfloat diffuse0[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat ambient0[] = { 0.7, 0.7, 0.7, 1.0 }; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0); glEnable(GL_COLOR_MATERIAL) ; glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); update_camera_location(); } // Display callback ------------------------------------------------------------ void display() { GLfloat position0[] = { EyeX, EyeY, EyeZ, 1.0 }; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLightfv(GL_LIGHT0, GL_POSITION, position0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(EyeX, EyeY, EyeZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // Sun cube glColor3f(0.9, 0.3, 0.0); glPushMatrix(); { glRotatef(SunAngle, 0.0, 1.0, 0.0); glScalef(SunScale, SunScale, SunScale); glutSolidCube(1.0); } glPopMatrix(); // Earth cube glColor3f(0.0, 0.4, 0.8); glPushMatrix(); { glRotatef(EarthRevAngle, 0.0, 1.0, 0.0); glTranslatef(EarthDistance, 0.0, EarthDistance); glPushMatrix(); { glRotatef(EarthSpinAngle, 0.0, 1.0, 0.0); glScalef(EarthScale, EarthScale, EarthScale); glutSolidCube(1.0); } glPopMatrix(); // Moon cube glColor3f(0.8, 0.8, 0.8); glPushMatrix(); { glRotatef(MoonRevAngle, 0.0, 1.0, 0.0); glTranslatef(MoonDistance, 0.0, MoonDistance); glRotatef(MoonSpinAngle, 0.0, 1.0, 0.0); glScalef(MoonScale, MoonScale, MoonScale); glutSolidCube(1.0); } glPopMatrix(); } glPopMatrix(); glutSwapBuffers(); } // Reshape callback ------------------------------------------------------------ void reshape(GLsizei nw, GLsizei nh) { WindowWidth = nw; WindowHeight = nh; init_scene(); } // Keyboard callback ----------------------------------------------------------- void keyboard(unsigned char key, int x, int y) { if (key == 'q' || key == 'Q') exit(EXIT_SUCCESS); if (key == ' ') AnimationOn = !AnimationOn; } // Special callback ----------------------------------------------------------- void special(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: CameraLatitude -= 1.0; break; case GLUT_KEY_RIGHT: CameraLatitude += 1.0; break; case GLUT_KEY_UP: CameraLongitude -= 1.0; break; case GLUT_KEY_DOWN: CameraLongitude += 1.0; break; } update_camera_location(); } // Mouse callback -------------------------------------------------------------- void mouse(int button, int state, int x, int y) { MouseX = x; MouseY = y; switch (button) { case WHEEL_UP: CameraDistance = (CameraDistance > CAMERA_DISTANCE_MIN ? CameraDistance - 1.0 : CAMERA_DISTANCE_MIN); break; case WHEEL_DOWN: CameraDistance = (CameraDistance < CAMERA_DISTANCE_MAX ? CameraDistance + 1.0 : CAMERA_DISTANCE_MAX); break; } update_camera_location(); } // Motion callback ------------------------------------------------------------- void motion(int x, int y) { CameraLatitude += 180.0*(double)(x - MouseX)/WindowWidth; CameraLongitude += 180.0*(double)(y - MouseY)/WindowHeight; update_camera_location(); MouseX = x; MouseY = y; } // Timer callback -------------------------------------------------------------- void timer(int value) { if (AnimationOn) { SunAngle = (SunAngle < 360.0 ? SunAngle + 1.0 : 1.0); EarthSpinAngle = (EarthSpinAngle < 360.0 ? EarthSpinAngle + 1.0 : 1.0); EarthRevAngle = (EarthRevAngle < 360.0 ? EarthRevAngle + 2.0 : 1.0); MoonSpinAngle = (MoonSpinAngle < 360.0 ? MoonSpinAngle + 2.0 : 1.0); MoonRevAngle = (MoonRevAngle < 360.0 ? MoonRevAngle + 4.0 : 1.0); } glutPostRedisplay(); glutTimerFunc(1000/FrameRate, timer, 0); } // Main execution -------------------------------------------------------------- int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow("orbit"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(special); glutMouseFunc(mouse); glutMotionFunc(motion); glutTimerFunc(1000/FrameRate, timer, 0); init_scene(); glutMainLoop(); return (EXIT_SUCCESS); } // vim: sts=4 sw=4 ts=8 ft=cpp