Example 06

Example 06

This OpenGL program display a 3D wireframe teapot and some axis and allows the user to use both the mouse and keyboard to move the camera in orbit around the teapot.

ex_06/teapot.png

Source Code

teapot.cc:

// Peter Bui
// CSE 40166 Computer Graphics (Fall 2010)
// Example 6: teapot
 
#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_MAX 100.0

// Global variables ------------------------------------------------------------

static size_t WindowWidth  = 640;
static size_t WindowHeight = 480;

static GLint  MouseX = 0;
static GLint  MouseY = 0;

static double CameraLatitude  = 5.0; 
static double CameraLongitude = 10.0;
static double CameraDistance  = 50.0;

static double EyeX = 50.0;
static double EyeY = 50.0;
static double EyeZ = 50.0;

// 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();
}

// Draw scene ------------------------------------------------------------------

void
draw_scene()
{
    glLoadIdentity();
    gluLookAt(EyeX, EyeY, EyeZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glLineWidth(4.0);
    glBegin(GL_LINES); {
        glColor3f(1.0, 0.0, 0.0); // X Axis
        glVertex3f(-CAMERA_DISTANCE_MAX, 0.0, 0.0);
        glVertex3f( CAMERA_DISTANCE_MAX, 0.0, 0.0);

        glColor3f(0.0, 1.0, 0.0); // Y Axis
        glVertex3f(0.0, -CAMERA_DISTANCE_MAX, 0.0);
        glVertex3f(0.0,  CAMERA_DISTANCE_MAX, 0.0);

        glColor3f(0.0, 0.0, 1.0); // Z Axis
        glVertex3f(0.0, 0.0, -CAMERA_DISTANCE_MAX);
        glVertex3f(0.0, 0.0,  CAMERA_DISTANCE_MAX);
    } glEnd();
    glPopAttrib();

    // Teapot
    glColor3f(1.0, 1.0, 1.0);
    glScalef(5.0, 5.0, 5.0);
    glutWireTeapot(1.0);
}

// 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);

    update_camera_location();
}

// Display callback ------------------------------------------------------------

void
display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    draw_scene();
    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);
}

// 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_MAX ? CameraDistance - 1.0 : -CAMERA_DISTANCE_MAX);
            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;
}

// Main execution --------------------------------------------------------------

int
main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(WindowWidth, WindowHeight);
    glutCreateWindow("teapot");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutSpecialFunc(special);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);

    init_scene();

    glutMainLoop();

    return (EXIT_SUCCESS);
}

// vim: sts=4 sw=4 ts=8 ft=cpp


Files