This OpenGL program displays the sun, earth, and moon as cubes and animates them so that the sun rotates in the middle, the earth spins on its axis and revolves around the sun, and the moon spins and revolves around the earth. The camera uses the same arcball method as that in example 06.
orbit.cc:
// Peter Bui
// CSE 40166 Computer Graphics (Fall 2010)
// Example 12: orbit
#include <cmath>
#include <cstdio>
#include <cstdlib>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#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