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
00052
00053 const BOOL use_cube_mipmaps = FALSE;
00054 #else
00055 const BOOL use_cube_mipmaps = FALSE;
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
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
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
00185 )
00186 {
00187
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
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
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;
00354 const S8 side_dir = (((side & 1) << 1) - 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:
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:
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:
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:
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:
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:
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;
00400 const S8 side_dir = (((side & 1) << 1) - 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:
00426 v_val = RESOLUTION - i_val;
00427 h_val = j_val;
00428 break;
00429 case 1:
00430 v_val = RESOLUTION - i_val;
00431 h_val = RESOLUTION - j_val;
00432 break;
00433 case 2:
00434 v_val = RESOLUTION - i_val;
00435 h_val = j_val;
00436 break;
00437 case 3:
00438 v_val = i_val;
00439 h_val = j_val;
00440 break;
00441 case 4:
00442 v_val = RESOLUTION - j_val;
00443 h_val = RESOLUTION - i_val;
00444 break;
00445 case 5:
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
00513
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 }