PageRenderTime 675ms CodeModel.GetById 155ms app.highlight 336ms RepoModel.GetById 175ms app.codeStats 0ms

/indra/newview/llvowlsky.cpp

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