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           mTextureCoordStage(0),
00061           mMatrixStage(0)
00062 {
00063 }
00064 
00065 LLCubeMap::~LLCubeMap()
00066 {
00067 }
00068 
00069 void LLCubeMap::initGL()
00070 {
00071         llassert(gGLManager.mInited);
00072 
00073         if (gGLManager.mHasCubeMap
00074             && LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"))
00075         {
00076                 mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
00077                 mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
00078                 mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
00079                 mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
00080                 mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
00081                 mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
00082                 
00083                 // Not initialized, do stuff.
00084                 if (mImages[0].isNull())
00085                 {
00086                         GLuint texname = 0;
00087                         
00088                         glGenTextures(1, &texname);
00089 
00090                         for (int i = 0; i < 6; i++)
00091                         {
00092                                 mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
00093                                 mImages[i]->setTarget(mTargets[i], GL_TEXTURE_CUBE_MAP_ARB);
00094                                 mRawImages[i] = new LLImageRaw(64, 64, 4);
00095                                 mImages[i]->createGLTexture(0, mRawImages[i], texname);
00096                                 
00097                                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texname);
00098                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00099                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00100                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
00101                                 stop_glerror();
00102                         }
00103                 }
00104                 disable();
00105         }
00106         else
00107         {
00108                 llwarns << "Using cube map without extension!" << llendl
00109         }
00110 }
00111 
00112 void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages)
00113 {
00114         bool flip_x[6] =        { false, true,  false, false, true,  false };
00115         bool flip_y[6] =        { true,  true,  true,  false, true,  true  };
00116         bool transpose[6] = { false, false, false, false, true,  true  };
00117         
00118         // Yes, I know that this is inefficient! - djs 08/08/02
00119         for (int i = 0; i < 6; i++)
00120         {
00121                 const U8 *sd = rawimages[i]->getData();
00122                 U8 *td = mRawImages[i]->getData();
00123 
00124                 S32 offset = 0;
00125                 S32 sx, sy, so;
00126                 for (int y = 0; y < 64; y++)
00127                 {
00128                         for (int x = 0; x < 64; x++)
00129                         {
00130                                 sx = x;
00131                                 sy = y;
00132                                 if (flip_y[i])
00133                                 {
00134                                         sy = 63 - y;
00135                                 }
00136                                 if (flip_x[i])
00137                                 {
00138                                         sx = 63 - x;
00139                                 }
00140                                 if (transpose[i])
00141                                 {
00142                                         S32 temp = sx;
00143                                         sx = sy;
00144                                         sy = temp;
00145                                 }
00146 
00147                                 so = 64*sy + sx;
00148                                 so *= 4;
00149                                 *(td + offset++) = *(sd + so++);
00150                                 *(td + offset++) = *(sd + so++);
00151                                 *(td + offset++) = *(sd + so++);
00152                                 *(td + offset++) = *(sd + so++);
00153                         }
00154                 }
00155         }
00156 }
00157 
00158 void LLCubeMap::initGLData()
00159 {
00160         for (int i = 0; i < 6; i++)
00161         {
00162                 mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64);
00163         }
00164 }
00165 
00166 void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
00167 {
00168         if (!gGLManager.mIsDisabled)
00169         {
00170                 initGL();
00171                 initRawData(rawimages);
00172                 initGLData();
00173         }
00174 }
00175 
00176 GLuint LLCubeMap::getGLName()
00177 {
00178         return mImages[0]->getTexName();
00179 }
00180 
00181 void LLCubeMap::bind()
00182 {
00183         if (gGLManager.mHasCubeMap
00184             //&& LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap")
00185             )
00186         {
00187                 // We assume that if they have cube mapping, they have multitexturing.
00188                 if (mTextureStage > 0)
00189                 {
00190                         glActiveTextureARB(GL_TEXTURE0_ARB + mTextureStage);
00191                 }
00192                 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
00193                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mImages[0]->getTexName());
00194 
00195                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00196                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, (use_cube_mipmaps? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
00197                 if (mTextureStage > 0)
00198                 {
00199                         glActiveTextureARB(GL_TEXTURE0_ARB);
00200                 }
00201         }
00202         else
00203         {
00204                 llwarns << "Using cube map without extension!" << llendl
00205         }
00206 }
00207 
00208 void LLCubeMap::enable(S32 stage)
00209 {
00210         enableTexture(stage);
00211         enableTextureCoords(stage);
00212 }
00213 
00214 void LLCubeMap::enableTexture(S32 stage)
00215 {
00216         mTextureStage = stage;
00217         if (gGLManager.mHasCubeMap &&
00218             stage >= 0
00219             //&& LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap")
00220             )
00221         {
00222                 if (stage > 0)
00223                 {
00224                         glActiveTextureARB(GL_TEXTURE0_ARB + stage); 
00225                 }
00226                 
00227                 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
00228                 
00229                 if (stage > 0)
00230                 {
00231                         glActiveTextureARB(GL_TEXTURE0_ARB);
00232                 }
00233         }
00234 }
00235 
00236 void LLCubeMap::enableTextureCoords(S32 stage)
00237 {
00238         mTextureCoordStage = stage;
00239         if (gGLManager.mHasCubeMap && stage >= 0)
00240         {
00241                 if (stage > 0)
00242                 {
00243                         glActiveTextureARB(GL_TEXTURE0_ARB + stage);
00244                 }
00245                 
00246                 glEnable(GL_TEXTURE_GEN_R);
00247                 glEnable(GL_TEXTURE_GEN_S);
00248                 glEnable(GL_TEXTURE_GEN_T);
00249 
00250                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
00251                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
00252                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
00253                 
00254                 if (stage > 0)
00255                 {
00256                         glActiveTextureARB(GL_TEXTURE0_ARB);
00257                 }
00258         }
00259 }
00260 
00261 void LLCubeMap::disable(void)
00262 {
00263         disableTexture();
00264         disableTextureCoords();
00265 }
00266 
00267 void LLCubeMap::disableTexture(void)
00268 {
00269         if (gGLManager.mHasCubeMap && mTextureStage >= 0
00270             //&& LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap")
00271             )
00272         {
00273                 if (mTextureStage > 0)
00274                 {
00275                         glActiveTextureARB(GL_TEXTURE0_ARB + mTextureStage);
00276                 }
00277                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
00278                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
00279                 if (mTextureStage > 0)
00280                 {
00281                         glActiveTextureARB(GL_TEXTURE0_ARB);
00282                 }
00283         }
00284 }
00285 
00286 void LLCubeMap::disableTextureCoords(void)
00287 {
00288         if (gGLManager.mHasCubeMap && mTextureCoordStage >= 0)
00289         {
00290                 if (mTextureCoordStage > 0)
00291                 {
00292                         glActiveTextureARB(GL_TEXTURE0_ARB + mTextureCoordStage);
00293                 }
00294                 glDisable(GL_TEXTURE_GEN_S);
00295                 glDisable(GL_TEXTURE_GEN_T);
00296                 glDisable(GL_TEXTURE_GEN_R);
00297                 if (mTextureCoordStage > 0)
00298                 {
00299                         glActiveTextureARB(GL_TEXTURE0_ARB);
00300                 }
00301         }
00302 }
00303 
00304 void LLCubeMap::setMatrix(S32 stage)
00305 {
00306         mMatrixStage = stage;
00307         
00308         if (stage > 0)
00309         {
00310                 glActiveTextureARB(GL_TEXTURE0_ARB+stage);
00311         }
00312 
00313         LLVector3 x(LLVector3d(gGLModelView+0));
00314         LLVector3 y(LLVector3d(gGLModelView+4));
00315         LLVector3 z(LLVector3d(gGLModelView+8));
00316 
00317         LLMatrix3 mat3;
00318         mat3.setRows(x,y,z);
00319         LLMatrix4 trans(mat3);
00320         trans.transpose();
00321 
00322         glMatrixMode(GL_TEXTURE);
00323         glPushMatrix();
00324         glLoadMatrixf((F32 *)trans.mMatrix);
00325         glMatrixMode(GL_MODELVIEW);
00326         
00327         if (stage > 0)
00328         {
00329                 glActiveTextureARB(GL_TEXTURE0_ARB);
00330         }
00331 }
00332 
00333 void LLCubeMap::restoreMatrix()
00334 {
00335         if (mMatrixStage > 0)
00336         {
00337                 glActiveTextureARB(GL_TEXTURE0_ARB+mMatrixStage);
00338         }
00339         glMatrixMode(GL_TEXTURE);
00340         glPopMatrix();
00341         glMatrixMode(GL_MODELVIEW);
00342         
00343         if (mMatrixStage > 0)
00344         {
00345                 glActiveTextureARB(GL_TEXTURE0_ARB);
00346         }
00347 }
00348 
00349 LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
00350 {
00351         LLVector3 dir;
00352 
00353         const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
00354         const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
00355         const U8 i_coef = (curr_coef + 1) % 3;
00356         const U8 j_coef = (i_coef + 1) % 3;
00357 
00358         dir.mV[curr_coef] = side_dir;
00359 
00360         switch (side)
00361         {
00362         case 0: // negative X
00363                 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00364                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00365                 break;
00366         case 1: // positive X
00367                 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00368                 dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
00369                 break;
00370         case 2: // negative Y
00371                 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00372                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00373                 break;
00374         case 3: // positive Y
00375                 dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
00376                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00377                 break;
00378         case 4: // negative Z
00379                 dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
00380                 dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
00381                 break;
00382         case 5: // positive Z
00383                 dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
00384                 dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
00385                 break;
00386         default:
00387                 dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
00388                 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
00389         }
00390 
00391         dir.normVec();
00392         return dir;
00393 }
00394 
00395 
00396 BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
00397                                                 U8 side, const LLVector3& dir) const
00398 {
00399         const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
00400         const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
00401         const U8 i_coef = (curr_coef + 1) % 3;
00402         const U8 j_coef = (i_coef + 1) % 3;
00403 
00404         outside = TRUE;
00405         if (side_dir * dir.mV[curr_coef] < 0)
00406                 return FALSE;
00407 
00408         LLVector3 ray;
00409 
00410         F32 norm_val = fabs(dir.mV[curr_coef]);
00411 
00412         if (norm_val < epsilon)
00413                 norm_val = 1e-5f;
00414 
00415         ray.mV[curr_coef] = side_dir;
00416         ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
00417         ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
00418 
00419 
00420         const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
00421         const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
00422 
00423         switch (side)
00424         {
00425         case 0: // negative X
00426                 v_val = RESOLUTION - i_val;
00427                 h_val = j_val;
00428                 break;
00429         case 1: // positive X
00430                 v_val = RESOLUTION - i_val;
00431                 h_val = RESOLUTION - j_val;
00432                 break;
00433         case 2: // negative Y
00434                 v_val = RESOLUTION - i_val;
00435                 h_val = j_val;
00436                 break;
00437         case 3: // positive Y
00438                 v_val = i_val;
00439                 h_val = j_val;
00440                 break;
00441         case 4: // negative Z
00442                 v_val = RESOLUTION - j_val;
00443                 h_val = RESOLUTION - i_val;
00444                 break;
00445         case 5: // positive Z
00446                 v_val = RESOLUTION - j_val;
00447                 h_val = i_val;
00448                 break;
00449         default:
00450                 v_val = i_val;
00451                 h_val = j_val;
00452         }
00453 
00454         outside =  ((v_val < 0) || (v_val > RESOLUTION) ||
00455                 (h_val < 0) || (h_val > RESOLUTION));
00456 
00457         return TRUE;
00458 }
00459 
00460 BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max, 
00461                                                 U8 side, LLVector3 dir[4]) const
00462 {
00463         v_min = h_min = RESOLUTION;
00464         v_max = h_max = 0;
00465 
00466         BOOL fully_outside = TRUE;
00467         for (U8 vtx = 0; vtx < 4; ++vtx)
00468         {
00469                 F32 v_val, h_val;
00470                 BOOL outside;
00471                 BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
00472                 if (!outside)
00473                         fully_outside = FALSE;
00474                 if (consider)
00475                 {
00476                         if (v_val < v_min) v_min = v_val;
00477                         if (v_val > v_max) v_max = v_val;
00478                         if (h_val < h_min) h_min = h_val;
00479                         if (h_val > h_max) h_max = h_val;
00480                 }
00481         }
00482 
00483         v_min = llmax(0.0f, v_min);
00484         v_max = llmin(RESOLUTION - epsilon, v_max);
00485         h_min = llmax(0.0f, h_min);
00486         h_max = llmin(RESOLUTION - epsilon, h_max);
00487 
00488         return !fully_outside;
00489 }
00490 
00491 
00492 void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
00493 {
00494         F32 v_min, v_max, h_min, h_max;
00495         LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
00496         center.normVec();
00497 
00498         for (U8 side = 0; side < 6; ++side)
00499         {
00500                 if (!project(v_min, v_max, h_min, h_max, side, dir))
00501                         continue;
00502 
00503                 U8 *td = mRawImages[side]->getData();
00504                 
00505                 U16 v_minu = (U16) v_min;
00506                 U16 v_maxu = (U16) (ceil(v_max) + 0.5);
00507                 U16 h_minu = (U16) h_min;
00508                 U16 h_maxu = (U16) (ceil(h_max) + 0.5);
00509 
00510                 for (U16 v = v_minu; v < v_maxu; ++v)
00511                         for (U16 h = h_minu; h < h_maxu; ++h)
00512                 //for (U16 v = 0; v < RESOLUTION; ++v)
00513                 //      for (U16 h = 0; h < RESOLUTION; ++h)
00514                         {
00515                                 const LLVector3 ray = map(side, v, h);
00516                                 if (ray * center > 0.999)
00517                                 {
00518                                         const U32 offset = (RESOLUTION * v + h) * 4;
00519                                         for (U8 cc = 0; cc < 3; ++cc)
00520                                                 td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
00521                                 }
00522                         }
00523                 mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64);
00524         }
00525 }
00526 
00527 void LLCubeMap::destroyGL()
00528 {
00529         for (S32 i = 0; i < 6; i++)
00530         {
00531                 mImages[i] = NULL;
00532         }
00533 }

Generated on Fri May 16 08:33:16 2008 for SecondLife by  doxygen 1.5.5