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 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
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
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
00184 )
00185 {
00186
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
00205 )
00206 {
00207 glActiveTextureARB(GL_TEXTURE0_ARB + stage);
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
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;
00268 const S8 side_dir = (((side & 1) << 1) - 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:
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:
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:
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:
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:
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:
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;
00314 const S8 side_dir = (((side & 1) << 1) - 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:
00340 v_val = RESOLUTION - i_val;
00341 h_val = j_val;
00342 break;
00343 case 1:
00344 v_val = RESOLUTION - i_val;
00345 h_val = RESOLUTION - j_val;
00346 break;
00347 case 2:
00348 v_val = RESOLUTION - i_val;
00349 h_val = j_val;
00350 break;
00351 case 3:
00352 v_val = i_val;
00353 h_val = j_val;
00354 break;
00355 case 4:
00356 v_val = RESOLUTION - j_val;
00357 h_val = RESOLUTION - i_val;
00358 break;
00359 case 5:
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
00427
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 }