llcubemap.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 #include "llfeaturemanager.h"
00034 #include "llworkerthread.h"
00035 
00036 #include "llcubemap.h"
00037 
00038 #include "v4coloru.h"
00039 #include "v3math.h"
00040 
00041 #include "llviewercamera.h"
00042 #include "llviewerimage.h"
00043 #include "llviewerimagelist.h"
00044 
00045 #include "llglheaders.h"
00046 
00047 const F32 epsilon = 1e-7f;
00048 const U16 RESOLUTION = 64;
00049 
00050 #if LL_DARWIN
00051 // mipmap generation on cubemap textures seems to be broken on the Mac for at least some cards.
00052 // Since the cubemap is small (64x64 per face) and doesn't have any fine detail, turning off mipmaps is a usable workaround.
00053 const BOOL use_cube_mipmaps = FALSE;
00054 #else
00055 const BOOL use_cube_mipmaps = FALSE;  //current build works best without cube mipmaps
00056 #endif
00057 
00058 LLCubeMap::LLCubeMap()
00059         : mTextureStage(0),
00060           mMatrixStage(0)
00061 {
00062 }
00063 
00064 LLCubeMap::~LLCubeMap()
00065 {
00066 }
00067 
00068 void LLCubeMap::initGL()
00069 {
00070         llassert(gGLManager.mInited);
00071 
00072         if (gGLManager.mHasCubeMap
00073             && gFeatureManagerp->isFeatureAvailable("RenderCubeMap"))
00074         {
00075                 mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
00076                 mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
00077                 mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
00078                 mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
00079                 mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
00080                 mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
00081                 
00082                 // Not initialized, do stuff.
00083                 if (mImages[0].isNull())
00084                 {
00085                         GLuint texname = 0;
00086                         
00087                         glGenTextures(1, &texname);
00088 
00089                         for (int i = 0; i < 6; i++)
00090                         {
00091                                 mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
00092                                 mImages[i]->setTarget(mTargets[i], GL_TEXTURE_CUBE_MAP_ARB);
00093                                 mRawImages[i] = new LLImageRaw(64, 64, 4);
00094                                 mImages[i]->createGLTexture(0, mRawImages[i], texname);
00095                                 
00096                                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texname);
00097                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00098                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00099                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00100                                 stop_glerror();
00101                         }
00102                 }
00103                 disable();
00104         }
00105         else
00106         {
00107                 llwarns << "Using cube map without extension!" << llendl
00108         }
00109 }
00110 
00111 void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages)
00112 {
00113         bool flip_x[6] =        { false, true,  false, false, true,  false };
00114         bool flip_y[6] =        { true,  true,  true,  false, true,  true  };
00115         bool transpose[6] = { false, false, false, false, true,  true  };
00116         
00117         // Yes, I know that this is inefficient! - djs 08/08/02
00118         for (int i = 0; i < 6; i++)
00119         {
00120                 const U8 *sd = rawimages[i]->getData();
00121                 U8 *td = mRawImages[i]->getData();
00122 
00123                 S32 offset = 0;
00124                 S32 sx, sy, so;
00125                 for (int y = 0; y < 64; y++)
00126                 {
00127                         for (int x = 0; x < 64; x++)
00128                         {
00129                                 sx = x;
00130                                 sy = y;
00131                                 if (flip_y[i])
00132                                 {
00133                                         sy = 63 - y;
00134                                 }
00135                                 if (flip_x[i])
00136                                 {
00137                                         sx = 63 - x;
00138                                 }
00139                                 if (transpose[i])
00140                                 {
00141                                         S32 temp = sx;
00142                                         sx = sy;
00143                                         sy = temp;
00144                                 }
00145 
00146                                 so = 64*sy + sx;
00147                                 so *= 4;
00148                                 *(td + offset++) = *(sd + so++);
00149                                 *(td + offset++) = *(sd + so++);
00150                                 *(td + offset++) = *(sd + so++);
00151                                 *(td + offset++) = *(sd + so++);
00152                         }
00153                 }
00154         }
00155 }
00156 
00157 void LLCubeMap::initGLData()
00158 {
00159         for (int i = 0; i < 6; i++)
00160         {
00161                 mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64);
00162         }
00163 }
00164 
00165 void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
00166 {
00167         if (!gGLManager.mIsDisabled)
00168         {
00169                 initGL();
00170                 initRawData(rawimages);
00171                 initGLData();
00172         }
00173 }
00174 
00175 GLuint LLCubeMap::getGLName()
00176 {
00177         return mImages[0]->getTexName();
00178 }
00179 
00180 void LLCubeMap::bind()
00181 {
00182         if (gGLManager.mHasCubeMap
00183             //&& gFeatureManagerp->isFeatureAvailable("RenderCubeMap")
00184             )
00185         {
00186                 // We assume that if they have cube mapping, they have multitexturing.
00187                 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
00188                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mImages[0]->getTexName());
00189 
00190                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00191                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, (use_cube_mipmaps? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
00192         }
00193         else
00194         {
00195                 llwarns << "Using cube map without extension!" << llendl
00196         }
00197 }
00198 
00199 void LLCubeMap::enable(S32 stage)
00200 {
00201         mTextureStage = stage;
00202         if (gGLManager.mHasCubeMap &&
00203             stage >= 0
00204             //&& gFeatureManagerp->isFeatureAvailable("RenderCubeMap")
00205             )
00206         {
00207                 glActiveTextureARB(GL_TEXTURE0_ARB + stage); // NOTE: leaves texture stage set
00208                 
00209                 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
00210                 glEnable(GL_TEXTURE_GEN_R);
00211                 glEnable(GL_TEXTURE_GEN_S);
00212                 glEnable(GL_TEXTURE_GEN_T);
00213 
00214                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
00215                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
00216                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
00217         }
00218 }
00219 
00220 void LLCubeMap::disable()
00221 {
00222         if (gGLManager.mHasCubeMap && mTextureStage >= 0
00223             //&& gFeatureManagerp->isFeatureAvailable("RenderCubeMap")
00224             )
00225         {
00226                 glActiveTextureARB(GL_TEXTURE0_ARB + mTextureStage);
00227                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
00228                 glDisable(GL_TEXTURE_GEN_S);
00229                 glDisable(GL_TEXTURE_GEN_T);
00230                 glDisable(GL_TEXTURE_GEN_R);
00231                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
00232         }
00233 }
00234 
00235 void LLCubeMap::setMatrix(S32 stage)
00236 {
00237         mMatrixStage = stage;
00238         glActiveTextureARB(GL_TEXTURE0_ARB+stage);
00239 
00240         LLVector3 x(LLVector3d(gGLModelView+0));
00241         LLVector3 y(LLVector3d(gGLModelView+4));
00242         LLVector3 z(LLVector3d(gGLModelView+8));
00243 
00244         LLMatrix3 mat3;
00245         mat3.setRows(x,y,z);
00246         LLMatrix4 trans(mat3);
00247         trans.transpose();
00248 
00249         glMatrixMode(GL_TEXTURE);
00250         glPushMatrix();
00251         glLoadMatrixf((F32 *)trans.mMatrix);
00252         glMatrixMode(GL_MODELVIEW);
00253 }
00254 
00255 void LLCubeMap::restoreMatrix()
00256 {
00257         glActiveTextureARB(GL_TEXTURE0_ARB+mMatrixStage);
00258         glMatrixMode(GL_TEXTURE);
00259         glPopMatrix();
00260         glMatrixMode(GL_MODELVIEW);
00261 }
00262 
00263 LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
00264 {
00265         LLVector3 dir;
00266 
00267         const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
00268         const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
00269         const U8 i_coef = (curr_coef + 1) % 3;
00270         const U8 j_coef = (i_coef + 1) % 3;
00271 
00272         dir.mV[curr_coef] = side_dir;
00273 
00274         switch (side)
00275         {
00276         case 0: // negative X
00277                 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00278                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00279                 break;
00280         case 1: // positive X
00281                 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00282                 dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
00283                 break;
00284         case 2: // negative Y
00285                 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00286                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00287                 break;
00288         case 3: // positive Y
00289                 dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
00290                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00291                 break;
00292         case 4: // negative Z
00293                 dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
00294                 dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00295                 break;
00296         case 5: // positive Z
00297                 dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
00298                 dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
00299                 break;
00300         default:
00301                 dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
00302                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00303         }
00304 
00305         dir.normVec();
00306         return dir;
00307 }
00308 
00309 
00310 BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
00311                                                 U8 side, const LLVector3& dir) const
00312 {
00313         const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
00314         const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
00315         const U8 i_coef = (curr_coef + 1) % 3;
00316         const U8 j_coef = (i_coef + 1) % 3;
00317 
00318         outside = TRUE;
00319         if (side_dir * dir.mV[curr_coef] < 0)
00320                 return FALSE;
00321 
00322         LLVector3 ray;
00323 
00324         F32 norm_val = fabs(dir.mV[curr_coef]);
00325 
00326         if (norm_val < epsilon)
00327                 norm_val = 1e-5f;
00328 
00329         ray.mV[curr_coef] = side_dir;
00330         ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
00331         ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
00332 
00333 
00334         const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
00335         const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
00336 
00337         switch (side)
00338         {
00339         case 0: // negative X
00340                 v_val = RESOLUTION - i_val;
00341                 h_val = j_val;
00342                 break;
00343         case 1: // positive X
00344                 v_val = RESOLUTION - i_val;
00345                 h_val = RESOLUTION - j_val;
00346                 break;
00347         case 2: // negative Y
00348                 v_val = RESOLUTION - i_val;
00349                 h_val = j_val;
00350                 break;
00351         case 3: // positive Y
00352                 v_val = i_val;
00353                 h_val = j_val;
00354                 break;
00355         case 4: // negative Z
00356                 v_val = RESOLUTION - j_val;
00357                 h_val = RESOLUTION - i_val;
00358                 break;
00359         case 5: // positive Z
00360                 v_val = RESOLUTION - j_val;
00361                 h_val = i_val;
00362                 break;
00363         default:
00364                 v_val = i_val;
00365                 h_val = j_val;
00366         }
00367 
00368         outside =  ((v_val < 0) || (v_val > RESOLUTION) ||
00369                 (h_val < 0) || (h_val > RESOLUTION));
00370 
00371         return TRUE;
00372 }
00373 
00374 BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max, 
00375                                                 U8 side, LLVector3 dir[4]) const
00376 {
00377         v_min = h_min = RESOLUTION;
00378         v_max = h_max = 0;
00379 
00380         BOOL fully_outside = TRUE;
00381         for (U8 vtx = 0; vtx < 4; ++vtx)
00382         {
00383                 F32 v_val, h_val;
00384                 BOOL outside;
00385                 BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
00386                 if (!outside)
00387                         fully_outside = FALSE;
00388                 if (consider)
00389                 {
00390                         if (v_val < v_min) v_min = v_val;
00391                         if (v_val > v_max) v_max = v_val;
00392                         if (h_val < h_min) h_min = h_val;
00393                         if (h_val > h_max) h_max = h_val;
00394                 }
00395         }
00396 
00397         v_min = llmax(0.0f, v_min);
00398         v_max = llmin(RESOLUTION - epsilon, v_max);
00399         h_min = llmax(0.0f, h_min);
00400         h_max = llmin(RESOLUTION - epsilon, h_max);
00401 
00402         return !fully_outside;
00403 }
00404 
00405 
00406 void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
00407 {
00408         F32 v_min, v_max, h_min, h_max;
00409         LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
00410         center.normVec();
00411 
00412         for (U8 side = 0; side < 6; ++side)
00413         {
00414                 if (!project(v_min, v_max, h_min, h_max, side, dir))
00415                         continue;
00416 
00417                 U8 *td = mRawImages[side]->getData();
00418                 
00419                 U16 v_minu = (U16) v_min;
00420                 U16 v_maxu = (U16) (ceil(v_max) + 0.5);
00421                 U16 h_minu = (U16) h_min;
00422                 U16 h_maxu = (U16) (ceil(h_max) + 0.5);
00423 
00424                 for (U16 v = v_minu; v < v_maxu; ++v)
00425                         for (U16 h = h_minu; h < h_maxu; ++h)
00426                 //for (U16 v = 0; v < RESOLUTION; ++v)
00427                 //      for (U16 h = 0; h < RESOLUTION; ++h)
00428                         {
00429                                 const LLVector3 ray = map(side, v, h);
00430                                 if (ray * center > 0.999)
00431                                 {
00432                                         const U32 offset = (RESOLUTION * v + h) * 4;
00433                                         for (U8 cc = 0; cc < 3; ++cc)
00434                                                 td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
00435                                 }
00436                         }
00437                 mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64);
00438         }
00439 }
00440 
00441 void LLCubeMap::destroyGL()
00442 {
00443         for (S32 i = 0; i < 6; i++)
00444         {
00445                 mImages[i] = NULL;
00446         }
00447 }

Generated on Thu Jul 1 06:08:23 2010 for Second Life Viewer by  doxygen 1.4.7