diff options
author | Jacek Antonelli | 2008-08-15 23:45:34 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:34 -0500 |
commit | cd17687f01420952712a500107e0f93e7ab8d5f8 (patch) | |
tree | ce48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/newview/llvowlsky.cpp | |
parent | Second Life viewer sources 1.19.0.5 (diff) | |
download | meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2 meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz |
Second Life viewer sources 1.19.1.0
Diffstat (limited to 'linden/indra/newview/llvowlsky.cpp')
-rw-r--r-- | linden/indra/newview/llvowlsky.cpp | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/linden/indra/newview/llvowlsky.cpp b/linden/indra/newview/llvowlsky.cpp new file mode 100644 index 0000000..30d1397 --- /dev/null +++ b/linden/indra/newview/llvowlsky.cpp | |||
@@ -0,0 +1,821 @@ | |||
1 | /** | ||
2 | * @file llvowlsky.cpp | ||
3 | * @brief LLVOWLSky class implementation | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2007&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2007-2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | #include "llviewerprecompiledheaders.h" | ||
33 | |||
34 | #include "pipeline.h" | ||
35 | |||
36 | #include "llvowlsky.h" | ||
37 | #include "llsky.h" | ||
38 | #include "lldrawpoolwlsky.h" | ||
39 | #include "llface.h" | ||
40 | #include "llwlparammanager.h" | ||
41 | #include "llviewercontrol.h" | ||
42 | |||
43 | #define DOME_SLICES 1 | ||
44 | const F32 LLVOWLSky::DISTANCE_TO_STARS = (HORIZON_DIST - 10.f)*0.25f; | ||
45 | |||
46 | const U32 LLVOWLSky::MIN_SKY_DETAIL = 3; | ||
47 | const U32 LLVOWLSky::MAX_SKY_DETAIL = 180; | ||
48 | |||
49 | inline U32 LLVOWLSky::getNumStacks(void) | ||
50 | { | ||
51 | return gSavedSettings.getU32("WLSkyDetail"); | ||
52 | } | ||
53 | |||
54 | inline U32 LLVOWLSky::getNumSlices(void) | ||
55 | { | ||
56 | return 2 * gSavedSettings.getU32("WLSkyDetail"); | ||
57 | } | ||
58 | |||
59 | inline U32 LLVOWLSky::getFanNumVerts(void) | ||
60 | { | ||
61 | return getNumSlices() + 1; | ||
62 | } | ||
63 | |||
64 | inline U32 LLVOWLSky::getFanNumIndices(void) | ||
65 | { | ||
66 | return getNumSlices() * 3; | ||
67 | } | ||
68 | |||
69 | inline U32 LLVOWLSky::getStripsNumVerts(void) | ||
70 | { | ||
71 | return (getNumStacks() - 1) * getNumSlices(); | ||
72 | } | ||
73 | |||
74 | inline U32 LLVOWLSky::getStripsNumIndices(void) | ||
75 | { | ||
76 | return 2 * ((getNumStacks() - 2) * (getNumSlices() + 1)) + 1 ; | ||
77 | } | ||
78 | |||
79 | inline U32 LLVOWLSky::getStarsNumVerts(void) | ||
80 | { | ||
81 | return 1000; | ||
82 | } | ||
83 | |||
84 | inline U32 LLVOWLSky::getStarsNumIndices(void) | ||
85 | { | ||
86 | return 1000; | ||
87 | } | ||
88 | |||
89 | LLVOWLSky::LLVOWLSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) | ||
90 | : LLStaticViewerObject(id, pcode, regionp) | ||
91 | { | ||
92 | initStars(); | ||
93 | } | ||
94 | |||
95 | void LLVOWLSky::initSunDirection(LLVector3 const & sun_direction, | ||
96 | LLVector3 const & sun_angular_velocity) | ||
97 | { | ||
98 | } | ||
99 | |||
100 | BOOL LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | ||
101 | { | ||
102 | return TRUE; | ||
103 | } | ||
104 | |||
105 | BOOL LLVOWLSky::isActive(void) const | ||
106 | { | ||
107 | return FALSE; | ||
108 | } | ||
109 | |||
110 | LLDrawable * LLVOWLSky::createDrawable(LLPipeline * pipeline) | ||
111 | { | ||
112 | pipeline->allocDrawable(this); | ||
113 | |||
114 | //LLDrawPoolWLSky *poolp = static_cast<LLDrawPoolWLSky *>( | ||
115 | gPipeline.getPool(LLDrawPool::POOL_WL_SKY); | ||
116 | |||
117 | mDrawable->setRenderType(LLPipeline::RENDER_TYPE_WL_SKY); | ||
118 | |||
119 | return mDrawable; | ||
120 | } | ||
121 | |||
122 | inline F32 LLVOWLSky::calcPhi(U32 i) | ||
123 | { | ||
124 | // i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f] | ||
125 | F32 t = float(i) / float(getNumStacks()); | ||
126 | |||
127 | // ^4 the parameter of the tesselation to bias things toward 0 (the dome's apex) | ||
128 | t = t*t*t*t; | ||
129 | |||
130 | // invert and square the parameter of the tesselation to bias things toward 1 (the horizon) | ||
131 | t = 1.f - t; | ||
132 | t = t*t; | ||
133 | t = 1.f - t; | ||
134 | |||
135 | return (F_PI / 8.f) * t; | ||
136 | } | ||
137 | |||
138 | #if !DOME_SLICES | ||
139 | static const F32 Q = (1.f + sqrtf(5.f))/2.f; //golden ratio | ||
140 | |||
141 | //icosahedron verts (based on asset b0c7b76e-28c6-1f87-a1de-752d5e3cd264, contact Runitai Linden for a copy) | ||
142 | static const LLVector3 icosahedron_vert[] = | ||
143 | { | ||
144 | LLVector3(0,1.f,Q), | ||
145 | LLVector3(0,-1.f,Q), | ||
146 | LLVector3(0,-1.f,-Q), | ||
147 | LLVector3(0,1.f,-Q), | ||
148 | |||
149 | LLVector3(Q,0,1.f), | ||
150 | LLVector3(-Q,0,1.f), | ||
151 | LLVector3(-Q,0,-1.f), | ||
152 | LLVector3(Q,0,-1.f), | ||
153 | |||
154 | LLVector3(1,-Q,0.f), | ||
155 | LLVector3(-1,-Q,0.f), | ||
156 | LLVector3(-1,Q,0.f), | ||
157 | LLVector3(1,Q,0.f), | ||
158 | }; | ||
159 | |||
160 | //indices | ||
161 | static const U32 icosahedron_ind[] = | ||
162 | { | ||
163 | 5,0,1, | ||
164 | 10,0,5, | ||
165 | 5,1,9, | ||
166 | 10,5,6, | ||
167 | 6,5,9, | ||
168 | 11,0,10, | ||
169 | 3,11,10, | ||
170 | 3,10,6, | ||
171 | 3,6,2, | ||
172 | 7,3,2, | ||
173 | 8,7,2, | ||
174 | 4,7,8, | ||
175 | 1,4,8, | ||
176 | 9,8,2, | ||
177 | 9,2,6, | ||
178 | 11,3,7, | ||
179 | 4,0,11, | ||
180 | 4,11,7, | ||
181 | 1,0,4, | ||
182 | 1,8,9, | ||
183 | }; | ||
184 | |||
185 | |||
186 | //split every triangle in LLVertexBuffer into even fourths (assumes index triangle lists) | ||
187 | void subdivide(LLVertexBuffer& in, LLVertexBuffer* ret) | ||
188 | { | ||
189 | S32 tri_in = in.getNumIndices()/3; | ||
190 | |||
191 | ret->allocateBuffer(tri_in*4*3, tri_in*4*3, TRUE); | ||
192 | |||
193 | LLStrider<LLVector3> vin, vout; | ||
194 | LLStrider<U16> indin, indout; | ||
195 | |||
196 | ret->getVertexStrider(vout); | ||
197 | in.getVertexStrider(vin); | ||
198 | |||
199 | ret->getIndexStrider(indout); | ||
200 | in.getIndexStrider(indin); | ||
201 | |||
202 | |||
203 | for (S32 i = 0; i < tri_in; i++) | ||
204 | { | ||
205 | LLVector3 v0 = vin[*indin++]; | ||
206 | LLVector3 v1 = vin[*indin++]; | ||
207 | LLVector3 v2 = vin[*indin++]; | ||
208 | |||
209 | LLVector3 v3 = (v0 + v1) * 0.5f; | ||
210 | LLVector3 v4 = (v1 + v2) * 0.5f; | ||
211 | LLVector3 v5 = (v2 + v0) * 0.5f; | ||
212 | |||
213 | *vout++ = v0; | ||
214 | *vout++ = v3; | ||
215 | *vout++ = v5; | ||
216 | |||
217 | *vout++ = v3; | ||
218 | *vout++ = v4; | ||
219 | *vout++ = v5; | ||
220 | |||
221 | *vout++ = v3; | ||
222 | *vout++ = v1; | ||
223 | *vout++ = v4; | ||
224 | |||
225 | *vout++ = v5; | ||
226 | *vout++ = v4; | ||
227 | *vout++ = v2; | ||
228 | } | ||
229 | |||
230 | for (S32 i = 0; i < ret->getNumIndices(); i++) | ||
231 | { | ||
232 | *indout++ = i; | ||
233 | } | ||
234 | |||
235 | } | ||
236 | |||
237 | void chop(LLVertexBuffer& in, LLVertexBuffer* out) | ||
238 | { | ||
239 | //chop off all triangles below horizon | ||
240 | F32 d = LLWLParamManager::sParamMgr->getDomeOffset() * LLWLParamManager::sParamMgr->getDomeRadius(); | ||
241 | |||
242 | std::vector<LLVector3> vert; | ||
243 | |||
244 | LLStrider<LLVector3> vin; | ||
245 | LLStrider<U16> index; | ||
246 | |||
247 | in.getVertexStrider(vin); | ||
248 | in.getIndexStrider(index); | ||
249 | |||
250 | U32 tri_count = in.getNumIndices()/3; | ||
251 | for (U32 i = 0; i < tri_count; i++) | ||
252 | { | ||
253 | LLVector3 &v1 = vin[index[i*3+0]]; | ||
254 | LLVector3 &v2 = vin[index[i*3+1]]; | ||
255 | LLVector3 &v3 = vin[index[i*3+2]]; | ||
256 | |||
257 | if (v1.mV[1] > d || | ||
258 | v2.mV[1] > d || | ||
259 | v3.mV[1] > d) | ||
260 | { | ||
261 | v1.mV[1] = llmax(v1.mV[1], d); | ||
262 | v2.mV[1] = llmax(v1.mV[1], d); | ||
263 | v3.mV[1] = llmax(v1.mV[1], d); | ||
264 | |||
265 | vert.push_back(v1); | ||
266 | vert.push_back(v2); | ||
267 | vert.push_back(v3); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | out->allocateBuffer(vert.size(), vert.size(), TRUE); | ||
272 | |||
273 | LLStrider<LLVector3> vout; | ||
274 | out->getVertexStrider(vout); | ||
275 | out->getIndexStrider(index); | ||
276 | |||
277 | for (U32 i = 0; i < vert.size(); i++) | ||
278 | { | ||
279 | *vout++ = vert[i]; | ||
280 | *index++ = i; | ||
281 | } | ||
282 | } | ||
283 | #endif // !DOME_SLICES | ||
284 | |||
285 | void LLVOWLSky::resetVertexBuffers() | ||
286 | { | ||
287 | mFanVerts = NULL; | ||
288 | mStripsVerts.clear(); | ||
289 | mStarsVerts = NULL; | ||
290 | |||
291 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); | ||
292 | } | ||
293 | |||
294 | void LLVOWLSky::cleanupGL() | ||
295 | { | ||
296 | mFanVerts = NULL; | ||
297 | mStripsVerts.clear(); | ||
298 | mStarsVerts = NULL; | ||
299 | |||
300 | LLDrawPoolWLSky::cleanupGL(); | ||
301 | } | ||
302 | |||
303 | void LLVOWLSky::restoreGL() | ||
304 | { | ||
305 | LLDrawPoolWLSky::restoreGL(); | ||
306 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); | ||
307 | } | ||
308 | |||
309 | BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) | ||
310 | { | ||
311 | LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY); | ||
312 | LLStrider<LLVector3> vertices; | ||
313 | LLStrider<LLVector2> texCoords; | ||
314 | LLStrider<U16> indices; | ||
315 | |||
316 | #if DOME_SLICES | ||
317 | { | ||
318 | mFanVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); | ||
319 | mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE); | ||
320 | |||
321 | BOOL success = mFanVerts->getVertexStrider(vertices) | ||
322 | && mFanVerts->getTexCoordStrider(texCoords) | ||
323 | && mFanVerts->getIndexStrider(indices); | ||
324 | |||
325 | if(!success) | ||
326 | { | ||
327 | llerrs << "Failed updating WindLight sky geometry." << llendl; | ||
328 | } | ||
329 | |||
330 | buildFanBuffer(vertices, texCoords, indices); | ||
331 | |||
332 | mFanVerts->setBuffer(0); | ||
333 | } | ||
334 | |||
335 | { | ||
336 | const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024; | ||
337 | const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; | ||
338 | const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcStride(data_mask); | ||
339 | |||
340 | const U32 total_stacks = getNumStacks(); | ||
341 | |||
342 | const U32 verts_per_stack = getNumSlices(); | ||
343 | |||
344 | // each seg has to have one more row of verts than it has stacks | ||
345 | // then round down | ||
346 | const U32 stacks_per_seg = (max_verts - verts_per_stack) / verts_per_stack; | ||
347 | |||
348 | // round up to a whole number of segments | ||
349 | const U32 strips_segments = (total_stacks+stacks_per_seg-1) / stacks_per_seg; | ||
350 | |||
351 | llinfos << "WL Skydome strips in " << strips_segments << " batches." << llendl; | ||
352 | |||
353 | mStripsVerts.resize(strips_segments, NULL); | ||
354 | |||
355 | for (U32 i = 0; i < strips_segments ;++i) | ||
356 | { | ||
357 | LLVertexBuffer * segment = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); | ||
358 | mStripsVerts[i] = segment; | ||
359 | |||
360 | U32 num_stacks_this_seg = stacks_per_seg; | ||
361 | if ((i == strips_segments - 1) && (total_stacks % stacks_per_seg) != 0) | ||
362 | { | ||
363 | // for the last buffer only allocate what we'll use | ||
364 | num_stacks_this_seg = total_stacks % stacks_per_seg; | ||
365 | } | ||
366 | |||
367 | // figure out what range of the sky we're filling | ||
368 | const U32 begin_stack = i * stacks_per_seg; | ||
369 | const U32 end_stack = begin_stack + num_stacks_this_seg; | ||
370 | llassert(end_stack <= total_stacks); | ||
371 | |||
372 | const U32 num_verts_this_seg = verts_per_stack * (num_stacks_this_seg+1); | ||
373 | llassert(num_verts_this_seg <= max_verts); | ||
374 | |||
375 | const U32 num_indices_this_seg = 1+num_stacks_this_seg*(2+2*verts_per_stack); | ||
376 | llassert(num_indices_this_seg * sizeof(U16) <= max_buffer_bytes); | ||
377 | |||
378 | segment->allocateBuffer(num_verts_this_seg, num_indices_this_seg, TRUE); | ||
379 | |||
380 | // lock the buffer | ||
381 | BOOL success = segment->getVertexStrider(vertices) | ||
382 | && segment->getTexCoordStrider(texCoords) | ||
383 | && segment->getIndexStrider(indices); | ||
384 | |||
385 | if(!success) | ||
386 | { | ||
387 | llerrs << "Failed updating WindLight sky geometry." << llendl; | ||
388 | } | ||
389 | |||
390 | // fill it | ||
391 | buildStripsBuffer(begin_stack, end_stack, vertices, texCoords, indices); | ||
392 | |||
393 | // and unlock the buffer | ||
394 | segment->setBuffer(0); | ||
395 | } | ||
396 | } | ||
397 | #else | ||
398 | mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); | ||
399 | |||
400 | const F32 RADIUS = LLWLParamManager::sParamMgr->getDomeRadius(); | ||
401 | |||
402 | LLPointer<LLVertexBuffer> temp = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); | ||
403 | temp->allocateBuffer(12, 60, TRUE); | ||
404 | |||
405 | BOOL success = temp->getVertexStrider(vertices) | ||
406 | && temp->getIndexStrider(indices); | ||
407 | |||
408 | if (success) | ||
409 | { | ||
410 | for (U32 i = 0; i < 12; i++) | ||
411 | { | ||
412 | *vertices++ = icosahedron_vert[i]; | ||
413 | } | ||
414 | |||
415 | for (U32 i = 0; i < 60; i++) | ||
416 | { | ||
417 | *indices++ = icosahedron_ind[i]; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | |||
422 | LLPointer<LLVertexBuffer> temp2; | ||
423 | |||
424 | for (U32 i = 0; i < 8; i++) | ||
425 | { | ||
426 | temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); | ||
427 | subdivide(*temp, temp2); | ||
428 | temp = temp2; | ||
429 | } | ||
430 | |||
431 | temp->getVertexStrider(vertices); | ||
432 | for (S32 i = 0; i < temp->getNumVerts(); i++) | ||
433 | { | ||
434 | LLVector3 v = vertices[i]; | ||
435 | v.normVec(); | ||
436 | vertices[i] = v*RADIUS; | ||
437 | } | ||
438 | |||
439 | temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0); | ||
440 | chop(*temp, temp2); | ||
441 | |||
442 | mStripsVerts->allocateBuffer(temp2->getNumVerts(), temp2->getNumIndices(), TRUE); | ||
443 | |||
444 | success = mStripsVerts->getVertexStrider(vertices) | ||
445 | && mStripsVerts->getTexCoordStrider(texCoords) | ||
446 | && mStripsVerts->getIndexStrider(indices); | ||
447 | |||
448 | LLStrider<LLVector3> v; | ||
449 | temp2->getVertexStrider(v); | ||
450 | LLStrider<U16> ind; | ||
451 | temp2->getIndexStrider(ind); | ||
452 | |||
453 | if (success) | ||
454 | { | ||
455 | for (S32 i = 0; i < temp2->getNumVerts(); ++i) | ||
456 | { | ||
457 | LLVector3 vert = *v++; | ||
458 | vert.normVec(); | ||
459 | F32 z0 = vert.mV[2]; | ||
460 | F32 x0 = vert.mV[0]; | ||
461 | |||
462 | vert *= RADIUS; | ||
463 | |||
464 | *vertices++ = vert; | ||
465 | *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); | ||
466 | } | ||
467 | |||
468 | for (S32 i = 0; i < temp2->getNumIndices(); ++i) | ||
469 | { | ||
470 | *indices++ = *ind++; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | mStripsVerts->setBuffer(0); | ||
475 | #endif | ||
476 | |||
477 | updateStarColors(); | ||
478 | updateStarGeometry(drawable); | ||
479 | |||
480 | LLPipeline::sCompiles++; | ||
481 | |||
482 | return TRUE; | ||
483 | } | ||
484 | |||
485 | void LLVOWLSky::drawStars(void) | ||
486 | { | ||
487 | glEnableClientState(GL_COLOR_ARRAY); | ||
488 | |||
489 | // render the stars as a sphere centered at viewer camera | ||
490 | if (mStarsVerts.notNull()) | ||
491 | { | ||
492 | mStarsVerts->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK); | ||
493 | U16* indicesp = (U16*) mStarsVerts->getIndicesPointer(); | ||
494 | glDrawElements(GL_POINTS, getStarsNumIndices(), GL_UNSIGNED_SHORT, indicesp); | ||
495 | } | ||
496 | |||
497 | glDisableClientState(GL_COLOR_ARRAY); | ||
498 | } | ||
499 | |||
500 | void LLVOWLSky::drawDome(void) | ||
501 | { | ||
502 | if (mStripsVerts.empty()) | ||
503 | { | ||
504 | updateGeometry(mDrawable); | ||
505 | } | ||
506 | |||
507 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
508 | |||
509 | const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; | ||
510 | |||
511 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
512 | |||
513 | #if DOME_SLICES | ||
514 | //mFanVerts->setBuffer(data_mask); | ||
515 | //glDrawRangeElements( | ||
516 | // GL_TRIANGLES, | ||
517 | // 0, getFanNumVerts()-1, getFanNumIndices(), | ||
518 | // GL_UNSIGNED_SHORT, | ||
519 | // mFanVerts->getIndicesPointer()); | ||
520 | |||
521 | //gPipeline.addTrianglesDrawn(getFanNumIndices()/3); | ||
522 | |||
523 | std::vector< LLPointer<LLVertexBuffer> >::const_iterator strips_vbo_iter, end_strips; | ||
524 | end_strips = mStripsVerts.end(); | ||
525 | for(strips_vbo_iter = mStripsVerts.begin(); strips_vbo_iter != end_strips; ++strips_vbo_iter) | ||
526 | { | ||
527 | LLVertexBuffer * strips_segment = strips_vbo_iter->get(); | ||
528 | |||
529 | strips_segment->setBuffer(data_mask); | ||
530 | |||
531 | glDrawRangeElements( | ||
532 | //GL_TRIANGLES, | ||
533 | GL_TRIANGLE_STRIP, | ||
534 | 0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(), | ||
535 | GL_UNSIGNED_SHORT, | ||
536 | strips_segment->getIndicesPointer()); | ||
537 | |||
538 | gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices() - 2); | ||
539 | } | ||
540 | |||
541 | #else | ||
542 | mStripsVerts->setBuffer(data_mask); | ||
543 | glDrawRangeElements( | ||
544 | GL_TRIANGLES, | ||
545 | 0, mStripsVerts->getNumVerts()-1, mStripsVerts->getNumIndices(), | ||
546 | GL_UNSIGNED_SHORT, | ||
547 | mStripsVerts->getIndicesPointer()); | ||
548 | #endif | ||
549 | |||
550 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
551 | |||
552 | LLVertexBuffer::unbind(); | ||
553 | } | ||
554 | |||
555 | void LLVOWLSky::initStars() | ||
556 | { | ||
557 | // Initialize star map | ||
558 | mStarVertices.resize(getStarsNumVerts()); | ||
559 | mStarColors.resize(getStarsNumVerts()); | ||
560 | mStarIntensities.resize(getStarsNumVerts()); | ||
561 | |||
562 | std::vector<LLVector3>::iterator v_p = mStarVertices.begin(); | ||
563 | std::vector<LLColor4>::iterator v_c = mStarColors.begin(); | ||
564 | std::vector<F32>::iterator v_i = mStarIntensities.begin(); | ||
565 | |||
566 | U32 i; | ||
567 | for (i = 0; i < getStarsNumVerts(); ++i) | ||
568 | { | ||
569 | v_p->mV[VX] = ll_frand() - 0.5f; | ||
570 | v_p->mV[VY] = ll_frand() - 0.5f; | ||
571 | |||
572 | // we only want stars on the top half of the dome! | ||
573 | |||
574 | v_p->mV[VZ] = ll_frand()/2.f; | ||
575 | |||
576 | v_p->normVec(); | ||
577 | *v_p *= DISTANCE_TO_STARS; | ||
578 | *v_i = llmin((F32)pow(ll_frand(),2.f) + 0.1f, 1.f); | ||
579 | v_c->mV[VRED] = 0.75f + ll_frand() * 0.25f ; | ||
580 | v_c->mV[VGREEN] = 1.f ; | ||
581 | v_c->mV[VBLUE] = 0.75f + ll_frand() * 0.25f ; | ||
582 | v_c->mV[VALPHA] = 1.f; | ||
583 | v_c->clamp(); | ||
584 | v_p++; | ||
585 | v_c++; | ||
586 | v_i++; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | void LLVOWLSky::buildFanBuffer(LLStrider<LLVector3> & vertices, | ||
591 | LLStrider<LLVector2> & texCoords, | ||
592 | LLStrider<U16> & indices) | ||
593 | { | ||
594 | const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius(); | ||
595 | |||
596 | U32 i, num_slices; | ||
597 | F32 phi0, theta, x0, y0, z0; | ||
598 | |||
599 | // paranoia checking for SL-55986/SL-55833 | ||
600 | U32 count_verts = 0; | ||
601 | U32 count_indices = 0; | ||
602 | |||
603 | // apex | ||
604 | *vertices++ = LLVector3(0.f, RADIUS, 0.f); | ||
605 | *texCoords++ = LLVector2(0.5f, 0.5f); | ||
606 | ++count_verts; | ||
607 | |||
608 | num_slices = getNumSlices(); | ||
609 | |||
610 | // and fan in a circle around the apex | ||
611 | phi0 = calcPhi(1); | ||
612 | for(i = 0; i < num_slices; ++i) { | ||
613 | theta = 2.f * F_PI * float(i) / float(num_slices); | ||
614 | |||
615 | // standard transformation from spherical to | ||
616 | // rectangular coordinates | ||
617 | x0 = sin(phi0) * cos(theta); | ||
618 | y0 = cos(phi0); | ||
619 | z0 = sin(phi0) * sin(theta); | ||
620 | |||
621 | *vertices++ = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS); | ||
622 | // generate planar uv coordinates | ||
623 | // note: x and z are transposed in order for things to animate | ||
624 | // correctly in the global coordinate system where +x is east and | ||
625 | // +y is north | ||
626 | *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); | ||
627 | ++count_verts; | ||
628 | |||
629 | if (i > 0) | ||
630 | { | ||
631 | *indices++ = 0; | ||
632 | *indices++ = i; | ||
633 | *indices++ = i+1; | ||
634 | count_indices += 3; | ||
635 | } | ||
636 | } | ||
637 | |||
638 | // the last vertex of the last triangle should wrap around to | ||
639 | // the beginning | ||
640 | *indices++ = 0; | ||
641 | *indices++ = num_slices; | ||
642 | *indices++ = 1; | ||
643 | count_indices += 3; | ||
644 | |||
645 | // paranoia checking for SL-55986/SL-55833 | ||
646 | llassert(getFanNumVerts() == count_verts); | ||
647 | llassert(getFanNumIndices() == count_indices); | ||
648 | } | ||
649 | |||
650 | void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack, | ||
651 | LLStrider<LLVector3> & vertices, | ||
652 | LLStrider<LLVector2> & texCoords, | ||
653 | LLStrider<U16> & indices) | ||
654 | { | ||
655 | const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius(); | ||
656 | |||
657 | U32 i, j, num_slices, num_stacks; | ||
658 | F32 phi0, theta, x0, y0, z0; | ||
659 | |||
660 | // paranoia checking for SL-55986/SL-55833 | ||
661 | U32 count_verts = 0; | ||
662 | U32 count_indices = 0; | ||
663 | |||
664 | num_slices = getNumSlices(); | ||
665 | num_stacks = getNumStacks(); | ||
666 | |||
667 | llassert(end_stack <= num_stacks); | ||
668 | |||
669 | // stacks are iterated one-indexed since phi(0) was handled by the fan above | ||
670 | for(i = begin_stack + 1; i <= end_stack+1; ++i) | ||
671 | { | ||
672 | phi0 = calcPhi(i); | ||
673 | |||
674 | for(j = 0; j < num_slices; ++j) | ||
675 | { | ||
676 | theta = F_TWO_PI * (float(j) / float(num_slices)); | ||
677 | |||
678 | // standard transformation from spherical to | ||
679 | // rectangular coordinates | ||
680 | x0 = sin(phi0) * cos(theta); | ||
681 | y0 = cos(phi0); | ||
682 | z0 = sin(phi0) * sin(theta); | ||
683 | |||
684 | if (i == num_stacks-2) | ||
685 | { | ||
686 | *vertices++ = LLVector3(x0*RADIUS, y0*RADIUS-1024.f*2.f, z0*RADIUS); | ||
687 | } | ||
688 | else if (i == num_stacks-1) | ||
689 | { | ||
690 | *vertices++ = LLVector3(0, y0*RADIUS-1024.f*2.f, 0); | ||
691 | } | ||
692 | else | ||
693 | { | ||
694 | *vertices++ = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS); | ||
695 | } | ||
696 | ++count_verts; | ||
697 | |||
698 | // generate planar uv coordinates | ||
699 | // note: x and z are transposed in order for things to animate | ||
700 | // correctly in the global coordinate system where +x is east and | ||
701 | // +y is north | ||
702 | *texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f); | ||
703 | } | ||
704 | } | ||
705 | |||
706 | //build triangle strip... | ||
707 | *indices++ = 0 ; | ||
708 | count_indices++ ; | ||
709 | S32 k = 0 ; | ||
710 | for(i = 1; i <= end_stack - begin_stack; ++i) | ||
711 | { | ||
712 | *indices++ = i * num_slices + k ; | ||
713 | count_indices++ ; | ||
714 | |||
715 | k = (k+1) % num_slices ; | ||
716 | for(j = 0; j < num_slices ; ++j) | ||
717 | { | ||
718 | *indices++ = (i-1) * num_slices + k ; | ||
719 | *indices++ = i * num_slices + k ; | ||
720 | |||
721 | count_indices += 2 ; | ||
722 | |||
723 | k = (k+1) % num_slices ; | ||
724 | } | ||
725 | |||
726 | if((--k) < 0) | ||
727 | { | ||
728 | k = num_slices - 1 ; | ||
729 | } | ||
730 | |||
731 | *indices++ = i * num_slices + k ; | ||
732 | count_indices++ ; | ||
733 | } | ||
734 | } | ||
735 | |||
736 | void LLVOWLSky::updateStarColors() | ||
737 | { | ||
738 | std::vector<LLColor4>::iterator v_c = mStarColors.begin(); | ||
739 | std::vector<F32>::iterator v_i = mStarIntensities.begin(); | ||
740 | std::vector<LLVector3>::iterator v_p = mStarVertices.begin(); | ||
741 | |||
742 | const F32 var = 0.15f; | ||
743 | const F32 min = 0.5f; //0.75f; | ||
744 | const F32 sunclose_max = 0.6f; | ||
745 | const F32 sunclose_range = 1 - sunclose_max; | ||
746 | |||
747 | //F32 below_horizon = - llmin(0.0f, gSky.mVOSkyp->getToSunLast().mV[2]); | ||
748 | //F32 brightness_factor = llmin(1.0f, below_horizon * 20); | ||
749 | |||
750 | static S32 swap = 0; | ||
751 | swap++; | ||
752 | |||
753 | if ((swap % 2) == 1) | ||
754 | { | ||
755 | F32 intensity; // max intensity of each star | ||
756 | U32 x; | ||
757 | for (x = 0; x < getStarsNumVerts(); ++x) | ||
758 | { | ||
759 | F32 sundir_factor = 1; | ||
760 | LLVector3 tostar = *v_p; | ||
761 | tostar.normVec(); | ||
762 | const F32 how_close_to_sun = tostar * gSky.mVOSkyp->getToSunLast(); | ||
763 | if (how_close_to_sun > sunclose_max) | ||
764 | { | ||
765 | sundir_factor = (1 - how_close_to_sun) / sunclose_range; | ||
766 | } | ||
767 | intensity = *(v_i); | ||
768 | F32 alpha = v_c->mV[VALPHA] + (ll_frand() - 0.5f) * var * intensity; | ||
769 | if (alpha < min * intensity) | ||
770 | { | ||
771 | alpha = min * intensity; | ||
772 | } | ||
773 | if (alpha > intensity) | ||
774 | { | ||
775 | alpha = intensity; | ||
776 | } | ||
777 | //alpha *= brightness_factor * sundir_factor; | ||
778 | |||
779 | alpha = llclamp(alpha, 0.f, 1.f); | ||
780 | v_c->mV[VALPHA] = alpha; | ||
781 | v_c++; | ||
782 | v_i++; | ||
783 | v_p++; | ||
784 | } | ||
785 | } | ||
786 | } | ||
787 | |||
788 | BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable) | ||
789 | { | ||
790 | LLStrider<LLVector3> verticesp; | ||
791 | LLStrider<LLColor4U> colorsp; | ||
792 | LLStrider<U16> indicesp; | ||
793 | |||
794 | if (mStarsVerts.isNull()) | ||
795 | { | ||
796 | mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW); | ||
797 | mStarsVerts->allocateBuffer(getStarsNumVerts(), getStarsNumIndices(), TRUE); | ||
798 | } | ||
799 | |||
800 | BOOL success = mStarsVerts->getVertexStrider(verticesp) | ||
801 | && mStarsVerts->getIndexStrider(indicesp) | ||
802 | && mStarsVerts->getColorStrider(colorsp); | ||
803 | |||
804 | if(!success) | ||
805 | { | ||
806 | llerrs << "Failed updating star geometry." << llendl; | ||
807 | } | ||
808 | |||
809 | // *TODO: fix LLStrider with a real prefix increment operator so it can be | ||
810 | // used as a model of OutputIterator. -Brad | ||
811 | // std::copy(mStarVertices.begin(), mStarVertices.end(), verticesp); | ||
812 | for (U32 vtx = 0; vtx < getStarsNumVerts(); ++vtx) | ||
813 | { | ||
814 | *(verticesp++) = mStarVertices[vtx]; | ||
815 | *(colorsp++) = LLColor4U(mStarColors[vtx]); | ||
816 | *(indicesp++) = vtx; | ||
817 | } | ||
818 | |||
819 | mStarsVerts->setBuffer(0); | ||
820 | return TRUE; | ||
821 | } | ||