/* 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 #include #include #include #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); }