aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvowlsky.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/newview/llvowlsky.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-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.cpp821
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
44const F32 LLVOWLSky::DISTANCE_TO_STARS = (HORIZON_DIST - 10.f)*0.25f;
45
46const U32 LLVOWLSky::MIN_SKY_DETAIL = 3;
47const U32 LLVOWLSky::MAX_SKY_DETAIL = 180;
48
49inline U32 LLVOWLSky::getNumStacks(void)
50{
51 return gSavedSettings.getU32("WLSkyDetail");
52}
53
54inline U32 LLVOWLSky::getNumSlices(void)
55{
56 return 2 * gSavedSettings.getU32("WLSkyDetail");
57}
58
59inline U32 LLVOWLSky::getFanNumVerts(void)
60{
61 return getNumSlices() + 1;
62}
63
64inline U32 LLVOWLSky::getFanNumIndices(void)
65{
66 return getNumSlices() * 3;
67}
68
69inline U32 LLVOWLSky::getStripsNumVerts(void)
70{
71 return (getNumStacks() - 1) * getNumSlices();
72}
73
74inline U32 LLVOWLSky::getStripsNumIndices(void)
75{
76 return 2 * ((getNumStacks() - 2) * (getNumSlices() + 1)) + 1 ;
77}
78
79inline U32 LLVOWLSky::getStarsNumVerts(void)
80{
81 return 1000;
82}
83
84inline U32 LLVOWLSky::getStarsNumIndices(void)
85{
86 return 1000;
87}
88
89LLVOWLSky::LLVOWLSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
90 : LLStaticViewerObject(id, pcode, regionp)
91{
92 initStars();
93}
94
95void LLVOWLSky::initSunDirection(LLVector3 const & sun_direction,
96 LLVector3 const & sun_angular_velocity)
97{
98}
99
100BOOL LLVOWLSky::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
101{
102 return TRUE;
103}
104
105BOOL LLVOWLSky::isActive(void) const
106{
107 return FALSE;
108}
109
110LLDrawable * 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
122inline 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
139static 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)
142static 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
161static 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)
187void 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
237void 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
285void LLVOWLSky::resetVertexBuffers()
286{
287 mFanVerts = NULL;
288 mStripsVerts.clear();
289 mStarsVerts = NULL;
290
291 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
292}
293
294void LLVOWLSky::cleanupGL()
295{
296 mFanVerts = NULL;
297 mStripsVerts.clear();
298 mStarsVerts = NULL;
299
300 LLDrawPoolWLSky::cleanupGL();
301}
302
303void LLVOWLSky::restoreGL()
304{
305 LLDrawPoolWLSky::restoreGL();
306 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
307}
308
309BOOL 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
485void 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
500void 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
555void 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
590void 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
650void 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
736void 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
788BOOL 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}