PageRenderTime 84ms CodeModel.GetById 13ms app.highlight 65ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/newview/llvopartgroup.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 570 lines | 424 code | 106 blank | 40 comment | 40 complexity | 130de7d31d7cad966d4c97a056f0c45a MD5 | raw file
  1/** 
  2 * @file llvopartgroup.cpp
  3 * @brief Group of particle systems
  4 *
  5 * $LicenseInfo:firstyear=2001&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 "llvopartgroup.h"
 30
 31#include "lldrawpoolalpha.h"
 32
 33#include "llfasttimer.h"
 34#include "message.h"
 35#include "v2math.h"
 36
 37#include "llagentcamera.h"
 38#include "lldrawable.h"
 39#include "llface.h"
 40#include "llsky.h"
 41#include "llviewercamera.h"
 42#include "llviewerpartsim.h"
 43#include "llviewerregion.h"
 44#include "pipeline.h"
 45#include "llspatialpartition.h"
 46
 47const F32 MAX_PART_LIFETIME = 120.f;
 48
 49extern U64 gFrameTime;
 50
 51LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 52	:	LLAlphaObject(id, pcode, regionp),
 53		mViewerPartGroupp(NULL)
 54{
 55	setNumTEs(1);
 56	setTETexture(0, LLUUID::null);
 57	mbCanSelect = FALSE;			// users can't select particle systems
 58}
 59
 60
 61LLVOPartGroup::~LLVOPartGroup()
 62{
 63}
 64
 65
 66BOOL LLVOPartGroup::isActive() const
 67{
 68	return FALSE;
 69}
 70
 71F32 LLVOPartGroup::getBinRadius()
 72{ 
 73	return mScale.mV[0]*2.f;
 74}
 75
 76void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
 77{		
 78	const LLVector3& pos_agent = getPositionAgent();
 79	newMin.load3( (pos_agent - mScale).mV);
 80	newMax.load3( (pos_agent + mScale).mV);
 81	LLVector4a pos;
 82	pos.load3(pos_agent.mV);
 83	mDrawable->setPositionGroup(pos);
 84}
 85
 86BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 87{
 88	return TRUE;
 89}
 90
 91void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent)
 92{
 93	// mPixelArea is calculated during render
 94	F32 mid_scale = getMidScale();
 95	F32 range = (getRenderPosition()-LLViewerCamera::getInstance()->getOrigin()).length();
 96
 97	if (range < 0.001f || isHUDAttachment())		// range == zero
 98	{
 99		mAppAngle = 180.f;
100	}
101	else
102	{
103		mAppAngle = (F32) atan2( mid_scale, range) * RAD_TO_DEG;
104	}
105}
106
107void LLVOPartGroup::updateTextures()
108{
109	// Texture stats for particles need to be updated in a different way...
110}
111
112
113LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline)
114{
115	pipeline->allocDrawable(this);
116	mDrawable->setLit(FALSE);
117	mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
118	return mDrawable;
119}
120
121 const F32 MAX_PARTICLE_AREA_SCALE = 0.02f; // some tuned constant, limits on how much particle area to draw
122
123F32 LLVOPartGroup::getPartSize(S32 idx)
124{
125	if (idx < (S32) mViewerPartGroupp->mParticles.size())
126	{
127		return mViewerPartGroupp->mParticles[idx]->mScale.mV[0];
128	}
129
130	return 0.f;
131}
132
133LLVector3 LLVOPartGroup::getCameraPosition() const
134{
135	return gAgentCamera.getCameraPositionAgent();
136}
137
138static LLFastTimer::DeclareTimer FTM_UPDATE_PARTICLES("Update Particles");
139BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
140{
141	LLFastTimer ftm(FTM_UPDATE_PARTICLES);
142
143	dirtySpatialGroup();
144	
145	S32 num_parts = mViewerPartGroupp->getCount();
146	LLFace *facep;
147	LLSpatialGroup* group = drawable->getSpatialGroup();
148	if (!group && num_parts)
149	{
150		drawable->movePartition();
151		group = drawable->getSpatialGroup();
152	}
153
154	if (group && group->isVisible())
155	{
156		dirtySpatialGroup(TRUE);
157	}
158
159	if (!num_parts)
160	{
161		if (group && drawable->getNumFaces())
162		{
163			group->setState(LLSpatialGroup::GEOM_DIRTY);
164		}
165		drawable->setNumFaces(0, NULL, getTEImage(0));
166		LLPipeline::sCompiles++;
167		return TRUE;
168	}
169
170 	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))
171	{
172		return TRUE;
173	}
174
175	if (num_parts > drawable->getNumFaces())
176	{
177		drawable->setNumFacesFast(num_parts+num_parts/4, NULL, getTEImage(0));
178	}
179
180	F32 tot_area = 0;
181
182	F32 max_area = LLViewerPartSim::getMaxPartCount() * MAX_PARTICLE_AREA_SCALE; 
183	F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio();
184	pixel_meter_ratio *= pixel_meter_ratio;
185
186	LLViewerPartSim::checkParticleCount(mViewerPartGroupp->mParticles.size()) ;
187
188	S32 count=0;
189	mDepth = 0.f;
190	S32 i = 0 ;
191	LLVector3 camera_agent = getCameraPosition();
192	for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++)
193	{
194		const LLViewerPart *part = mViewerPartGroupp->mParticles[i];
195
196		LLVector3 part_pos_agent(part->mPosAgent);
197		LLVector3 at(part_pos_agent - camera_agent);
198
199		F32 camera_dist_squared = at.lengthSquared();
200		F32 inv_camera_dist_squared;
201		if (camera_dist_squared > 1.f)
202			inv_camera_dist_squared = 1.f / camera_dist_squared;
203		else
204			inv_camera_dist_squared = 1.f;
205		F32 area = part->mScale.mV[0] * part->mScale.mV[1] * inv_camera_dist_squared;
206		tot_area = llmax(tot_area, area);
207 		
208		if (tot_area > max_area)
209		{
210			break;
211		}
212	
213		count++;
214
215		facep = drawable->getFace(i);
216		if (!facep)
217		{
218			llwarns << "No face found for index " << i << "!" << llendl;
219			continue;
220		}
221
222		facep->setTEOffset(i);
223		const F32 NEAR_PART_DIST_SQ = 5.f*5.f;  // Only discard particles > 5 m from the camera
224		const F32 MIN_PART_AREA = .005f*.005f;  // only less than 5 mm x 5 mm at 1 m from camera
225		
226		if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA)
227		{
228			facep->setSize(0, 0);
229			continue;
230		}
231
232		facep->setSize(4, 6);
233		
234		facep->setViewerObject(this);
235
236		if (part->mFlags & LLPartData::LL_PART_EMISSIVE_MASK)
237		{
238			facep->setState(LLFace::FULLBRIGHT);
239		}
240		else
241		{
242			facep->clearState(LLFace::FULLBRIGHT);
243		}
244
245		facep->mCenterLocal = part->mPosAgent;
246		facep->setFaceColor(part->mColor);
247		facep->setTexture(part->mImagep);
248			
249		//check if this particle texture is replaced by a parcel media texture.
250		if(part->mImagep.notNull() && part->mImagep->hasParcelMedia()) 
251		{
252			part->mImagep->getParcelMedia()->addMediaToFace(facep) ;
253		}
254
255		mPixelArea = tot_area * pixel_meter_ratio;
256		const F32 area_scale = 10.f; // scale area to increase priority a bit
257		facep->setVirtualSize(mPixelArea*area_scale);
258	}
259	for (i = count; i < drawable->getNumFaces(); i++)
260	{
261		LLFace* facep = drawable->getFace(i);
262		if (!facep)
263		{
264			llwarns << "No face found for index " << i << "!" << llendl;
265			continue;
266		}
267		facep->setTEOffset(i);
268		facep->setSize(0, 0);
269	}
270
271	mDrawable->movePartition();
272	LLPipeline::sCompiles++;
273	return TRUE;
274}
275
276void LLVOPartGroup::getGeometry(S32 idx,
277								LLStrider<LLVector4a>& verticesp,
278								LLStrider<LLVector3>& normalsp, 
279								LLStrider<LLVector2>& texcoordsp,
280								LLStrider<LLColor4U>& colorsp, 
281								LLStrider<U16>& indicesp)
282{
283	if (idx >= (S32) mViewerPartGroupp->mParticles.size())
284	{
285		return;
286	}
287
288	const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx]));
289
290	U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex();
291
292	
293	LLVector4a part_pos_agent;
294	part_pos_agent.load3(part.mPosAgent.mV);
295	LLVector4a camera_agent;
296	camera_agent.load3(getCameraPosition().mV); 
297	LLVector4a at;
298	at.setSub(part_pos_agent, camera_agent);
299	LLVector4a up(0, 0, 1);
300	LLVector4a right;
301
302	right.setCross3(at, up);
303	right.normalize3fast();
304	up.setCross3(right, at);
305	up.normalize3fast();
306
307	if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)
308	{
309		LLVector4a normvel;
310		normvel.load3(part.mVelocity.mV);
311		normvel.normalize3fast();
312		LLVector2 up_fracs;
313		up_fracs.mV[0] = normvel.dot3(right).getF32();
314		up_fracs.mV[1] = normvel.dot3(up).getF32();
315		up_fracs.normalize();
316		LLVector4a new_up;
317		LLVector4a new_right;
318
319		//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up;
320		LLVector4a t = right;
321		t.mul(up_fracs.mV[0]);
322		new_up = up;
323		new_up.mul(up_fracs.mV[1]);
324		new_up.add(t);
325
326		//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up;
327		t = right;
328		t.mul(up_fracs.mV[1]);
329		new_right = up;
330		new_right.mul(up_fracs.mV[0]);
331		t.sub(new_right);
332
333		up = new_up;
334		right = t;
335		up.normalize3fast();
336		right.normalize3fast();
337	}
338
339	right.mul(0.5f*part.mScale.mV[0]);
340	up.mul(0.5f*part.mScale.mV[1]);
341
342
343	LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis();
344
345	//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should)
346	// this works because there is actually a 4th float stored after the vertex position which is used as a texture index
347	// also, somebody please VECTORIZE THIS
348
349	LLVector4a ppapu;
350	LLVector4a ppamu;
351
352	ppapu.setAdd(part_pos_agent, up);
353	ppamu.setSub(part_pos_agent, up);
354
355	verticesp->setSub(ppapu, right);
356	(*verticesp++).getF32ptr()[3] = 0.f;
357	verticesp->setSub(ppamu, right);
358	(*verticesp++).getF32ptr()[3] = 0.f;
359	verticesp->setAdd(ppapu, right);
360	(*verticesp++).getF32ptr()[3] = 0.f;
361	verticesp->setAdd(ppamu, right);
362	(*verticesp++).getF32ptr()[3] = 0.f;
363
364	//*verticesp++ = part_pos_agent + up - right;
365	//*verticesp++ = part_pos_agent - up - right;
366	//*verticesp++ = part_pos_agent + up + right;
367	//*verticesp++ = part_pos_agent - up + right;
368
369	*colorsp++ = part.mColor;
370	*colorsp++ = part.mColor;
371	*colorsp++ = part.mColor;
372	*colorsp++ = part.mColor;
373
374	*texcoordsp++ = LLVector2(0.f, 1.f);
375	*texcoordsp++ = LLVector2(0.f, 0.f);
376	*texcoordsp++ = LLVector2(1.f, 1.f);
377	*texcoordsp++ = LLVector2(1.f, 0.f);
378
379	*normalsp++   = normal;
380	*normalsp++   = normal;
381	*normalsp++   = normal;
382	*normalsp++   = normal;
383
384	*indicesp++ = vert_offset + 0;
385	*indicesp++ = vert_offset + 1;
386	*indicesp++ = vert_offset + 2;
387
388	*indicesp++ = vert_offset + 1;
389	*indicesp++ = vert_offset + 3;
390	*indicesp++ = vert_offset + 2;
391}
392
393U32 LLVOPartGroup::getPartitionType() const
394{ 
395	return LLViewerRegion::PARTITION_PARTICLE; 
396}
397
398LLParticlePartition::LLParticlePartition()
399: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB)
400{
401	mRenderPass = LLRenderPass::PASS_ALPHA;
402	mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
403	mPartitionType = LLViewerRegion::PARTITION_PARTICLE;
404	mSlopRatio = 0.f;
405	mLODPeriod = 1;
406}
407
408LLHUDParticlePartition::LLHUDParticlePartition() :
409	LLParticlePartition()
410{
411	mDrawableType = LLPipeline::RENDER_TYPE_HUD_PARTICLES;
412	mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE;
413}
414
415void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count)
416{
417	group->mBufferUsage = mBufferUsage;
418
419	mFaceList.clear();
420
421	LLViewerCamera* camera = LLViewerCamera::getInstance();
422	for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
423	{
424		LLDrawable* drawablep = *i;
425		
426		if (drawablep->isDead())
427		{
428			continue;
429		}
430
431		LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj().get();
432		obj->mDepth = 0.f;
433		
434		if (drawablep->isAnimating())
435		{
436			group->mBufferUsage = GL_STREAM_DRAW_ARB;
437		}
438
439		U32 count = 0;
440		for (S32 j = 0; j < drawablep->getNumFaces(); ++j)
441		{
442			drawablep->updateFaceSize(j);
443
444			LLFace* facep = drawablep->getFace(j);
445			if ( !facep || !facep->hasGeometry())
446			{
447				continue;
448			}
449			
450			count++;
451			facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis();
452			obj->mDepth += facep->mDistance;
453			
454			mFaceList.push_back(facep);
455			vertex_count += facep->getGeomCount();
456			index_count += facep->getIndicesCount();
457			llassert(facep->getIndicesCount() < 65536);
458		}
459		
460		obj->mDepth /= count;
461	}
462}
463
464static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB");
465static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB");
466
467void LLParticlePartition::getGeometry(LLSpatialGroup* group)
468{
469	LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
470	LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ?
471					FTM_REBUILD_GRASS_VB :
472					FTM_REBUILD_PARTICLE_VB);
473
474	std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater());
475
476	U32 index_count = 0;
477	U32 vertex_count = 0;
478
479	group->clearDrawMap();
480
481	LLVertexBuffer* buffer = group->mVertexBuffer;
482
483	LLStrider<U16> indicesp;
484	LLStrider<LLVector4a> verticesp;
485	LLStrider<LLVector3> normalsp;
486	LLStrider<LLVector2> texcoordsp;
487	LLStrider<LLColor4U> colorsp;
488
489	buffer->getVertexStrider(verticesp);
490	buffer->getNormalStrider(normalsp);
491	buffer->getColorStrider(colorsp);
492	buffer->getTexCoord0Strider(texcoordsp);
493	buffer->getIndexStrider(indicesp);
494
495	LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];	
496
497	for (std::vector<LLFace*>::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
498	{
499		LLFace* facep = *i;
500		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
501		facep->setGeomIndex(vertex_count);
502		facep->setIndicesIndex(index_count);
503		facep->setVertexBuffer(buffer);
504		facep->setPoolType(LLDrawPool::POOL_ALPHA);
505		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp);
506		
507		vertex_count += facep->getGeomCount();
508		index_count += facep->getIndicesCount();
509
510		S32 idx = draw_vec.size()-1;
511
512		BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
513		F32 vsize = facep->getVirtualSize();
514
515		if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
516			draw_vec[idx]->mTexture == facep->getTexture() &&
517			(U16) (draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount()) <= (U32) gGLManager.mGLMaxVertexRange &&
518			//draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
519			draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 &&
520			draw_vec[idx]->mFullbright == fullbright)
521		{
522			draw_vec[idx]->mCount += facep->getIndicesCount();
523			draw_vec[idx]->mEnd += facep->getGeomCount();
524			draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
525		}
526		else
527		{
528			U32 start = facep->getGeomIndex();
529			U32 end = start + facep->getGeomCount()-1;
530			U32 offset = facep->getIndicesStart();
531			U32 count = facep->getIndicesCount();
532			LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), 
533				//facep->getTexture(),
534				buffer, fullbright); 
535			info->mExtents[0] = group->mObjectExtents[0];
536			info->mExtents[1] = group->mObjectExtents[1];
537			info->mVSize = vsize;
538			draw_vec.push_back(info);
539			//for alpha sorting
540			facep->setDrawInfo(info);
541		}
542	}
543
544	buffer->flush();
545	mFaceList.clear();
546}
547
548F32 LLParticlePartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
549{
550	return 1024.f;
551}
552
553U32 LLVOHUDPartGroup::getPartitionType() const
554{
555	return LLViewerRegion::PARTITION_HUD_PARTICLE; 
556}
557
558LLDrawable* LLVOHUDPartGroup::createDrawable(LLPipeline *pipeline)
559{
560	pipeline->allocDrawable(this);
561	mDrawable->setLit(FALSE);
562	mDrawable->setRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
563	return mDrawable;
564}
565
566LLVector3 LLVOHUDPartGroup::getCameraPosition() const
567{
568	return LLVector3(-1,0,0);
569}
570