aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llcubemap.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llcubemap.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llcubemap.cpp423
1 files changed, 423 insertions, 0 deletions
diff --git a/linden/indra/newview/llcubemap.cpp b/linden/indra/newview/llcubemap.cpp
new file mode 100644
index 0000000..4406bc8
--- /dev/null
+++ b/linden/indra/newview/llcubemap.cpp
@@ -0,0 +1,423 @@
1/**
2 * @file llcubemap.cpp
3 * @brief LLCubeMap class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29#include "llworkerthread.h"
30
31#include "llcubemap.h"
32
33#include "v4coloru.h"
34#include "v3math.h"
35
36#include "llviewercamera.h"
37#include "llviewerimage.h"
38#include "llviewerimagelist.h"
39
40#include "llglheaders.h"
41
42const F32 epsilon = 1e-7f;
43const U16 RESOLUTION = 64;
44
45#if LL_DARWIN
46// mipmap generation on cubemap textures seems to be broken on the Mac for at least some cards.
47// Since the cubemap is small (64x64 per face) and doesn't have any fine detail, turning off mipmaps is a usable workaround.
48const BOOL use_cube_mipmaps = FALSE;
49#else
50const BOOL use_cube_mipmaps = FALSE; //current build works best without cube mipmaps
51#endif
52
53LLCubeMap::LLCubeMap()
54 : mTextureStage(0),
55 mMatrixStage(0)
56{
57}
58
59LLCubeMap::~LLCubeMap()
60{
61}
62
63void LLCubeMap::initGL()
64{
65 llassert(gGLManager.mInited);
66
67 if (gGLManager.mHasCubeMap)
68 {
69 mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
70 mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
71 mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
72 mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
73 mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
74 mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
75
76 // Not initialized, do stuff.
77 if (mImages[0].isNull())
78 {
79 GLuint texname = 0;
80
81 glGenTextures(1, &texname);
82
83 for (int i = 0; i < 6; i++)
84 {
85 mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
86 mImages[i]->setTarget(mTargets[i], GL_TEXTURE_CUBE_MAP_ARB);
87 mRawImages[i] = new LLImageRaw(64, 64, 4);
88 mImages[i]->createGLTexture(0, mRawImages[i], texname);
89
90 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texname);
91 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
92 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
93 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
94 stop_glerror();
95 }
96 }
97 disable();
98 }
99 else
100 {
101 llwarns << "Using cube map without extension!" << llendl
102 }
103}
104
105void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages)
106{
107 bool flip_x[6] = { false, true, false, false, true, false };
108 bool flip_y[6] = { true, true, true, false, true, true };
109 bool transpose[6] = { false, false, false, false, true, true };
110
111 // Yes, I know that this is inefficient! - djs 08/08/02
112 for (int i = 0; i < 6; i++)
113 {
114 const U8 *sd = rawimages[i]->getData();
115 U8 *td = mRawImages[i]->getData();
116
117 S32 offset = 0;
118 S32 sx, sy, so;
119 for (int y = 0; y < 64; y++)
120 {
121 for (int x = 0; x < 64; x++)
122 {
123 sx = x;
124 sy = y;
125 if (flip_y[i])
126 {
127 sy = 63 - y;
128 }
129 if (flip_x[i])
130 {
131 sx = 63 - x;
132 }
133 if (transpose[i])
134 {
135 S32 temp = sx;
136 sx = sy;
137 sy = temp;
138 }
139
140 so = 64*sy + sx;
141 so *= 4;
142 *(td + offset++) = *(sd + so++);
143 *(td + offset++) = *(sd + so++);
144 *(td + offset++) = *(sd + so++);
145 *(td + offset++) = *(sd + so++);
146 }
147 }
148 }
149}
150
151void LLCubeMap::initGLData()
152{
153 for (int i = 0; i < 6; i++)
154 {
155 mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64);
156 }
157}
158
159void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
160{
161 if (!gGLManager.mIsDisabled)
162 {
163 initGL();
164 initRawData(rawimages);
165 initGLData();
166 }
167}
168
169void LLCubeMap::bind()
170{
171 if (gGLManager.mHasCubeMap)
172 {
173 // We assume that if they have cube mapping, they have multitexturing.
174 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
175 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mImages[0]->getTexName());
176
177 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
178 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, (use_cube_mipmaps? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
179
180 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
181 }
182 else
183 {
184 llwarns << "Using cube map without extension!" << llendl
185 }
186}
187
188void LLCubeMap::enable(S32 stage)
189{
190 mTextureStage = stage;
191 if (gGLManager.mHasCubeMap && stage >= 0)
192 {
193 glActiveTextureARB(GL_TEXTURE0_ARB + stage); // NOTE: leaves texture stage set
194
195 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
196 glEnable(GL_TEXTURE_GEN_R);
197 glEnable(GL_TEXTURE_GEN_S);
198 glEnable(GL_TEXTURE_GEN_T);
199
200 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
201 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
202 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
203 }
204}
205
206void LLCubeMap::disable()
207{
208 if (gGLManager.mHasCubeMap && mTextureStage >= 0)
209 {
210 glActiveTextureARB(GL_TEXTURE0_ARB + mTextureStage);
211
212 glDisable(GL_TEXTURE_GEN_S);
213 glDisable(GL_TEXTURE_GEN_T);
214 glDisable(GL_TEXTURE_GEN_R);
215 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
216 }
217}
218
219void LLCubeMap::setMatrix(S32 stage)
220{
221 mMatrixStage = stage;
222 glActiveTextureARB(GL_TEXTURE0_ARB+stage);
223 glMatrixMode(GL_TEXTURE);
224 glPushMatrix();
225 LLMatrix4 tmat;
226 gCamera->getRotMatrixToParent(tmat);
227 glLoadMatrixf((F32 *)tmat.mMatrix);
228 glMatrixMode(GL_MODELVIEW);
229}
230
231void LLCubeMap::restoreMatrix()
232{
233 glActiveTextureARB(GL_TEXTURE0_ARB+mMatrixStage);
234 glMatrixMode(GL_TEXTURE);
235 glPopMatrix();
236 glMatrixMode(GL_MODELVIEW);
237}
238
239LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
240{
241 LLVector3 dir;
242
243 const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
244 const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
245 const U8 i_coef = (curr_coef + 1) % 3;
246 const U8 j_coef = (i_coef + 1) % 3;
247
248 dir.mV[curr_coef] = side_dir;
249
250 switch (side)
251 {
252 case 0: // negative X
253 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
254 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
255 break;
256 case 1: // positive X
257 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
258 dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
259 break;
260 case 2: // negative Y
261 dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
262 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
263 break;
264 case 3: // positive Y
265 dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
266 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
267 break;
268 case 4: // negative Z
269 dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
270 dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
271 break;
272 case 5: // positive Z
273 dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
274 dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
275 break;
276 default:
277 dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
278 dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
279 }
280
281 dir.normVec();
282 return dir;
283}
284
285
286BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
287 U8 side, const LLVector3& dir) const
288{
289 const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
290 const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
291 const U8 i_coef = (curr_coef + 1) % 3;
292 const U8 j_coef = (i_coef + 1) % 3;
293
294 outside = TRUE;
295 if (side_dir * dir.mV[curr_coef] < 0)
296 return FALSE;
297
298 LLVector3 ray;
299
300 F32 norm_val = fabs(dir.mV[curr_coef]);
301
302 if (norm_val < epsilon)
303 norm_val = 1e-5f;
304
305 ray.mV[curr_coef] = side_dir;
306 ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
307 ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
308
309
310 const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
311 const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
312
313 switch (side)
314 {
315 case 0: // negative X
316 v_val = RESOLUTION - i_val;
317 h_val = j_val;
318 break;
319 case 1: // positive X
320 v_val = RESOLUTION - i_val;
321 h_val = RESOLUTION - j_val;
322 break;
323 case 2: // negative Y
324 v_val = RESOLUTION - i_val;
325 h_val = j_val;
326 break;
327 case 3: // positive Y
328 v_val = i_val;
329 h_val = j_val;
330 break;
331 case 4: // negative Z
332 v_val = RESOLUTION - j_val;
333 h_val = RESOLUTION - i_val;
334 break;
335 case 5: // positive Z
336 v_val = RESOLUTION - j_val;
337 h_val = i_val;
338 break;
339 default:
340 v_val = i_val;
341 h_val = j_val;
342 }
343
344 outside = ((v_val < 0) || (v_val > RESOLUTION) ||
345 (h_val < 0) || (h_val > RESOLUTION));
346
347 return TRUE;
348}
349
350BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
351 U8 side, LLVector3 dir[4]) const
352{
353 v_min = h_min = RESOLUTION;
354 v_max = h_max = 0;
355
356 BOOL fully_outside = TRUE;
357 for (U8 vtx = 0; vtx < 4; ++vtx)
358 {
359 F32 v_val, h_val;
360 BOOL outside;
361 BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
362 if (!outside)
363 fully_outside = FALSE;
364 if (consider)
365 {
366 if (v_val < v_min) v_min = v_val;
367 if (v_val > v_max) v_max = v_val;
368 if (h_val < h_min) h_min = h_val;
369 if (h_val > h_max) h_max = h_val;
370 }
371 }
372
373 v_min = llmax(0.0f, v_min);
374 v_max = llmin(RESOLUTION - epsilon, v_max);
375 h_min = llmax(0.0f, h_min);
376 h_max = llmin(RESOLUTION - epsilon, h_max);
377
378 return !fully_outside;
379}
380
381
382void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
383{
384 F32 v_min, v_max, h_min, h_max;
385 LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
386 center.normVec();
387
388 for (U8 side = 0; side < 6; ++side)
389 {
390 if (!project(v_min, v_max, h_min, h_max, side, dir))
391 continue;
392
393 U8 *td = mRawImages[side]->getData();
394
395 U16 v_minu = (U16) v_min;
396 U16 v_maxu = (U16) (ceil(v_max) + 0.5);
397 U16 h_minu = (U16) h_min;
398 U16 h_maxu = (U16) (ceil(h_max) + 0.5);
399
400 for (U16 v = v_minu; v < v_maxu; ++v)
401 for (U16 h = h_minu; h < h_maxu; ++h)
402 //for (U16 v = 0; v < RESOLUTION; ++v)
403 // for (U16 h = 0; h < RESOLUTION; ++h)
404 {
405 const LLVector3 ray = map(side, v, h);
406 if (ray * center > 0.999)
407 {
408 const U32 offset = (RESOLUTION * v + h) * 4;
409 for (U8 cc = 0; cc < 3; ++cc)
410 td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
411 }
412 }
413 mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64);
414 }
415}
416
417void LLCubeMap::destroyGL()
418{
419 for (S32 i = 0; i < 6; i++)
420 {
421 mImages[i] = NULL;
422 }
423}