Example 21

Example 21

Simple example that loads a ppm as a texture onto a quad.

ex_21/texture_demo.png

Source Code

texture_demo.cc:

// Peter Bui
// CSE 40166 Computer Graphics (Fall 2010)
// Example 21: texture demo 

#include "ppm.h"
 
#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 50.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  = 10.0;

static double   EyeX = 20.0;
static double   EyeY = 20.0;
static double   EyeZ = 20.0;

static GLubyte *ImageBuffer;
static size_t   ImageWidth;
static size_t   ImageHeight;
static GLuint   ImageTextureId;

// Register texture ------------------------------------------------------------

void
register_texture(GLuint *tid, GLubyte *buffer, size_t width, size_t height)
{
    glGenTextures(1, tid);
    glBindTexture(GL_TEXTURE_2D, *tid);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);                                                                                                                     
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
}

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

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

void
display()
{
    double width  = (GLdouble)ImageWidth/(GLdouble)ImageHeight;
    double height = 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);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, ImageTextureId);

    glColor3f(1.0, 1.0, 1.0);
    glBegin(GL_QUADS); {
        glTexCoord2f(0.0, 0.0);
        glVertex3f(-width, -height, 0.0);

        glTexCoord2f(1.0, 0.0);
        glVertex3f( width, -height, 0.0);

        glTexCoord2f(1.0, 1.0);
        glVertex3f( width,  height, 0.0);

        glTexCoord2f(0.0, 1.0);
        glVertex3f(-width,  height, 0.0);
    } glEnd();

    glutSwapBuffers();
}

// Reshape callback ------------------------------------------------------------

void
reshape(GLsizei nw, GLsizei nh)
{
    WindowWidth  = nw;
    WindowHeight = nh;
    
    glEnable(GL_DEPTH_TEST);

    glViewport(0, 0, WindowWidth, WindowHeight);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (GLdouble)WindowWidth/(GLdouble)WindowHeight, 1.0, 750.0);

    update_camera_location();
}

// 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_MIN ? CameraDistance - 0.5 : CAMERA_DISTANCE_MIN);
            break;
        case WHEEL_DOWN:
            CameraDistance = (CameraDistance < CAMERA_DISTANCE_MAX ? CameraDistance + 0.1 : 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;

    if (CameraLongitude < -90.0)
        CameraLongitude = -90.0;
    if (CameraLongitude > 90.0)
        CameraLongitude = 90.0;
    
    update_camera_location();
    
    MouseX = x;
    MouseY = y;
}

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

int
main(int argc, char *argv[])
{
    glutInit(&argc, argv);

    if (argc != 2) {
        fprintf(stderr, "use: texture_demo [ppmfile]\n");
        return EXIT_FAILURE;
    }

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(WindowWidth, WindowHeight);
    glutCreateWindow("simple texture demo");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutSpecialFunc(special);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);

    ppm_read(argv[1], &ImageBuffer, &ImageWidth, &ImageHeight);
    register_texture(&ImageTextureId, ImageBuffer, ImageWidth, ImageHeight);

    glutMainLoop();

    return (EXIT_SUCCESS);
}

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


Files