glsmap/smap_buildsmap.c

 
/* Copyright (c) Mark J. Kilgard, 1998.  */
 
/* This program is freely distributable without licensing fees
   and is provided without guarantee or warrantee expressed or
   implied. This program is -not- in the public domain. */
 
/* smap_buildsmap.c - automatically builds sphere map */
 
#include <assert.h>
#include <stdio.h>
#include <glsmap.h>
#include <OpenGL/glu.h>
 
#include "glsmapint.h"
 
#if defined(GL_EXT_texture_object) && !defined(GL_VERSION_1_1)
#define glBindTexture(A,B)     glBindTextureEXT(A,B)
#endif
#if defined(GL_EXT_copy_texture) && !defined(GL_VERSION_1_1)
#define glCopyTexImage2D(A, B, C, D, E, F, G, H)    glCopyTexImage2DEXT(A, B, C, D, E, F, G, H)
#endif
 
static void
copyImageToTexture(SphereMap *smap,
                   GLuint texobj, int origin[2], int texdim)
{
        int isSmapTexObj = (texobj == smap->smapTexObj) ? 1 : 0;
        int genMipmapsFlag =
                isSmapTexObj ? SMAP_GENERATE_SMAP_MIPMAPS : SMAP_GENERATE_VIEW_MIPMAPS;
        static GLubyte pixels[256][256][3];  /* XXX fix me. */
 
    glBindTexture(GL_TEXTURE_2D, texobj);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
        GL_LINEAR);
        if (smap->flags & genMipmapsFlag) {
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                        GL_LINEAR_MIPMAP_LINEAR);
        } else {
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                GL_LINEAR);
        }
 
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    /* Clamp to avoid artifacts from wrap around in texture. */
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
        if (smap->flags & genMipmapsFlag) {
            glPixelStorei(GL_PACK_ALIGNMENT, 1);
                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                glReadPixels(origin[X], origin[Y], texdim, texdim,
                        GL_RGB, GL_UNSIGNED_BYTE, pixels);
                gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texdim, texdim,
                        GL_RGB, GL_UNSIGNED_BYTE, pixels);       
        } else {
                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                origin[X], origin[Y], texdim, texdim, 0);
        }
}
 
static struct {
    GLfloat angle;
    GLfloat x, y, z;
} faceInfo[6] = {
    {   0.0, +1.0,  0.0,  0.0 },  /* front */
    {  90.0, -1.0,  0.0,  0.0 },  /* top */
    {  90.0, +1.0,  0.0,  0.0 },  /* bottom */
    {  90.0,  0.0, -1.0,  0.0 },  /* left */
    {  90.0,  0.0, +1.0,  0.0 },  /* right */
    { 180.0, -1.0,  0.0,  0.0 }   /* back */
};
 
static void
configFace(SphereMap *smap, int view)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRotatef(faceInfo[view].angle,
        faceInfo[view].x, faceInfo[view].y, faceInfo[view].z);
    gluLookAt(smap->obj[X], smap->obj[Y], smap->obj[Z],  /* "eye" at object */
              smap->eye[X], smap->eye[Y], smap->eye[Z],  /* looking at eye */
              smap->up[X], smap->up[Y], smap->up[Z]);
}
 
static void
initGenViewTex(SphereMap *smap)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.0, 1.0, smap->viewNear, smap->viewFar);
    glViewport(smap->viewOrigin[X], smap->viewOrigin[Y],
        smap->viewTexDim, smap->viewTexDim);
    glScissor(0, 0, smap->viewTexDim, smap->viewTexDim);
    glEnable(GL_SCISSOR_TEST);
    glEnable(GL_DEPTH_TEST);
}
 
static void
genViewTex(SphereMap *smap, int view)
{
    configFace(smap, view);
        assert(smap->positionLights);
    smap->positionLights(view, smap->context);
        assert(smap->drawView);
    smap->drawView(view, smap->context);
}
 
void
smapGenViewTex(SphereMap *smap, int view)
{
    initGenViewTex(smap);
    genViewTex(smap, view);
    copyImageToTexture(smap, smap->viewTexObjs[view],
        smap->viewOrigin, smap->viewTexDim);
}
 
void
smapGenViewTexs(SphereMap *smap)
{
    int view;
 
    initGenViewTex(smap);
 
    for (view=0; view<6; view++) {
        genViewTex(smap, view);
        copyImageToTexture(smap, smap->viewTexObjs[view],
            smap->viewOrigin, smap->viewTexDim);
    }
}
 
void
drawSphereMapMesh(SphereMap *smap)
{
    int side;
 
    /* Calculate sphere map mesh if needed. */
    __smapValidateSphereMapMesh(smap->mesh);
 
    /* Five front and side faces. */
    for (side=0; side<5; side++) {
        /* Bind to texture for given face of cube map. */
        glBindTexture(GL_TEXTURE_2D, smap->viewTexObjs[side]);
        __smapDrawSphereMapMeshSide(smap->mesh, side);
    }
 
    /* Bind to texture for back face of cube map. */
    glBindTexture(GL_TEXTURE_2D, smap->viewTexObjs[side]);
    __smapDrawSphereMapMeshBack(smap->mesh);
}
 
void
initDrawSphereMapMesh(SphereMap *smap)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, 1, 0, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
        glViewport(smap->smapOrigin[X], smap->smapOrigin[Y],
        smap->smapTexDim, smap->smapTexDim);
 
        if (smap->flags & SMAP_CLEAR_SMAP_TEXTURE) {
            glClear(GL_COLOR_BUFFER_BIT);
        }
 
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glDisable(GL_CULL_FACE);
}
 
void
smapGenSphereMapFromViewTexs(SphereMap *smap)
{
    initDrawSphereMapMesh(smap);
    drawSphereMapMesh(smap);
 
    copyImageToTexture(smap, smap->smapTexObj,
        smap->smapOrigin, smap->smapTexDim);
}
 
void
smapGenSphereMap(SphereMap *smap)
{
    smapGenViewTexs(smap);
    smapGenSphereMapFromViewTexs(smap);
}
 
void
smapGenSphereMapWithOneViewTex(SphereMap *smap)
{
    int side;
 
    /* Make sure viewports are not obviously overlapping. */
    assert(smap->viewOrigin[X] != smap->smapOrigin[X]);
    assert(smap->viewOrigin[Y] != smap->smapOrigin[Y]);
 
    /* Calculate sphere map mesh if needed. */
    __smapValidateSphereMapMesh(smap->mesh);
 
    /* Five front and side faces. */
    for (side=0; side<5; side++) {
        initGenViewTex(smap);
        genViewTex(smap, side);
        copyImageToTexture(smap, smap->viewTexObj,
            smap->viewOrigin, smap->viewTexDim);
 
        /* Preceeding copyImageToTexture does bind to smap->viewTexObj */
 
        initDrawSphereMapMesh(smap);
        __smapDrawSphereMapMeshSide(smap->mesh, side);
    }
 
    initGenViewTex(smap);
    genViewTex(smap, SMAP_BACK);
    copyImageToTexture(smap, smap->viewTexObj,
            smap->viewOrigin, smap->viewTexDim);
 
    /* Preceeding copyImageToTexture does bind to smap->viewTexObj */
 
    initDrawSphereMapMesh(smap);
    __smapDrawSphereMapMeshBack(smap->mesh);
 
    copyImageToTexture(smap, smap->smapTexObj,
        smap->smapOrigin, smap->smapTexDim);
}