Example 14

Example 14

This OpenGL program displays a 3d geometric object: glutSolidSphere, glutSolidCube, glutSolidCone, glutSolidTorus, gluCylinder, gluDisk, gluPartialDisk. To scale the object use the up and down arrow keys. To rotate the object about the Y axis, use the left and right arrow keys. To switch among the objects, use F1 though F7. The camera uses the same arcball method as that in example 06.

ex_14/geodemo.png

Source Code

geodemo.cc:

// Peter Bui
// CSE 40166 Computer Graphics (Fall 2010)
// Example 14: geometric object demo 
 
#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   1.0
#define CAMERA_DISTANCE_MAX 100.0

enum {
    GEO_SPHERE,
    GEO_CUBE,
    GEO_CONE,
    GEO_TORUS,
/*
    GEO_DODECAHEDRON,
    GEO_OCTAHEDRON,
    GEO_TETRAHEDRON,
    GEO_ICOSAHEDRON,
    GEO_TEAPOT,
*/
    GEO_CYLINDER,
    GEO_DISK,
    GEO_PARTIAL_DISK,
    GEO_MAX
};

// 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  = 50.0;

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

static int GeoMode = GEO_SPHERE;
static double GeoScale = 1.0;
static double GeoOrientation = 0.0;

static bool GeoWired = false;

static GLUquadric *GeoQuadric = NULL;

// Update camera ---------------------------------------------------------------

void
update_camera_location()
{
    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[]  = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat ambient0[]  = { 0.2, 0.2, 0.2, 1.0 };
    GLfloat specular0[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat position0[] = { 100.0, 100.0, 100.0, 1.0 };

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);
    glLightfv(GL_LIGHT0, GL_POSITION, position0);

    glEnable(GL_COLOR_MATERIAL) ;
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

    glEnable(GL_NORMALIZE);
    glEnable(GL_SMOOTH);

    if (!GeoQuadric) {
        GeoQuadric = gluNewQuadric();
        gluQuadricOrientation(GeoQuadric, GLU_OUTSIDE);
        gluQuadricNormals(GeoQuadric, GLU_SMOOTH);
    }

    update_camera_location();
}

// Draw grid -------------------------------------------------------------------

void
draw_grid()
{
    glPushMatrix(); glPushAttrib(GL_LIGHTING_BIT); {
        glDisable(GL_LIGHTING);
        glColor3f(1.0, 1.0, 1.0);
        glScalef(5.0, 5.0, 5.0);
        for(int k = 0; k < 2; k++) {
            for(int i = -5; i < 6; i++) {
                glBegin(GL_LINE_STRIP); {
                    for(int j = -5; j < 6; j++)
                        glVertex3f(k == 0 ? i : j, 0, k == 0 ? j : i);
                } glEnd();
            }
        }

    } glPopAttrib(); glPopMatrix();
}

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

void
display()
{
    //GLfloat position0[] = { EyeX, EyeY, EyeZ, 1.0 };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(EyeX, EyeY, EyeZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    draw_grid();

    glPushMatrix();
    glRotatef(GeoOrientation, 0.0, 1.0, 0.0);
    glScalef(GeoScale, GeoScale, GeoScale);
    glColor3f(1.0, 0.0, 0.0);
                
    gluQuadricDrawStyle(GeoQuadric, (GeoWired ? GLU_LINE : GLU_FILL));

    switch (GeoMode) {
        case GEO_SPHERE:
            if (GeoWired) 
                glutWireSphere(1.0, 24, 24);
            else
                glutSolidSphere(1.0, 24, 24);
            break;
        case GEO_CUBE:
            if (GeoWired) 
                glutWireCube(2.0);
            else
                glutSolidCube(2.0);
            break;
        case GEO_CONE:
            if (GeoWired) 
                glutWireCone(1.0, 1.0, 24, 24);
            else
                glutSolidCone(1.0, 1.0, 24, 24);
            break;
        case GEO_TORUS:
            if (GeoWired) 
                glutWireTorus(0.5, 1.0, 24, 24);
            else
                glutSolidTorus(0.5, 1.0, 24, 24);
            break;
        case GEO_CYLINDER:
            gluCylinder(GeoQuadric, 1.0, 1.0, 2.0, 24, 24);
            break;
        case GEO_DISK:
            gluDisk(GeoQuadric, 0.5, 1.0, 24, 24);
            break;
        case GEO_PARTIAL_DISK:
            gluPartialDisk(GeoQuadric, 0.5, 1.0, 24, 24, 0.0, 180.0);
            break;
    }

    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)
{
    switch (key) {
        case 'q':
        case 'Q':
            exit(EXIT_SUCCESS);
            break;
        case 'w':
            GeoWired = !GeoWired;
            break;
    }
    
    glutPostRedisplay();
}

// Special callback -----------------------------------------------------------

void
special(int key, int x, int y)
{
    switch (key) {
        case GLUT_KEY_LEFT:  GeoOrientation -= 1.0; break;
        case GLUT_KEY_RIGHT: GeoOrientation += 1.0; break;
        case GLUT_KEY_UP:    GeoScale += 1.0; break;
        case GLUT_KEY_DOWN:  GeoScale -= 1.0; break;
        case GLUT_KEY_F1:    GeoMode = GEO_SPHERE; break;
        case GLUT_KEY_F2:    GeoMode = GEO_CUBE; break;
        case GLUT_KEY_F3:    GeoMode = GEO_CONE; break;
        case GLUT_KEY_F4:    GeoMode = GEO_TORUS; break;
        case GLUT_KEY_F5:    GeoMode = GEO_CYLINDER; break;
        case GLUT_KEY_F6:    GeoMode = GEO_DISK; break;
        case GLUT_KEY_F7:    GeoMode = GEO_PARTIAL_DISK; break;
    }
    
    glutPostRedisplay();
}

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

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

int
main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(WindowWidth, WindowHeight);
    glutCreateWindow("geodemo");
    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