|
CS 371
|
Lecture 18: More OpenGL
Extra constanst and variables:
// current angle and change in angle
static const double deltaAngle = 1.0;
double angle = 0.0;
// The GLUT window idle callback function
void idle(void) {
// increment current angle
angle+=deltaAngle;
// and reset if too large
if(angle >= 360.00)
angle = 0.0;
// force a redraw!
glutPostRedisplay();
}
// At the end of display callback, swap buffers instead of flushing
void display(void) {
// We will do a local transform to the sphere
// First, make sure we have the correct matrix stack
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); // Now duplicate top of stack
// add a rotation to the modelview matrix
glRotated(angle,0.0,0.0,1.0); // Then rotate around z-axis
// Erase window, then redraw teapot
glClear(GL_COLOR_BUFFER_BIT);
// Draw a sphere of radius .5, with 10 longitude lines and 15 latitude lines
glutWireSphere(0.5,10,15);
glPopMatrix(); // first get rid of local transform
glutSwapBuffers(); // swap buffer to screen; no glFlush() necessary
}
// At the end of initWindowInfo, register the idle callback
void initWindowInfo(void) {
...
glutIdleFunc(idle);
}
// in main, request double buffering
int main(int argc, char** argv) {
glutInit(&argc, argv);
// use double-buffering for smoother animation
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(VIEWPORTWIDTH, VIEWPORTHEIGHT);
glutInitWindowPosition(CORNER_X, CORNER_Y);
...
}
glutCreateMenu(menu_callback_func)
// Variables
// Animation state
bool isAnimated = true;
// The GLUT window mouse callback function
void mouse(int button, int state, int x, int y) {
// am I pressing the left mouse button
if(state == GLUT_DOWN && button == GLUT_LEFT_BUTTON) {
if (isAnimated)
glutIdleFunc(NULL); // turn off animation
else
glutIdleFunc(idle); // turn on animation
isAnimated=!isAnimated;// change state
}
}
// Don't forget to register mouse callback
void initWindowInfo(void) {
...
glutMouseFunc(mouse);
}
// Constants and variables...
// Menu item constants
enum {SLOW_ITEM, MEDIUM_ITEM, FAST_ITEM, QUIT_ITEM};
// Menu callback: choice is value of the chosen menu entry
void menu(int choice) {
switch(choice) {
case SLOW_ITEM:
deltaAngle=.5;
break;
case MEDIUM_ITEM:
deltaAngle=1;
break;
case FAST_ITEM:
deltaAngle=2;
break;
case QUIT_ITEM:
exit(0);
break;
default:
break;
}
}
// Create the menu, add the items, and attach to the mouse button
void initWindowInfo(void) {
... //other initWindow code
...
// create menu
glutCreateMenu(menu); // simultaneously registers callback
// add entries: 2nd parameter is value returned when entry is selected
glutAddMenuEntry("Slow",SLOW_ITEM);
glutAddMenuEntry("Medium",MEDIUM_ITEM);
glutAddMenuEntry("Fast",FAST_ITEM);
glutAddMenuEntry("Quit",QUIT_ITEM);
// attach button to menu: overrides mouse callback for MIDDLE button
glutAttachMenu(GLUT_MIDDLE_BUTTON);
}
// state variables
bool isSphere = true;
// The GLUT window keyboard callback function
void keyboard(unsigned char key, int x, int y) {
// we don't care where the mouse is, so ignore x & y
// Use 's' for toggling shape
if(key == 's')
isSphere = !isSphere;
}
// The display method checks ``isSphere''
void display(void) {
// We will do a local transform to the sphere
// First, make sure we have the correct matrix stack
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); // Now duplicate top of stack
// add a rotation to the modelview matrix
glRotated(angle,0.0,0.0,1.0); // Then rotate around z-axis
// Erase window, then redraw teapot
glClear(GL_COLOR_BUFFER_BIT);
// Draw current state
if(isSphere)
// sphere of radius .5, with 10 longitude lines and 15 latitude lines
glutWireSphere(0.5,10,15);
else
// torus of radii .25 and .5, with 10 longitude and 15 latitude lines
glutWireTorus(0.25,0.5,10,15);
glPopMatrix(); // first get rid of local transform
glutSwapBuffers(); // swap buffer to screen; no glFlush() necessary
}
// Don't forget to register keyboard callback
void initWindowInfo(void) {
...
glutKeyboardFunc(keyboard);
}
// current angle and change in angle (used for all revolutions)
double deltaAngle = 1.0;
double angle = 0.0;
// state variables
bool isAnimated = true;
// celestial body info
double sunRadius = 0.5;
double planetRadius = 0.1;
double distanceToSun = 2.0;
Point3Dd sunAxis(1,3,1);
Point3Dd planetAxis(1,1,1);
// OpenGL wants its transforms as 1-D arrays in COLUMN-MAJOR order
double* sunTrans;
double* planetTrans;
// A transform that rotates vector (0,0,1) to vector dir about (0,0,1) x dir
Transform4Dd rotateToAxis(const Point3Dd& dir) {
Point3Dd axis = dir;
axis.normalize();
Point3Dd zAxis(0,0,1);
Point3Dd cross = zAxis.cross(axis);
cross.normalize();
return MakeRotation(acos(zAxis.dot(axis)),cross);
}
// set up sun and planet transforms and convert to openGL format
// Note: GetArray returns matrices in COLUMN-MAJOR order
void initUniverse() {
sunTrans= GetArray(rotateToAxis(sunAxis));
// note order of multiplication!
planetTrans = GetArray(MakeTranslation(0,0,distanceToSun)*
rotateToAxis(planetAxis));
}
// The GLUT window keyboard callback function
void keyboard(unsigned char key, int x, int y) {
// we don't care where the mouse is, so ignore x & y
Point3Dd dir = eye - lookAt;
dir.normalize();
switch(key) {
case 'o' : // zoom out
eye+=dir;
lookAt+=dir;
break;
case 'i' : // zoom in
eye-=dir;
lookAt-=dir;
break;
}
// Reset the camera here, since we never adjust the camera
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye.x, eye.y, eye.z,
lookAt.x, lookAt.y, lookAt.z,
up.x, up.y, up.z);
}
// The GLUT window display callback function
// Note: transforms that change over time are computed here
void display(void) {
// We will do a local transform to the sphere
// First, make sure we have the correct matrix stack
glMatrixMode(GL_MODELVIEW);
// Erase window
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix(); // Now duplicate top of stack
// Sun's location affects planet
glTranslated(sunLocation.x, sunLocation.y, sunLocation.z);
glPushMatrix(); // but it's orientation and spin don't affect planet
glMultMatrixd(sunTrans);
glRotated(angle,0,0,1); // done here since angle keeps changing
glutWireSphere(sunRadius,10,15);
glPopMatrix(); // remove sun's spin and orientation
// now add planet's transform
glPushMatrix();
glRotated(angle,orbitAxis.x,orbitAxis.y,orbitAxis.z); // orbit planet around sun
glMultMatrixd(planetTrans);
glRotated(angle,0,0,1); // done here since angle keeps changing
glutWireSphere(planetRadius,10,15);
glPopMatrix(); // first get rid of planet transform
glPopMatrix(); // now get rid of sun's location
glutSwapBuffers(); // swap buffer to screen; no glFlush() necessary
}