aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llvovolume.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llvovolume.cpp1662
1 files changed, 1059 insertions, 603 deletions
diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp
index 6791acd..f425687 100644
--- a/linden/indra/newview/llvovolume.cpp
+++ b/linden/indra/newview/llvovolume.cpp
@@ -42,7 +42,6 @@
42#include "material_codes.h" 42#include "material_codes.h"
43#include "message.h" 43#include "message.h"
44#include "object_flags.h" 44#include "object_flags.h"
45
46#include "llagent.h" 45#include "llagent.h"
47#include "lldrawable.h" 46#include "lldrawable.h"
48#include "lldrawpoolsimple.h" 47#include "lldrawpoolsimple.h"
@@ -64,14 +63,14 @@
64#include "pipeline.h" 63#include "pipeline.h"
65 64
66const S32 MIN_QUIET_FRAMES_COALESCE = 30; 65const S32 MIN_QUIET_FRAMES_COALESCE = 30;
67 66const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
68//#define LLDEBUG_DISPLAY_LODS 1 67const F32 FORCE_CULL_AREA = 8.f;
69 68
70BOOL gAnimateTextures = TRUE; 69BOOL gAnimateTextures = TRUE;
70extern BOOL gHideSelectedObjects;
71 71
72F32 LLVOVolume::sLODFactor = 1.f; 72F32 LLVOVolume::sLODFactor = 1.f;
73F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop 73F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
74F32 LLVOVolume::sLODComplexityDistanceBias = 0.0f;//Changing this to zero makes all prims LOD equally regardless of complexity
75F32 LLVOVolume::sDistanceFactor = 1.0f; 74F32 LLVOVolume::sDistanceFactor = 1.0f;
76S32 LLVOVolume::sNumLODChanges = 0; 75S32 LLVOVolume::sNumLODChanges = 0;
77 76
@@ -79,17 +78,14 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
79 : LLViewerObject(id, pcode, regionp), 78 : LLViewerObject(id, pcode, regionp),
80 mVolumeImpl(NULL) 79 mVolumeImpl(NULL)
81{ 80{
81 mTexAnimMode = 0;
82 mRelativeXform.identity(); 82 mRelativeXform.identity();
83 mRelativeXformInvTrans.identity(); 83 mRelativeXformInvTrans.identity();
84 84
85 mLOD = MIN_LOD; 85 mLOD = MIN_LOD;
86 mInited = FALSE; 86 mInited = FALSE;
87 mAllTEsSame = FALSE;
88 mTextureAnimp = NULL; 87 mTextureAnimp = NULL;
89 mGlobalVolume = FALSE; 88 mGlobalVolume = FALSE;
90
91 mTextureAnimp = NULL;
92 mAllTEsSame = FALSE;
93 mVObjRadius = LLVector3(1,1,0.5f).magVec(); 89 mVObjRadius = LLVector3(1,1,0.5f).magVec();
94 mNumFaces = 0; 90 mNumFaces = 0;
95} 91}
@@ -142,12 +138,19 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
142 mTextureAnimp->reset(); 138 mTextureAnimp->reset();
143 } 139 }
144 } 140 }
141 mTexAnimMode = 0;
145 mTextureAnimp->unpackTAMessage(mesgsys, block_num); 142 mTextureAnimp->unpackTAMessage(mesgsys, block_num);
146 } 143 }
147 else 144 else
148 { 145 {
149 delete mTextureAnimp; 146 if (mTextureAnimp)
150 mTextureAnimp = NULL; 147 {
148 delete mTextureAnimp;
149 mTextureAnimp = NULL;
150 gPipeline.markTextured(mDrawable);
151 mFaceMappingChanged = TRUE;
152 mTexAnimMode = 0;
153 }
151 } 154 }
152 155
153 // Unpack volume data 156 // Unpack volume data
@@ -193,8 +196,8 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
193 // Well, crap, there's something bogus in the data that we're unpacking. 196 // Well, crap, there's something bogus in the data that we're unpacking.
194 dp->dumpBufferToLog(); 197 dp->dumpBufferToLog();
195 llwarns << "Flushing cache files" << llendl; 198 llwarns << "Flushing cache files" << llendl;
196 char mask[LL_MAX_PATH]; 199 char mask[LL_MAX_PATH]; /* Flawfinder: ignore */
197 sprintf(mask, "%s*.slc", gDirUtilp->getDirDelimiter().c_str()); 200 snprintf(mask, LL_MAX_PATH, "%s*.slc", gDirUtilp->getDirDelimiter().c_str()); /* Flawfinder: ignore */
198 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask); 201 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask);
199// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl; 202// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl;
200 llwarns << "Bogus TE data in " << getID() << llendl; 203 llwarns << "Bogus TE data in " << getID() << llendl;
@@ -219,12 +222,16 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
219 mTextureAnimp->reset(); 222 mTextureAnimp->reset();
220 } 223 }
221 } 224 }
225 mTexAnimMode = 0;
222 mTextureAnimp->unpackTAMessage(*dp); 226 mTextureAnimp->unpackTAMessage(*dp);
223 } 227 }
224 else 228 else if (mTextureAnimp)
225 { 229 {
226 delete mTextureAnimp; 230 delete mTextureAnimp;
227 mTextureAnimp = NULL; 231 mTextureAnimp = NULL;
232 gPipeline.markTextured(mDrawable);
233 mFaceMappingChanged = TRUE;
234 mTexAnimMode = 0;
228 } 235 }
229 } 236 }
230 else 237 else
@@ -247,65 +254,142 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
247} 254}
248 255
249 256
250BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) 257void LLVOVolume::animateTextures()
251{ 258{
252 LLViewerObject::idleUpdate(agent, world, time); 259 F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f;
253 260 S32 result;
254 /////////////////////// 261
255 // 262 if (result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot))
256 // Do texture animation stuff
257 //
258
259 if (mTextureAnimp && gAnimateTextures)
260 { 263 {
261 F32 off_s, off_t, scale_s, scale_t, rot; 264 if (!mTexAnimMode)
262 S32 result; 265 {
263 if ((result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot))) 266 mFaceMappingChanged = TRUE;
267 gPipeline.markTextured(mDrawable);
268 }
269 mTexAnimMode = result | mTextureAnimp->mMode;
270
271 S32 start=0, end=mDrawable->getNumFaces()-1;
272 if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end)
273 {
274 start = end = mTextureAnimp->mFace;
275 }
276
277 for (S32 i = start; i <= end; i++)
264 { 278 {
265 U8 has_bump = 0; 279 LLQuaternion quat;
266 if (mTextureAnimp->mFace <= -1) 280 LLVector3 scale(1,1,1);
281
282 LLFace* facep = mDrawable->getFace(i);
283 const LLTextureEntry* te = facep->getTextureEntry();
284 LLMatrix4& tex_mat = facep->mTextureMatrix;
285
286 if (!te)
287 {
288 continue;
289 }
290 if (!(result & LLViewerTextureAnim::ROTATE))
291 {
292 te->getRotation(&rot);
293 }
294
267 { 295 {
268 S32 face; 296 F32 axis = -1;
269 for (face = 0; face < getNumTEs(); face++) 297 F32 s,t;
298 te->getScale(&s,&t);
299 if (s < 0)
270 { 300 {
271 if (result & LLViewerTextureAnim::TRANSLATE) 301 axis = -axis;
272 {
273 setTEOffset(face, off_s, off_t);
274 }
275 if (result & LLViewerTextureAnim::SCALE)
276 {
277 setTEScale(face, scale_s, scale_t);
278 }
279 if (result & LLViewerTextureAnim::ROTATE)
280 {
281 setTERotation(face, rot);
282 }
283 has_bump |= getTE(face)->getBumpmap();
284 } 302 }
303 if (t < 0)
304 {
305 axis = -axis;
306 }
307 quat.setQuat(rot, 0, 0, axis);
285 } 308 }
286 else if (mTextureAnimp->mFace < getNumTEs()) 309
310 if (!(result & LLViewerTextureAnim::TRANSLATE))
287 { 311 {
288 if (result & LLViewerTextureAnim::TRANSLATE) 312 te->getOffset(&off_s,&off_t);
313 }
314
315 LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f);
316
317 tex_mat.identity();
318 tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
319 tex_mat.rotate(quat);
320
321 if (!(result & LLViewerTextureAnim::SCALE))
322 {
323 te->getScale(&scale_s, &scale_t);
324 }
325
326 {
327 scale.setVec(scale_s, scale_t, 1.f);
328 LLMatrix4 mat;
329 mat.initAll(scale, LLQuaternion(), LLVector3());
330 tex_mat *= mat;
331 }
332
333 tex_mat.translate(trans);
334 }
335 }
336 else
337 {
338 if (mTexAnimMode && mTextureAnimp->mRate == 0)
339 {
340 U8 start, count;
341
342 if (mTextureAnimp->mFace == -1)
343 {
344 start = 0;
345 count = getNumTEs();
346 }
347 else
348 {
349 start = (U8) mTextureAnimp->mFace;
350 count = 1;
351 }
352
353 for (S32 i = start; i < start + count; i++)
354 {
355 if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE)
289 { 356 {
290 setTEOffset(mTextureAnimp->mFace, off_s, off_t); 357 setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT);
291 } 358 }
292 if (result & LLViewerTextureAnim::SCALE) 359 if (mTexAnimMode & LLViewerTextureAnim::SCALE)
293 { 360 {
294 setTEScale(mTextureAnimp->mFace, scale_s, scale_t); 361 setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT);
295 } 362 }
296 if (result & LLViewerTextureAnim::ROTATE) 363 if (mTexAnimMode & LLViewerTextureAnim::ROTATE)
297 { 364 {
298 setTERotation(mTextureAnimp->mFace, rot); 365 setTERotation(i, mTextureAnimp->mRot);
299 } 366 }
300 has_bump |= getTE(mTextureAnimp->mFace)->getBumpmap();
301 }
302// mFaceMappingChanged = TRUE;
303 if (mDrawable->isVisible())
304 {
305 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, TRUE);
306 } 367 }
368
369 gPipeline.markTextured(mDrawable);
370 mFaceMappingChanged = TRUE;
371 mTexAnimMode = 0;
307 } 372 }
308 } 373 }
374}
375BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
376{
377 LLViewerObject::idleUpdate(agent, world, time);
378
379 if (mDead || mDrawable.isNull())
380 {
381 return TRUE;
382 }
383
384 ///////////////////////
385 //
386 // Do texture animation stuff
387 //
388
389 if (mTextureAnimp && gAnimateTextures)
390 {
391 animateTextures();
392 }
309 393
310 // Dispatch to implementation 394 // Dispatch to implementation
311 if (mVolumeImpl) 395 if (mVolumeImpl)
@@ -318,75 +402,45 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
318 402
319void LLVOVolume::updateTextures(LLAgent &agent) 403void LLVOVolume::updateTextures(LLAgent &agent)
320{ 404{
321 405// LLFastTimer t(LLFastTimer::FTM_TEMP6);
406 const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds
407 if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
408 {
409 if (mDrawable->isVisible())
410 {
411 updateTextures();
412 }
413 }
322} 414}
323 415
324//static 416void LLVOVolume::updateTextures()
325F32 LLVOVolume::getTextureVirtualSize(const LLFace* face)
326{ 417{
327 //LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; 418 // Update the pixel area of all faces
328 //F32 pixel_area = 1.f/llmin(llmax(tdim.mV[0] * tdim.mV[1], 1.f), 10.f);
329 LLVector3 cross_vec = (face->mExtents[1] - face->mExtents[0]);
330
331
332 LLVector3 lookAt = (face->getPositionAgent()-gCamera->getOrigin());
333 F32 dist = lookAt.normVec();
334 419
335 F32 face_area; 420 if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
336
337 if (face->isState(LLFace::GLOBAL))
338 { 421 {
339 face_area = cross_vec.mV[0]*cross_vec.mV[1]*fabsf(lookAt.mV[2]) + 422 return;
340 cross_vec.mV[1]*cross_vec.mV[2]*fabsf(lookAt.mV[0]) +
341 cross_vec.mV[0]*cross_vec.mV[2]*fabsf(lookAt.mV[1]);
342 }
343 else
344 {
345 face_area = cross_vec.mV[0]*cross_vec.mV[1] +
346 cross_vec.mV[1]*cross_vec.mV[2] +
347 cross_vec.mV[0]*cross_vec.mV[2];
348 } 423 }
349 424
350 if (face_area <= 0) 425 if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible())
351 { 426 {
352 return 0.f; 427 return;
353 } 428 }
354 429
355 F32 view = llmax(lookAt*gCamera->getAtAxis(), 0.5f); 430 mTextureUpdateTimer.reset();
356 F32 dist_ramp = dist * view/face_area;
357 //ramp down distance for things closer than 16 m * lookAt
358 dist /= dist_ramp;
359 dist *= dist;
360 dist *= dist_ramp;
361
362 F32 dist_ratio = face_area / llmax(dist, 0.1f);
363 F32 pixel_area = dist_ratio*gCamera->getScreenPixelArea();
364 431
365 return view*pixel_area; 432 F32 old_area = mPixelArea;
366} 433 mPixelArea = 0.f;
367
368void LLVOVolume::updateTextures(S32 lod)
369{
370 // Update the image levels of all textures...
371 // First we do some quick checks.
372 434
373 // This doesn't take into account whether the object is in front
374 // or behind...
375
376 if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull() || !mDrawable->isVisible())
377 {
378 return;
379 }
380
381 const S32 num_faces = mDrawable->getNumFaces(); 435 const S32 num_faces = mDrawable->getNumFaces();
382 436 F32 min_vsize=999999999.f, max_vsize=0.f;
383 for (S32 i = 0; i < num_faces; i++) 437 for (S32 i = 0; i < num_faces; i++)
384 { 438 {
385 const LLFace* face = mDrawable->getFace(i); 439 LLFace* face = mDrawable->getFace(i);
386 const LLTextureEntry *te = face->getTextureEntry(); 440 const LLTextureEntry *te = face->getTextureEntry();
387 LLViewerImage *imagep = face->getTexture(); 441 LLViewerImage *imagep = face->getTexture();
388 442 if (!imagep || !te ||
389 if (!imagep || !te) 443 face->mExtents[0] == face->mExtents[1])
390 { 444 {
391 continue; 445 continue;
392 } 446 }
@@ -395,25 +449,87 @@ void LLVOVolume::updateTextures(S32 lod)
395 449
396 if (isHUDAttachment()) 450 if (isHUDAttachment())
397 { 451 {
398 vsize = (F32) (imagep->getWidth(0) * imagep->getHeight(0)); 452 F32 area = (F32) gCamera->getScreenPixelArea();
453 vsize = area;
399 imagep->setBoostLevel(LLViewerImage::BOOST_HUD); 454 imagep->setBoostLevel(LLViewerImage::BOOST_HUD);
455 face->setPixelArea(area); // treat as full screen
400 } 456 }
401 else 457 else
402 { 458 {
403 vsize = getTextureVirtualSize(face); 459 vsize = getTextureVirtualSize(face);
404 } 460 }
405 461
462 mPixelArea = llmax(mPixelArea, face->getPixelArea());
463 face->setVirtualSize(vsize);
406 imagep->addTextureStats(vsize); 464 imagep->addTextureStats(vsize);
407 465 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
408 466 {
409 U8 bump = te->getBumpmap(); 467 if (vsize < min_vsize) min_vsize = vsize;
410 if( te && bump) 468 if (vsize > max_vsize) max_vsize = vsize;
469 }
470 else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
411 { 471 {
412 gBumpImageList.addTextureStats( bump, imagep->getID(), vsize, 1, 1); 472 F32 pri = imagep->getDecodePriority();
473 if (pri < min_vsize) min_vsize = pri;
474 if (pri > max_vsize) max_vsize = pri;
413 } 475 }
476 else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
477 {
478 F32 pri = mPixelArea;
479 if (pri < min_vsize) min_vsize = pri;
480 if (pri > max_vsize) max_vsize = pri;
481 }
482 }
483
484 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
485 {
486 setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
487 }
488 else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
489 {
490 setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
491 }
492 else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
493 {
494 setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
495 }
496
497 if (mPixelArea == 0)
498 { //flexi phasing issues make this happen
499 mPixelArea = old_area;
414 } 500 }
415} 501}
416 502
503F32 LLVOVolume::getTextureVirtualSize(LLFace* face)
504{
505 //get area of circle around face
506 LLVector3 center = face->getPositionAgent();
507 LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f;
508
509 F32 face_area = LLPipeline::calcPixelArea(center, size, *gCamera);
510
511 face->setPixelArea(face_area);
512
513 if (face_area <= 0)
514 {
515 return 0.f;
516 }
517
518 //get area of circle in texture space
519 LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0];
520 F32 texel_area = (tdim * 0.5f).magVecSquared()*3.14159f;
521 if (texel_area <= 0)
522 {
523 // Probably animated, use default
524 texel_area = 1.f;
525 }
526
527 //apply texel area to face area to get accurate ratio
528 face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
529
530 return face_area;
531}
532
417BOOL LLVOVolume::isActive() const 533BOOL LLVOVolume::isActive() const
418{ 534{
419 return !mStatic || mTextureAnimp || isAttachment() || (mVolumeImpl && mVolumeImpl->isActive()); 535 return !mStatic || mTextureAnimp || isAttachment() || (mVolumeImpl && mVolumeImpl->isActive());
@@ -455,7 +571,7 @@ void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped)
455 571
456 //since drawable transforms do not include scale, changing volume scale 572 //since drawable transforms do not include scale, changing volume scale
457 //requires an immediate rebuild of volume verts. 573 //requires an immediate rebuild of volume verts.
458 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); 574 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE);
459 } 575 }
460} 576}
461 577
@@ -463,16 +579,7 @@ LLFace* LLVOVolume::addFace(S32 f)
463{ 579{
464 const LLTextureEntry* te = getTE(f); 580 const LLTextureEntry* te = getTE(f);
465 LLViewerImage* imagep = getTEImage(f); 581 LLViewerImage* imagep = getTEImage(f);
466 LLDrawPool* poolp; 582 return mDrawable->addFace(te, imagep);
467 if (isHUDAttachment())
468 {
469 poolp = gPipeline.getPool(LLDrawPool::POOL_HUD);
470 }
471 else
472 {
473 poolp = LLPipeline::getPoolFromTE(te, imagep);
474 }
475 return mDrawable->addFace(poolp, imagep);
476} 583}
477 584
478LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) 585LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
@@ -480,7 +587,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
480 pipeline->allocDrawable(this); 587 pipeline->allocDrawable(this);
481 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); 588 mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
482 589
483 S32 max_tes_to_set = calcAllTEsSame() ? 1 : getNumTEs(); 590 S32 max_tes_to_set = getNumTEs();
484 for (S32 i = 0; i < max_tes_to_set; i++) 591 for (S32 i = 0; i < max_tes_to_set; i++)
485 { 592 {
486 LLFace* face = addFace(i); 593 LLFace* face = addFace(i);
@@ -537,10 +644,6 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
537 } 644 }
538 mGlobalVolume = (mVolumeImpl && mVolumeImpl->isVolumeGlobal()); 645 mGlobalVolume = (mVolumeImpl && mVolumeImpl->isVolumeGlobal());
539 646
540 //MSMSM Recompute LOD here in case the object was just created,
541 // its LOD might be incorrectly set to minumum detail...
542 calcLOD();
543
544 if (LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) 647 if (LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique())))
545 { 648 {
546 mFaceMappingChanged = TRUE; 649 mFaceMappingChanged = TRUE;
@@ -555,45 +658,12 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
555 return FALSE; 658 return FALSE;
556} 659}
557 660
558
559F32 LLVOVolume::computeLODProfilePathComplexityBias(){
560 //compute a complexity cost from 0 to 1.0 where the 'simplest' prim has a cost of 0.0
561 // and the 'heaviest' prim has a cost of 1.0
562// LLVolume* volume = getVolume();
563 F32 complexity = 0.0f;
564// const LLVolumeParams& params = volume->getParams();
565// U8 type = volume->getPathType();
566// U8 pcode = this->getPCode();
567// U8 proftype = volume->getProfileType();
568
569 //if(params.getHollow()>0.0f){// || (proftype == 1) || (proftype == 0)){
570 //If it is hollow, or a cube/pyramid(subdivided), the complexity is roughly doubled
571 // complexity+=0.5f;
572 //}
573
574 if(this->getVolume()->getProfile().mParams.getCurveType()==LL_PCODE_PROFILE_SQUARE &&
575 this->getVolume()->getPath().mParams.getCurveType()==LL_PCODE_PATH_LINE)
576 {
577 //Object is a cube so bias it heavily since cubes are subdivided alot.
578// this->setDebugText("CUBE");
579 complexity += 1.0f;
580 }
581
582// if(params.getTwist() != params.getTwistBegin()){
583 //if there is twist.. the complexity is bumped
584// complexity+=0.25f;
585// }
586// if(type != LL_PCODE_PATH_LINE)//If the path is not a line it is more complex
587// complexity+=0.2f;
588 return complexity * sLODComplexityDistanceBias;
589}
590
591S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) 661S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius)
592{ 662{
593 S32 cur_detail; 663 S32 cur_detail;
594 // We've got LOD in the profile, and in the twist. Use radius. 664 // We've got LOD in the profile, and in the twist. Use radius.
595 F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; 665 F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance;
596 cur_detail = LLVolumeLODGroup::getDetailFromTan(tan_angle); 666 cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f));
597 return cur_detail; 667 return cur_detail;
598} 668}
599 669
@@ -603,62 +673,32 @@ BOOL LLVOVolume::calcLOD()
603 { 673 {
604 return FALSE; 674 return FALSE;
605 } 675 }
676
606 S32 cur_detail = 0; 677 S32 cur_detail = 0;
607 /*if (isHUDAttachment()) 678
679 F32 radius = mVolumep->mLODScaleBias.scaledVec(getScale()).magVec();
680 F32 distance = mDrawable->mDistanceWRTCamera;
681 distance *= sDistanceFactor;
682
683 F32 rampDist = LLVOVolume::sLODFactor * 2;
684
685 if (distance < rampDist)
608 { 686 {
609 cur_detail = LLVolumeLODGroup::NUM_LODS-1; // max detail 687 // Boost LOD when you're REALLY close
688 distance *= 1.0f/rampDist;
689 distance *= distance;
690 distance *= rampDist;
610 } 691 }
611 else*/ 692
612 { 693 // DON'T Compensate for field of view changing on FOV zoom.
613 F32 radius = (mVolumep->mLODScaleBias.scaledVec(getScale())).magVec(); 694 distance *= 3.14159f/3.f;
614 F32 distance = mDrawable->mDistanceWRTCamera;
615 distance *= sDistanceFactor;
616
617 F32 rampDist = LLVOVolume::sLODFactor * 2;
618
619 if (distance < rampDist)
620 {
621 // Boost LOD when you're REALLY close
622 distance *= 1.0f/rampDist;
623 distance *= distance;
624 distance *= rampDist;
625 }
626 else
627 {
628 //Now adjust the computed distance by some factor based on the geometric complexity of the primitive
629 distance += computeLODProfilePathComplexityBias();
630 }
631 // Compensate for field of view changing on FOV zoom.
632 distance *= gCamera->getView();
633
634 cur_detail = computeLODDetail(distance, radius);
635 695
636 //update textures with what the real LOD is 696 cur_detail = computeLODDetail(llround(distance, 0.01f),
637 updateTextures(cur_detail); 697 llround(radius, 0.01f));
638
639 if(cur_detail != mLOD)
640 {
641 // Here we test whether the LOD is increasing or decreasing to introduce a slop factor
642 if(cur_detail < mLOD)
643 {
644 // Viewer is moving away from the object
645 // so bias our LOD by adding a fixed amount to the distance.
646 // This will reduce the problem of LOD twitching when the
647 // user makes slight movements near the LOD transition threshhold.
648 F32 test_distance = distance - (distance*sLODSlopDistanceFactor/(1.0f+sLODFactor));
649 if(test_distance < 0.0f) test_distance = 0.0f;
650 S32 potential_detail = computeLODDetail( test_distance, radius );
651 if(potential_detail >= mLOD )
652 { //The LOD has truly not changed
653 cur_detail = mLOD;
654 }
655 }
656 }
657 }
658 698
659 if (cur_detail != mLOD) 699 if (cur_detail != mLOD)
660 { 700 {
661 mAppAngle = (F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG; 701 mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
662 mLOD = cur_detail; 702 mLOD = cur_detail;
663 return TRUE; 703 return TRUE;
664 } 704 }
@@ -676,17 +716,10 @@ BOOL LLVOVolume::updateLOD()
676 } 716 }
677 717
678 BOOL lod_changed = calcLOD(); 718 BOOL lod_changed = calcLOD();
679 719
680#if LLDEBUG_DISPLAY_LODS
681 //MS Enable this to display LOD numbers on objects
682 std::ostringstream msg;
683 msg << cur_detail;//((cur_detail<mLOD)?"-":cur_detail==mLOD?"=":"+") << (int)cur_detail << " , " << mDrawable->mDistanceWRTCamera << " , " << ((LLVOVolume::sLODFactor*mVObjRadius)/mDrawable->mDistanceWRTCamera);
684 this->setDebugText(msg.str());
685#endif
686
687 if (lod_changed) 720 if (lod_changed)
688 { 721 {
689 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); 722 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
690 mLODChanged = TRUE; 723 mLODChanged = TRUE;
691 } 724 }
692 725
@@ -703,8 +736,8 @@ BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp)
703 736
704 if (!mDrawable->isRoot()) 737 if (!mDrawable->isRoot())
705 { 738 {
706 // parent is dynamic, so I'll need to share its drawable, must rebuild to share drawables 739 // rebuild vertices in parent relative space
707 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); 740 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
708 741
709 if (mDrawable->isActive() && !parentp->isActive()) 742 if (mDrawable->isActive() && !parentp->isActive())
710 { 743 {
@@ -723,7 +756,7 @@ void LLVOVolume::updateFaceFlags()
723{ 756{
724 for (S32 i = 0; i < getVolume()->getNumFaces(); i++) 757 for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
725 { 758 {
726 LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); 759 LLFace *face = mDrawable->getFace(i);
727 BOOL fullbright = getTE(i)->getFullbright(); 760 BOOL fullbright = getTE(i)->getFullbright();
728 face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); 761 face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT);
729 762
@@ -739,10 +772,17 @@ void LLVOVolume::updateFaceFlags()
739 { 772 {
740 face->setState(LLFace::HUD_RENDER); 773 face->setState(LLFace::HUD_RENDER);
741 } 774 }
742 if (getAllTEsSame()) 775 }
743 { 776}
744 break; // only 1 face 777
745 } 778void LLVOVolume::setParent(LLViewerObject* parent)
779{
780 LLViewerObject::setParent(parent);
781 if (mDrawable)
782 {
783 gPipeline.markMoved(mDrawable);
784 mVolumeChanged = TRUE;
785 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
746 } 786 }
747} 787}
748 788
@@ -750,104 +790,87 @@ void LLVOVolume::updateFaceFlags()
750void LLVOVolume::regenFaces() 790void LLVOVolume::regenFaces()
751{ 791{
752 // remove existing faces 792 // remove existing faces
753 // use mDrawable->getVOVolume() in case of shared drawables 793 BOOL count_changed = mNumFaces != getNumTEs();
754 mDrawable->getVOVolume()->deleteFaces(this); 794
755 mFaceIndexOffset = mDrawable->getNumFaces(); 795 if (count_changed)
756 // add new faces 796 {
757 mNumFaces = getAllTEsSame() ? 1 : getNumTEs(); 797 deleteFaces();
798 // add new faces
799 mNumFaces = getNumTEs();
800 }
801
758 for (S32 i = 0; i < mNumFaces; i++) 802 for (S32 i = 0; i < mNumFaces; i++)
759 { 803 {
760 LLFace* facep = addFace(i); 804 LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i);
761 facep->setViewerObject(this);
762 facep->setTEOffset(i); 805 facep->setTEOffset(i);
806 facep->setTexture(getTEImage(i));
807 facep->setViewerObject(this);
808 }
809
810 if (!count_changed)
811 {
812 updateFaceFlags();
763 } 813 }
764 // Need to do this as texture entries may not correspond to faces any more!
765 mDrawable->updateTexture();
766 gPipeline.markMaterialed(mDrawable);
767} 814}
768 815
769BOOL LLVOVolume::genTriangles(BOOL force_global) 816BOOL LLVOVolume::genBBoxes(BOOL force_global)
770{ 817{
771 BOOL res = TRUE; 818 BOOL res = TRUE;
772 819
773 LLVector3 min,max; 820 LLVector3 min,max;
774 821
775 if (getAllTEsSame()) 822 BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION);
823
824 for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
776 { 825 {
777 setupSingleFace(mFaceIndexOffset); 826 LLFace *face = mDrawable->getFace(i);
778 LLFace *face = mDrawable->getFace(mFaceIndexOffset); 827 res &= face->genVolumeBBoxes(*getVolume(), i,
779 S32 num_faces = getVolume()->getNumFaces(); 828 mRelativeXform, mRelativeXformInvTrans,
780 res = face->genVolumeTriangles(*getVolume(), 0, num_faces-1, 829 mGlobalVolume | force_global);
781 mRelativeXform, mRelativeXformInvTrans,
782 mGlobalVolume | force_global);
783 830
784 if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) 831 if (rebuild)
785 {
786 min = face->mExtents[0];
787 max = face->mExtents[1];
788 }
789 mWereAllTEsSame = TRUE;
790 }
791 else
792 {
793 for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
794 { 832 {
795 LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); 833 if (i == 0)
796 res &= face->genVolumeTriangles(*getVolume(), i,
797 mRelativeXform, mRelativeXformInvTrans,
798 mGlobalVolume | force_global);
799
800 if (mDrawable->isState(LLDrawable::REBUILD_VOLUME))
801 { 834 {
802 if (i == 0) 835 min = face->mExtents[0];
803 { 836 max = face->mExtents[1];
804 min = face->mExtents[0]; 837 }
805 max = face->mExtents[1]; 838 else
806 } 839 {
807 else 840 for (U32 i = 0; i < 3; i++)
808 { 841 {
809 for (U32 i = 0; i < 3; i++) 842 if (face->mExtents[0].mV[i] < min.mV[i])
810 { 843 {
811 if (face->mExtents[0].mV[i] < min.mV[i]) 844 min.mV[i] = face->mExtents[0].mV[i];
812 { 845 }
813 min.mV[i] = face->mExtents[0].mV[i]; 846 if (face->mExtents[1].mV[i] > max.mV[i])
814 } 847 {
815 if (face->mExtents[1].mV[i] > max.mV[i]) 848 max.mV[i] = face->mExtents[1].mV[i];
816 {
817 max.mV[i] = face->mExtents[1].mV[i];
818 }
819 } 849 }
820 } 850 }
821 } 851 }
822 } 852 }
823 mWereAllTEsSame = FALSE;
824 } 853 }
825 854
826 if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) 855 if (rebuild)
827 { 856 {
828 mDrawable->setSpatialExtents(min,max); 857 mDrawable->setSpatialExtents(min,max);
829 if (!isVolumeGlobal()) 858 mDrawable->setPositionGroup((min+max)*0.5f);
830 { 859 //bounding boxes changed, update texture priorities
831 mDrawable->setPositionGroup((min+max)*0.5f); 860 updateTextures();
832 }
833 else
834 {
835 mDrawable->setPositionGroup(getPosition());
836 }
837
838 updateRadius();
839 mDrawable->updateBinRadius();
840 mDrawable->movePartition();
841 } 861 }
842 862
863 updateRadius();
864 mDrawable->movePartition();
865
843 return res; 866 return res;
844} 867}
845 868
846void LLVOVolume::updateRelativeXform(BOOL global_volume) 869void LLVOVolume::updateRelativeXform()
847{ 870{
848 if (mVolumeImpl) 871 if (mVolumeImpl)
849 { 872 {
850 mVolumeImpl->updateRelativeXform(global_volume); 873 mVolumeImpl->updateRelativeXform();
851 return; 874 return;
852 } 875 }
853 876
@@ -873,12 +896,25 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume)
873 LLVector4(y_axis, 0.f), 896 LLVector4(y_axis, 0.f),
874 LLVector4(z_axis, 0.f), 897 LLVector4(z_axis, 0.f),
875 LLVector4(delta_pos, 1.f)); 898 LLVector4(delta_pos, 1.f));
876 899
877 x_axis.normVec();
878 y_axis.normVec();
879 z_axis.normVec();
880 900
881 mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); 901 // compute inverse transpose for normals
902 // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
903 // mRelativeXformInvTrans.invert();
904 // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
905 // grumble - invert is NOT a matrix invert, so we do it by hand:
906
907 LLMatrix3 rot_inverse = LLMatrix3(~delta_rot);
908
909 LLMatrix3 scale_inverse;
910 scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX],
911 LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY],
912 LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]);
913
914
915 mRelativeXformInvTrans = rot_inverse * scale_inverse;
916
917 mRelativeXformInvTrans.transpose();
882 } 918 }
883 else 919 else
884 { 920 {
@@ -905,34 +941,35 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume)
905 LLVector4(z_axis, 0.f), 941 LLVector4(z_axis, 0.f),
906 LLVector4(pos, 1.f)); 942 LLVector4(pos, 1.f));
907 943
908 x_axis.normVec(); 944 // compute inverse transpose for normals
909 y_axis.normVec(); 945 LLMatrix3 rot_inverse = LLMatrix3(~rot);
910 z_axis.normVec(); 946
911 947 LLMatrix3 scale_inverse;
912 mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); 948 scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX],
949 LLVector3(0.0, 1.0, 0.0) / scale.mV[VY],
950 LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]);
951
952
953 mRelativeXformInvTrans = rot_inverse * scale_inverse;
954
955 mRelativeXformInvTrans.transpose();
913 } 956 }
914} 957}
915 958
916BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) 959BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
917{ 960{
918 LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES); 961 LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES);
919 962
920 if (mVolumeImpl != NULL) 963 if (mVolumeImpl != NULL)
921 { 964 {
922 LLFastTimer t(LLFastTimer::FTM_GEN_FLEX); 965 LLFastTimer t(LLFastTimer::FTM_GEN_FLEX);
923 BOOL res = mVolumeImpl->doUpdateGeometry(drawable); 966 BOOL res = mVolumeImpl->doUpdateGeometry(drawable);
924 updateFaceFlags(); 967 updateFaceFlags();
925 if (res)
926 {
927 drawable->clearState(LLDrawable::REBUILD_GEOMETRY);
928 }
929
930 return res; 968 return res;
931 } 969 }
932 970
933 BOOL compiled = FALSE; 971 BOOL compiled = FALSE;
934 BOOL change_shared = FALSE; 972
935
936 updateRelativeXform(); 973 updateRelativeXform();
937 974
938 if (mDrawable.isNull()) // Not sure why this is happening, but it is... 975 if (mDrawable.isNull()) // Not sure why this is happening, but it is...
@@ -940,28 +977,23 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
940 return TRUE; // No update to complete 977 return TRUE; // No update to complete
941 } 978 }
942 979
943 calcAllTEsSame(); 980 if (mVolumeChanged || mFaceMappingChanged )
944
945 if (mVolumeChanged || mFaceMappingChanged || change_shared)
946 { 981 {
947 compiled = TRUE; 982 compiled = TRUE;
948 mInited = TRUE; 983 mInited = TRUE;
949 984
985 if (mVolumeChanged)
950 { 986 {
951 LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME); 987 LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME);
952 LLVolumeParams volume_params = getVolume()->getParams(); 988 LLVolumeParams volume_params = getVolume()->getParams();
953 setVolume(volume_params, 0); 989 setVolume(volume_params, 0);
954 } 990 drawable->setState(LLDrawable::REBUILD_VOLUME);
955 drawable->setState(LLDrawable::REBUILD_GEOMETRY);
956 if (mVolumeChanged || change_shared)
957 {
958 drawable->setState(LLDrawable::REBUILD_LIGHTING);
959 } 991 }
960 992
961 { 993 {
962 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); 994 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
963 regenFaces(); 995 regenFaces();
964 genTriangles(FALSE); 996 genBBoxes(FALSE);
965 } 997 }
966 } 998 }
967 else if (mLODChanged) 999 else if (mLODChanged)
@@ -983,9 +1015,9 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
983 if (new_lod != old_lod) 1015 if (new_lod != old_lod)
984 { 1016 {
985 compiled = TRUE; 1017 compiled = TRUE;
986 sNumLODChanges += (getAllTEsSame() ? 1 : getVolume()->getNumFaces()); 1018 sNumLODChanges += getVolume()->getNumFaces();
987 1019
988 drawable->setState(LLDrawable::REBUILD_ALL); // for face->genVolumeTriangles() 1020 drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
989 1021
990 { 1022 {
991 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); 1023 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
@@ -993,7 +1025,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
993 { 1025 {
994 regenFaces(); 1026 regenFaces();
995 } 1027 }
996 genTriangles(FALSE); 1028 genBBoxes(FALSE);
997 } 1029 }
998 } 1030 }
999 } 1031 }
@@ -1003,7 +1035,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
1003 compiled = TRUE; 1035 compiled = TRUE;
1004 // All it did was move or we changed the texture coordinate offset 1036 // All it did was move or we changed the texture coordinate offset
1005 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); 1037 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
1006 genTriangles(FALSE); 1038 genBBoxes(FALSE);
1007 } 1039 }
1008 1040
1009 // Update face flags 1041 // Update face flags
@@ -1018,11 +1050,16 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
1018 mLODChanged = FALSE; 1050 mLODChanged = FALSE;
1019 mFaceMappingChanged = FALSE; 1051 mFaceMappingChanged = FALSE;
1020 1052
1021 drawable->clearState(LLDrawable::REBUILD_GEOMETRY);
1022
1023 return TRUE; 1053 return TRUE;
1024} 1054}
1025 1055
1056void LLVOVolume::updateFaceSize(S32 idx)
1057{
1058 const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx);
1059 LLFace* facep = mDrawable->getFace(idx);
1060 facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size());
1061}
1062
1026BOOL LLVOVolume::isRootEdit() const 1063BOOL LLVOVolume::isRootEdit() const
1027{ 1064{
1028 if (mParent && !((LLViewerObject*)mParent)->isAvatar()) 1065 if (mParent && !((LLViewerObject*)mParent)->isAvatar())
@@ -1034,178 +1071,121 @@ BOOL LLVOVolume::isRootEdit() const
1034 1071
1035void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep) 1072void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep)
1036{ 1073{
1037// llinfos << "SetTEImage:" << llendl;
1038 BOOL changed = (mTEImages[te] != imagep); 1074 BOOL changed = (mTEImages[te] != imagep);
1039 LLViewerObject::setTEImage(te, imagep); 1075 LLViewerObject::setTEImage(te, imagep);
1040 if (mDrawable.notNull()) 1076 if (changed)
1041 { 1077 {
1042 if (changed) 1078 gPipeline.markTextured(mDrawable);
1043 { 1079 mFaceMappingChanged = TRUE;
1044 calcAllTEsSame();
1045 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
1046 mFaceMappingChanged = TRUE;
1047 }
1048 } 1080 }
1049} 1081}
1050 1082
1051S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) 1083S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid)
1052{ 1084{
1053 BOOL changed = (uuid != getTE(te)->getID() || (uuid == LLUUID::null));
1054
1055 S32 res = LLViewerObject::setTETexture(te, uuid); 1085 S32 res = LLViewerObject::setTETexture(te, uuid);
1056 if (mDrawable.notNull()) 1086 if (res)
1057 { 1087 {
1058 if (changed) 1088 gPipeline.markTextured(mDrawable);
1059 { 1089 mFaceMappingChanged = TRUE;
1060 calcAllTEsSame();
1061 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
1062 mFaceMappingChanged = TRUE;
1063 }
1064 } 1090 }
1065 return res; 1091 return res;
1066} 1092}
1067 1093
1068S32 LLVOVolume::setTEColor(const U8 te, const LLColor4 &color) 1094S32 LLVOVolume::setTEColor(const U8 te, const LLColor4 &color)
1069{ 1095{
1070 BOOL changed = (color != getTE(te)->getColor());
1071 S32 res = LLViewerObject::setTEColor(te, color); 1096 S32 res = LLViewerObject::setTEColor(te, color);
1072 if (mDrawable.notNull()) 1097 if (res)
1073 { 1098 {
1074 if (changed) 1099 gPipeline.markTextured(mDrawable);
1075 { 1100 mFaceMappingChanged = TRUE;
1076 calcAllTEsSame();
1077// mFaceMappingChanged = TRUE;
1078 }
1079 } 1101 }
1080 return res; 1102 return res;
1081} 1103}
1082 1104
1083S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) 1105S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap)
1084{ 1106{
1085 BOOL changed = (bumpmap != getTE(te)->getBumpmap());
1086 S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); 1107 S32 res = LLViewerObject::setTEBumpmap(te, bumpmap);
1087 if (mDrawable.notNull()) 1108 if (res)
1088 { 1109 {
1089 if (changed) 1110 gPipeline.markTextured(mDrawable);
1090 { 1111 mFaceMappingChanged = TRUE;
1091 calcAllTEsSame();
1092 mFaceMappingChanged = TRUE;
1093 }
1094 } 1112 }
1095 return res; 1113 return res;
1096} 1114}
1097 1115
1098S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) 1116S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen)
1099{ 1117{
1100 BOOL changed = (texgen != getTE(te)->getTexGen());
1101 S32 res = LLViewerObject::setTETexGen(te, texgen); 1118 S32 res = LLViewerObject::setTETexGen(te, texgen);
1102 if (mDrawable.notNull()) 1119 if (res)
1103 { 1120 {
1104 if (changed) 1121 gPipeline.markTextured(mDrawable);
1105 { 1122 mFaceMappingChanged = TRUE;
1106 calcAllTEsSame();
1107 mFaceMappingChanged = TRUE;
1108 }
1109 } 1123 }
1110 return res; 1124 return res;
1111} 1125}
1112 1126
1113S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) 1127S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny)
1114{ 1128{
1115 BOOL changed = (shiny != getTE(te)->getShiny());
1116 S32 res = LLViewerObject::setTEShiny(te, shiny); 1129 S32 res = LLViewerObject::setTEShiny(te, shiny);
1117 if (mDrawable.notNull()) 1130 if (res)
1118 { 1131 {
1119 if (changed) 1132 gPipeline.markTextured(mDrawable);
1120 { 1133 mFaceMappingChanged = TRUE;
1121 calcAllTEsSame();
1122 mFaceMappingChanged = TRUE;
1123 }
1124 } 1134 }
1125 return res; 1135 return res;
1126} 1136}
1127 1137
1128S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) 1138S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright)
1129{ 1139{
1130 BOOL changed = (fullbright != getTE(te)->getFullbright());
1131 S32 res = LLViewerObject::setTEFullbright(te, fullbright); 1140 S32 res = LLViewerObject::setTEFullbright(te, fullbright);
1132 if (mDrawable.notNull()) 1141 if (res)
1133 { 1142 {
1134 if (changed) 1143 gPipeline.markTextured(mDrawable);
1135 { 1144 mFaceMappingChanged = TRUE;
1136 calcAllTEsSame();
1137 if (!mDrawable->isState(LLDrawable::REBUILD_VOLUME))
1138 {
1139 updateFaceFlags();
1140 }
1141 mFaceMappingChanged = TRUE;
1142 }
1143 } 1145 }
1144 return res; 1146 return res;
1145} 1147}
1146 1148
1147S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) 1149S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags)
1148{ 1150{
1149 bool changed = (media_flags != getTE(te)->getMediaFlags());
1150 S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); 1151 S32 res = LLViewerObject::setTEMediaFlags(te, media_flags);
1151 if (mDrawable.notNull()) 1152 if (res)
1152 { 1153 {
1153 if (changed) 1154 gPipeline.markTextured(mDrawable);
1154 { 1155 mFaceMappingChanged = TRUE;
1155 calcAllTEsSame();
1156 mFaceMappingChanged = TRUE;
1157 }
1158 } 1156 }
1159 return res; 1157 return res;
1160} 1158}
1161 1159
1162S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) 1160S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
1163{ 1161{
1164 F32 olds,oldt;
1165 getTE(te)->getScale(&olds, &oldt);
1166 bool changed = (s != olds || t != oldt);
1167 S32 res = LLViewerObject::setTEScale(te, s, t); 1162 S32 res = LLViewerObject::setTEScale(te, s, t);
1168 if (mDrawable.notNull()) 1163 if (res)
1169 { 1164 {
1170 if (changed) 1165 gPipeline.markTextured(mDrawable);
1171 { 1166 mFaceMappingChanged = TRUE;
1172 calcAllTEsSame();
1173 mFaceMappingChanged = TRUE;
1174 }
1175 } 1167 }
1176 return res; 1168 return res;
1177} 1169}
1178 1170
1179S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) 1171S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s)
1180{ 1172{
1181 F32 olds,oldt;
1182 getTE(te)->getScale(&olds, &oldt);
1183 bool changed = (s != olds);
1184 S32 res = LLViewerObject::setTEScaleS(te, s); 1173 S32 res = LLViewerObject::setTEScaleS(te, s);
1185 if (mDrawable.notNull()) 1174 if (res)
1186 { 1175 {
1187 if (changed) 1176 gPipeline.markTextured(mDrawable);
1188 { 1177 mFaceMappingChanged = TRUE;
1189 calcAllTEsSame();
1190 mFaceMappingChanged = TRUE;
1191 }
1192 } 1178 }
1193 return res; 1179 return res;
1194} 1180}
1195 1181
1196S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) 1182S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t)
1197{ 1183{
1198 F32 olds,oldt;
1199 getTE(te)->getScale(&olds, &oldt);
1200 bool changed = (t != oldt);
1201 S32 res = LLViewerObject::setTEScaleT(te, t); 1184 S32 res = LLViewerObject::setTEScaleT(te, t);
1202 if (mDrawable.notNull()) 1185 if (res)
1203 { 1186 {
1204 if (changed) 1187 gPipeline.markTextured(mDrawable);
1205 { 1188 mFaceMappingChanged = TRUE;
1206 calcAllTEsSame();
1207 mFaceMappingChanged = TRUE;
1208 }
1209 } 1189 }
1210 return res; 1190 return res;
1211} 1191}
@@ -1214,137 +1194,11 @@ void LLVOVolume::updateTEData()
1214{ 1194{
1215 if (mDrawable.notNull()) 1195 if (mDrawable.notNull())
1216 { 1196 {
1217 calcAllTEsSame();
1218 mFaceMappingChanged = TRUE; 1197 mFaceMappingChanged = TRUE;
1219 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); 1198 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE);
1220 } 1199 }
1221} 1200}
1222 1201
1223BOOL LLVOVolume::calcAllTEsSame()
1224{
1225 BOOL is_alpha = FALSE;
1226 BOOL was_same = mAllTEsSame;
1227 BOOL all_same = TRUE;
1228 S32 num_tes = getNumTEs();
1229
1230 LLViewerImage *first_texturep = getTEImage(0);
1231 if (!first_texturep)
1232 {
1233 return FALSE;
1234 }
1235
1236 const LLTextureEntry *tep = getTE(0);
1237 if (!tep)
1238 {
1239 llwarns << "Volume with zero textures!" << llendl;
1240 return FALSE;
1241 }
1242
1243 if (tep->getColor().mV[3] != 1.f)
1244 {
1245 is_alpha = TRUE;
1246 }
1247 const LLColor4 first_color = tep->getColor();
1248 const U8 first_bump = tep->getBumpShinyFullbright();
1249 const U8 first_media_flags = tep->getMediaTexGen();
1250
1251 if (first_texturep->getComponents() == 4)
1252 {
1253 is_alpha = TRUE;
1254 }
1255
1256 F32 s_scale, t_scale;
1257 tep->getScale(&s_scale, &t_scale);
1258
1259 for (S32 f = 1; f < num_tes; f++)
1260 {
1261 LLViewerImage *texturep = getTEImage(f);
1262 if (texturep != first_texturep)
1263 {
1264 all_same = FALSE;
1265 break;
1266 }
1267
1268 tep = getTE(f);
1269
1270 if( tep->getBumpShinyFullbright() != first_bump )
1271 {
1272 all_same = FALSE;
1273 break;
1274 }
1275
1276 if (first_bump)
1277 {
1278 F32 cur_s, cur_t;
1279 tep->getScale(&cur_s, &cur_t);
1280 if ((cur_s != s_scale) || (cur_t != t_scale))
1281 {
1282 all_same = FALSE;
1283 break;
1284 }
1285 }
1286
1287 if ((texturep->getComponents() == 4) || (tep->getColor().mV[3] != 1.f))
1288 {
1289 if (!is_alpha)
1290 {
1291 all_same = FALSE;
1292 break;
1293 }
1294 }
1295 else if (is_alpha)
1296 {
1297 all_same = FALSE;
1298 break;
1299 }
1300
1301 if (tep->getColor() != first_color)
1302 {
1303 all_same = FALSE;
1304 break;
1305 }
1306
1307 if (tep->getMediaTexGen() != first_media_flags)
1308 {
1309 all_same = FALSE;
1310 break;
1311 }
1312 }
1313
1314 mAllTEsSame = all_same;
1315 if (was_same != all_same)
1316 {
1317 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); // rebuild NOW
1318 mFaceMappingChanged = TRUE;
1319 }
1320 return mAllTEsSame;
1321}
1322
1323void LLVOVolume::setupSingleFace(S32 face_offset)
1324{
1325 S32 num_indices = 0;
1326 S32 num_vertices = 0;
1327
1328 if (mDrawable.isNull())
1329 {
1330 llerrs << "setupSingleFace called with NULL mDrawable" << llendl;
1331 }
1332 if (face_offset >= mDrawable->getNumFaces())
1333 {
1334 llerrs << "setupSingleFace called with invalid face_offset" << llendl;
1335 }
1336
1337 const S32 num_faces = getVolume()->getNumFaces();
1338 for (S32 i = 0; i < num_faces; i++)
1339 {
1340 const LLVolumeFace &vf = getVolume()->getVolumeFace(i);
1341 num_vertices += vf.mVertices.size();
1342 num_indices += vf.mIndices.size();
1343 }
1344 LLFace *facep = mDrawable->getFace(face_offset);
1345 facep->setSize(num_vertices, num_indices);
1346}
1347
1348//---------------------------------------------------------------------------- 1202//----------------------------------------------------------------------------
1349 1203
1350void LLVOVolume::setIsLight(BOOL is_light) 1204void LLVOVolume::setIsLight(BOOL is_light)
@@ -1388,6 +1242,8 @@ void LLVOVolume::setLightColor(const LLColor3& color)
1388 { 1242 {
1389 param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); 1243 param_block->setColor(LLColor4(color, param_block->getColor().mV[3]));
1390 parameterChanged(LLNetworkData::PARAMS_LIGHT, true); 1244 parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
1245 gPipeline.markTextured(mDrawable);
1246 mFaceMappingChanged = TRUE;
1391 } 1247 }
1392 } 1248 }
1393} 1249}
@@ -1551,7 +1407,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL
1551 LLVector3 light_dir = light_pos - pos; 1407 LLVector3 light_dir = light_pos - pos;
1552 F32 dist = light_dir.normVec(); 1408 F32 dist = light_dir.normVec();
1553 F32 dp = norm * light_dir; 1409 F32 dp = norm * light_dir;
1554 if ((gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)) 1410 if ((gPipeline.getLightingDetail() > 2))
1555 { 1411 {
1556 if (dp <= 0) 1412 if (dp <= 0)
1557 { 1413 {
@@ -1590,7 +1446,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL
1590BOOL LLVOVolume::updateLighting(BOOL do_lighting) 1446BOOL LLVOVolume::updateLighting(BOOL do_lighting)
1591{ 1447{
1592 LLMemType mt1(LLMemType::MTYPE_DRAWABLE); 1448 LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
1593 1449#if 0
1594 if (mDrawable->isStatic()) 1450 if (mDrawable->isStatic())
1595 { 1451 {
1596 do_lighting = FALSE; 1452 do_lighting = FALSE;
@@ -1600,31 +1456,31 @@ BOOL LLVOVolume::updateLighting(BOOL do_lighting)
1600 const LLMatrix3& mat_normal = LLMatrix3(mDrawable->getWorldRotation()); 1456 const LLMatrix3& mat_normal = LLMatrix3(mDrawable->getWorldRotation());
1601 1457
1602 LLVolume* volume = getVolume(); 1458 LLVolume* volume = getVolume();
1603 if (getAllTEsSame()) 1459
1460 for (S32 i = 0; i < volume->getNumFaces(); i++)
1604 { 1461 {
1605 LLFace *face = mDrawable->getFace(mFaceIndexOffset); 1462 LLFace *face = mDrawable->getFace(i);
1606 S32 num_faces = volume->getNumFaces();
1607 if (face && face->getGeomCount()) 1463 if (face && face->getGeomCount())
1608 { 1464 {
1609 face->genLighting(volume, mDrawable, 0, num_faces-1, mat_vert, mat_normal, do_lighting); 1465 face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting);
1610 }
1611 }
1612 else
1613 {
1614 for (S32 i = 0; i < volume->getNumFaces(); i++)
1615 {
1616 LLFace *face = mDrawable->getFace(i + mFaceIndexOffset);
1617 if (face && face->getGeomCount())
1618 {
1619 face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting);
1620 }
1621 } 1466 }
1622 } 1467 }
1468#endif
1623 return TRUE; 1469 return TRUE;
1624} 1470}
1625 1471
1626//---------------------------------------------------------------------------- 1472//----------------------------------------------------------------------------
1627 1473
1474U32 LLVOVolume::getVolumeInterfaceID() const
1475{
1476 if (mVolumeImpl)
1477 {
1478 return mVolumeImpl->getID();
1479 }
1480
1481 return 0;
1482}
1483
1628BOOL LLVOVolume::isFlexible() const 1484BOOL LLVOVolume::isFlexible() const
1629{ 1485{
1630 if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) 1486 if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE))
@@ -1715,16 +1571,18 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p
1715 LLVector3 view_vector; 1571 LLVector3 view_vector;
1716 view_vector = view_point; 1572 view_vector = view_point;
1717 1573
1574 //transform view vector into volume space
1575 view_vector -= getRenderPosition();
1576 mDrawable->mDistanceWRTCamera = view_vector.magVec();
1577 LLQuaternion worldRot = getRenderRotation();
1578 view_vector = view_vector * ~worldRot;
1718 if (!isVolumeGlobal()) 1579 if (!isVolumeGlobal())
1719 { //transform view vector into volume space 1580 {
1720 view_vector -= getRenderPosition();
1721 LLQuaternion worldRot = getRenderRotation();
1722 view_vector = view_vector * ~worldRot;
1723 LLVector3 objScale = getScale(); 1581 LLVector3 objScale = getScale();
1724 LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); 1582 LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]);
1725 view_vector.scaleVec(invObjScale); 1583 view_vector.scaleVec(invObjScale);
1726 } 1584 }
1727 1585
1728 updateRelativeXform(); 1586 updateRelativeXform();
1729 volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, mRelativeXform, mRelativeXformInvTrans); 1587 volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, mRelativeXform, mRelativeXformInvTrans);
1730 1588
@@ -1732,33 +1590,15 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p
1732 } 1590 }
1733} 1591}
1734 1592
1735void LLVOVolume::deleteFaces(LLVOVolume* childp) 1593void LLVOVolume::deleteFaces()
1736{ 1594{
1737 S32 face_count = childp->mNumFaces; 1595 S32 face_count = mNumFaces;
1738 S32 start_index = childp->mFaceIndexOffset;
1739 if (mDrawable.notNull()) 1596 if (mDrawable.notNull())
1740 { 1597 {
1741 mDrawable->deleteFaces(start_index, face_count); 1598 mDrawable->deleteFaces(0, face_count);
1742 }
1743 if (mFaceIndexOffset > start_index)
1744 {
1745 mFaceIndexOffset -= face_count;
1746 } 1599 }
1747 1600
1748 for (U32 i = 0; i < mChildList.size(); i++) 1601 mNumFaces = 0;
1749 {
1750 LLViewerObject* siblingp = mChildList[i];
1751 if (siblingp != childp)
1752 {
1753 if (siblingp->getPCode() == LL_PCODE_VOLUME &&
1754 ((LLVOVolume*)siblingp)->mFaceIndexOffset > start_index)
1755 {
1756 ((LLVOVolume*)siblingp)->mFaceIndexOffset -= face_count;
1757 }
1758 }
1759 }
1760 childp->mFaceIndexOffset = 0;
1761 childp->mNumFaces = 0;
1762} 1602}
1763 1603
1764void LLVOVolume::updateRadius() 1604void LLVOVolume::updateRadius()
@@ -1806,7 +1646,8 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
1806 1646
1807void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file_base, S32 joint_num, LLVector3& pos, LLQuaternion& rot, S32& material_index, S32& texture_index, std::multimap<LLUUID, LLMaterialExportInfo*>& material_map) 1647void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file_base, S32 joint_num, LLVector3& pos, LLQuaternion& rot, S32& material_index, S32& texture_index, std::multimap<LLUUID, LLMaterialExportInfo*>& material_map)
1808{ 1648{
1809 LLPointer<LLImageTGA> tga_image = new LLImageTGA; 1649#if 0
1650 LLImageTGA tga_image;
1810 1651
1811 if (mDrawable.isNull()) 1652 if (mDrawable.isNull())
1812 { 1653 {
@@ -1878,8 +1719,8 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file
1878 my_texture = texture_index++; 1719 my_texture = texture_index++;
1879 1720
1880 //...and export texture as image file 1721 //...and export texture as image file
1881 char filename[MAX_PATH]; 1722 char filename[MAX_PATH]; /* Flawfinder: ignore */
1882 sprintf(filename, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), my_texture); 1723 snprintf(filename, MAX_PATH, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), my_texture); /* Flawfinder: ignore */
1883 1724
1884 LLViewerImage* imagep = facep->getTexture(); 1725 LLViewerImage* imagep = facep->getTexture();
1885 if (imagep->getTexName() == 0) 1726 if (imagep->getTexName() == 0)
@@ -1887,10 +1728,10 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file
1887 llinfos << "No image data available for " << filename << llendl; 1728 llinfos << "No image data available for " << filename << llendl;
1888 continue; 1729 continue;
1889 } 1730 }
1890 LLPointer<LLImageRaw> raw_image = new LLImageRaw; 1731 LLImageRaw raw_image;
1891 imagep->readBackRaw(-1, raw_image); 1732 imagep->readBackRaw(-1, raw_image);
1892 BOOL success = tga_image->encode(raw_image); 1733 BOOL success = tga_image.encode(raw_image);
1893 success = tga_image->save(filename); 1734 success = tga_image.save(filename);
1894 } 1735 }
1895 1736
1896 material_info = new LLMaterialExportInfo(my_material, my_texture, face_color); 1737 material_info = new LLMaterialExportInfo(my_material, my_texture, face_color);
@@ -1931,6 +1772,7 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file
1931 { 1772 {
1932 ((LLVOVolume*)(LLViewerObject*)mChildList[i])->writeCAL3D(fp, path, file_base, joint_num, final_pos, final_rot, material_index, texture_index, material_map); 1773 ((LLVOVolume*)(LLViewerObject*)mChildList[i])->writeCAL3D(fp, path, file_base, joint_num, final_pos, final_rot, material_index, texture_index, material_map);
1933 } 1774 }
1775#endif
1934} 1776}
1935 1777
1936//static 1778//static
@@ -1961,10 +1803,67 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u
1961 } 1803 }
1962} 1804}
1963 1805
1806void LLVOVolume::setSelected(BOOL sel)
1807{
1808 LLViewerObject::setSelected(sel);
1809 if (mDrawable.notNull())
1810 {
1811 mDrawable->movePartition();
1812 }
1813}
1814
1964void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) 1815void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
1965{ 1816{
1966} 1817}
1967 1818
1819F32 LLVOVolume::getBinRadius()
1820{
1821 F32 radius;
1822
1823 const LLVector3* ext = mDrawable->getSpatialExtents();
1824
1825 BOOL shrink_wrap = mDrawable->isAnimating();
1826 BOOL alpha_wrap = FALSE;
1827
1828 if (!isHUDAttachment())
1829 {
1830 for (S32 i = 0; i < mDrawable->getNumFaces(); i++)
1831 {
1832 if (mDrawable->getFace(i)->getPoolType() == LLDrawPool::POOL_ALPHA)
1833 {
1834 alpha_wrap = TRUE;
1835 break;
1836 }
1837 }
1838 }
1839 else
1840 {
1841 shrink_wrap = FALSE;
1842 }
1843
1844 if (alpha_wrap)
1845 {
1846 LLVector3 bounds = getScale();
1847 radius = llmin(bounds.mV[1], bounds.mV[2]);
1848 radius = llmin(radius, bounds.mV[0]);
1849 radius *= 0.5f;
1850 }
1851 else if (shrink_wrap)
1852 {
1853 radius = (ext[1]-ext[0]).magVec()*0.5f;
1854 }
1855 else if (mDrawable->isStatic())
1856 {
1857 radius = 32.f;
1858 }
1859 else
1860 {
1861 radius = 8.f;
1862 }
1863
1864 return llclamp(radius, 0.5f, 256.f);
1865}
1866
1968const LLVector3 LLVOVolume::getPivotPositionAgent() const 1867const LLVector3 LLVOVolume::getPivotPositionAgent() const
1969{ 1868{
1970 if (mVolumeImpl) 1869 if (mVolumeImpl)
@@ -1980,6 +1879,8 @@ void LLVOVolume::onShift(const LLVector3 &shift_vector)
1980 { 1879 {
1981 mVolumeImpl->onShift(shift_vector); 1880 mVolumeImpl->onShift(shift_vector);
1982 } 1881 }
1882
1883 updateRelativeXform();
1983} 1884}
1984 1885
1985const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const 1886const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const
@@ -1993,14 +1894,9 @@ const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const
1993 1894
1994LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const 1895LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const
1995{ 1896{
1996 if (isVolumeGlobal())
1997 {
1998 return pos;
1999 }
2000
2001 LLVector3 ret = pos - getRenderPosition(); 1897 LLVector3 ret = pos - getRenderPosition();
2002 ret = ret * ~getRenderRotation(); 1898 ret = ret * ~getRenderRotation();
2003 LLVector3 objScale = getScale(); 1899 LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale();
2004 LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); 1900 LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]);
2005 ret.scaleVec(invObjScale); 1901 ret.scaleVec(invObjScale);
2006 1902
@@ -2009,7 +1905,7 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const
2009 1905
2010LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const 1906LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const
2011{ 1907{
2012 return isVolumeGlobal() ? dir : (dir * ~getRenderRotation()); 1908 return dir * ~getRenderRotation();
2013} 1909}
2014 1910
2015LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const 1911LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const
@@ -2024,6 +1920,9 @@ LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const
2024 1920
2025BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const 1921BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
2026{ 1922{
1923 return FALSE;
1924
1925#if 0 // needs to be rewritten to use face extents instead of volume bounds
2027 LLVolume* volume = getVolume(); 1926 LLVolume* volume = getVolume();
2028 BOOL ret = FALSE; 1927 BOOL ret = FALSE;
2029 if (volume) 1928 if (volume)
@@ -2043,4 +1942,561 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) co
2043 } 1942 }
2044 } 1943 }
2045 return ret; 1944 return ret;
1945#endif
1946}
1947
1948U32 LLVOVolume::getPartitionType() const
1949{
1950 if (isHUDAttachment())
1951 {
1952 return LLPipeline::PARTITION_HUD;
1953 }
1954
1955 return LLPipeline::PARTITION_VOLUME;
1956}
1957
1958LLVolumePartition::LLVolumePartition()
1959: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE)
1960{
1961 mLODPeriod = 16;
1962 mDepthMask = FALSE;
1963 mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
1964 mPartitionType = LLPipeline::PARTITION_VOLUME;
1965 mSlopRatio = 0.25f;
1966 mBufferUsage = GL_DYNAMIC_DRAW_ARB;
1967 mImageEnabled = TRUE;
1968}
1969
1970LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
1971: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK)
1972{
1973 mDepthMask = FALSE;
1974 mLODPeriod = 16;
1975 mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
1976 mPartitionType = LLPipeline::PARTITION_BRIDGE;
1977
1978 mBufferUsage = GL_DYNAMIC_DRAW_ARB;
1979
1980 mSlopRatio = 0.25f;
1981}
1982
1983void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
1984{
1985 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1986
1987 if (facep->getViewerObject()->isSelected() && gHideSelectedObjects)
1988 {
1989 return;
1990 }
1991
1992 //add face to drawmap
1993 std::vector<LLDrawInfo*>& draw_vec = group->mDrawMap[type];
1994
1995 S32 idx = draw_vec.size()-1;
1996
1997
1998 BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT ||
1999 type == LLRenderPass::PASS_ALPHA) ? facep->isState(LLFace::FULLBRIGHT) : FALSE;
2000
2001 const LLMatrix4* tex_mat = NULL;
2002 if (type != LLRenderPass::PASS_SHINY && facep->isState(LLFace::TEXTURE_ANIM))
2003 {
2004 tex_mat = &(facep->mTextureMatrix);
2005 }
2006
2007 U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0);
2008
2009 //LLViewerImage* tex = facep->mAppAngle < FORCE_SIMPLE_RENDER_ANGLE ? NULL : facep->getTexture();
2010 LLViewerImage* tex = facep->getTexture();
2011
2012 if (type == LLRenderPass::PASS_GLOW)
2013 {
2014 U32 start = facep->getGeomIndex();
2015 U32 end = start + facep->getGeomCount()-1;
2016 U32 offset = facep->getIndicesStart();
2017 U32 count = facep->getIndicesCount();
2018 LLDrawInfo* draw_info = new LLDrawInfo(start,end,count,offset,tex,
2019 facep->mVertexBuffer, fullbright, bump);
2020 draw_info->mVSize = facep->getVirtualSize();
2021 draw_vec.push_back(draw_info);
2022 LLVOVolume* volume = (LLVOVolume*) facep->getViewerObject();
2023 BOOL is_light = volume->mDrawable->isLight();
2024
2025// U8 alpha = is_light ? 196 : 160;
2026 LLColor3 col = is_light ? volume->getLightColor() : LLColor3(0,0,0);
2027 LLColor4 col2 = facep->getRenderColor();
2028 draw_info->mGlowColor.setVec((U8) (col.mV[0]*col2.mV[0]*255),
2029 (U8) (col.mV[1]*col2.mV[1]*255),
2030 (U8) (col.mV[2]*col2.mV[2]*255),
2031 196);
2032 draw_info->mTextureMatrix = tex_mat;
2033 validate_draw_info(*draw_info);
2034 }
2035 else if (idx >= 0 &&
2036 draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer &&
2037 draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
2038 draw_vec[idx]->mTexture == tex &&
2039#if LL_DARWIN
2040 draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
2041 draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
2042#endif
2043 draw_vec[idx]->mFullbright == fullbright &&
2044 draw_vec[idx]->mBump == bump &&
2045 draw_vec[idx]->mTextureMatrix == tex_mat)
2046 {
2047 draw_vec[idx]->mCount += facep->getIndicesCount();
2048 draw_vec[idx]->mEnd += facep->getGeomCount();
2049 draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
2050 validate_draw_info(*draw_vec[idx]);
2051 }
2052 else
2053 {
2054 U32 start = facep->getGeomIndex();
2055 U32 end = start + facep->getGeomCount()-1;
2056 U32 offset = facep->getIndicesStart();
2057 U32 count = facep->getIndicesCount();
2058 LLDrawInfo* draw_info = new LLDrawInfo(start,end,count,offset,tex,
2059 facep->mVertexBuffer, fullbright, bump);
2060 draw_info->mVSize = facep->getVirtualSize();
2061 draw_vec.push_back(draw_info);
2062 draw_info->mReflectionMap = group->mReflectionMap;
2063 draw_info->mTextureMatrix = tex_mat;
2064 validate_draw_info(*draw_info);
2065 }
2066}
2067
2068void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group)
2069{
2070
2071}
2072
2073void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
2074{
2075 if (group->changeLOD())
2076 {
2077 group->mLastUpdateDistance = group->mDistance;
2078 }
2079
2080 group->mLastUpdateViewAngle = group->mViewAngle;
2081
2082 if (!group->isState(LLSpatialGroup::GEOM_DIRTY |
2083 LLSpatialGroup::ALPHA_DIRTY))
2084 {
2085 return;
2086 }
2087
2088 group->mBuilt = 1.f;
2089 LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
2090
2091 LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB);
2092
2093 //find reflection map
2094 if (group->mSpatialPartition->mImageEnabled)
2095 {
2096 if (group->mReflectionMap.isNull())
2097 {
2098 LLSpatialGroup* parent = group->getParent();
2099 while (parent && group->mReflectionMap.isNull())
2100 {
2101 group->mReflectionMap = parent->mReflectionMap;
2102 parent = parent->getParent();
2103 }
2104 }
2105 }
2106
2107 group->clearDrawMap();
2108
2109 mFaceList.clear();
2110
2111 std::vector<LLFace*> alpha_faces;
2112 U32 vertex_count = 0;
2113 U32 index_count = 0;
2114 U32 useage = group->mSpatialPartition->mBufferUsage;
2115
2116 //get all the faces into a list, putting alpha faces in their own list
2117 for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
2118 {
2119 LLDrawable* drawablep = *drawable_iter;
2120
2121 if (drawablep->isDead())
2122 {
2123 continue;
2124 }
2125
2126 if (drawablep->isAnimating())
2127 { //fall back to stream draw for animating verts
2128 useage = GL_STREAM_DRAW_ARB;
2129 }
2130
2131 LLVOVolume* vobj = drawablep->getVOVolume();
2132
2133 //for each face
2134 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
2135 {
2136 //sum up face verts and indices
2137 drawablep->updateFaceSize(i);
2138 LLFace* facep = drawablep->getFace(i);
2139 if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
2140 {
2141 const LLTextureEntry* te = facep->getTextureEntry();
2142 LLViewerImage* tex = facep->getTexture();
2143
2144 BOOL force_simple = (facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA);
2145 U32 type = gPipeline.getPoolTypeFromTE(te, tex);
2146 if (type != LLDrawPool::POOL_ALPHA && force_simple)
2147 {
2148 type = LLDrawPool::POOL_SIMPLE;
2149 }
2150 facep->setPoolType(type);
2151
2152 if (vobj->isHUDAttachment())
2153 {
2154 facep->setState(LLFace::FULLBRIGHT);
2155 }
2156
2157 if (vobj->mTextureAnimp && vobj->mTexAnimMode)
2158 {
2159 if (vobj->mTextureAnimp->mFace <= -1)
2160 {
2161 S32 face;
2162 for (face = 0; face < vobj->getNumTEs(); face++)
2163 {
2164 drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM);
2165 }
2166 }
2167 else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs())
2168 {
2169 drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM);
2170 }
2171 }
2172
2173 if (type == LLDrawPool::POOL_ALPHA)
2174 {
2175 vertex_count += facep->getGeomCount();
2176 index_count += facep->getIndicesCount();
2177 alpha_faces.push_back(facep);
2178 }
2179 else
2180 {
2181 if (drawablep->isState(LLDrawable::REBUILD_VOLUME))
2182 {
2183 facep->mLastUpdateTime = gFrameTimeSeconds;
2184 }
2185 mFaceList.push_back(facep);
2186 }
2187 }
2188 else
2189 { //face has no renderable geometry
2190 facep->mVertexBuffer = NULL;
2191 facep->mLastVertexBuffer = NULL;
2192 //don't alpha wrap drawables that have only tiny tiny alpha faces
2193 facep->setPoolType(LLDrawPool::POOL_SIMPLE);
2194 }
2195
2196 vobj->updateTextures();
2197 }
2198 }
2199
2200 group->mVertexCount = vertex_count;
2201 group->mIndexCount = index_count;
2202 group->mBufferUsage = useage;
2203
2204 LLStrider<LLVector3> vertices;
2205 LLStrider<LLVector3> normals;
2206 LLStrider<LLVector2> texcoords2;
2207 LLStrider<LLVector2> texcoords;
2208 LLStrider<LLColor4U> colors;
2209 LLStrider<U32> indices;
2210
2211 //PROCESS NON-ALPHA FACES
2212 {
2213 //sort faces by texture
2214 std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareTextureAndTime());
2215
2216 std::vector<LLFace*>::iterator face_iter = mFaceList.begin();
2217
2218 LLSpatialGroup::buffer_map_t buffer_map;
2219
2220 while (face_iter != mFaceList.end())
2221 {
2222 //pull off next face
2223 LLFace* facep = *face_iter;
2224 LLViewerImage* tex = facep->getTexture();
2225
2226 U32 index_count = facep->getIndicesCount();
2227 U32 geom_count = facep->getGeomCount();
2228
2229 //sum up vertices needed for this texture
2230 std::vector<LLFace*>::iterator i = face_iter;
2231 ++i;
2232 while (i != mFaceList.end() && (*i)->getTexture() == tex)
2233 {
2234 facep = *i;
2235 ++i;
2236 index_count += facep->getIndicesCount();
2237 geom_count += facep->getGeomCount();
2238 }
2239
2240 //create/delete/resize vertex buffer if needed
2241 LLVertexBuffer* buffer = NULL;
2242 LLSpatialGroup::buffer_map_t::iterator found_iter = group->mBufferMap.find(tex);
2243 if (found_iter != group->mBufferMap.end())
2244 {
2245 buffer = found_iter->second;
2246 }
2247
2248 if (!buffer)
2249 { //create new buffer if needed
2250 buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask,
2251 group->mBufferUsage);
2252 buffer->allocateBuffer(geom_count, index_count, TRUE);
2253 }
2254 else
2255 {
2256 if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage)
2257 {
2258 buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask,
2259 group->mBufferUsage);
2260 buffer->allocateBuffer(geom_count, index_count, TRUE);
2261 }
2262 else
2263 {
2264 buffer->resizeBuffer(geom_count, index_count);
2265 }
2266 }
2267
2268 BOOL clean = TRUE;
2269 buffer_map[tex] = buffer;
2270
2271 //add face geometry
2272
2273 //get vertex buffer striders
2274 buffer->getVertexStrider(vertices);
2275 buffer->getNormalStrider(normals);
2276 buffer->getTexCoordStrider(texcoords);
2277 buffer->getTexCoord2Strider(texcoords2);
2278 buffer->getColorStrider(colors);
2279 buffer->getIndexStrider(indices);
2280
2281 U32 indices_index = 0;
2282 U32 index_offset = 0;
2283
2284 while (face_iter < i)
2285 {
2286 facep = *face_iter;
2287 LLDrawable* drawablep = facep->getDrawable();
2288 LLVOVolume* vobj = drawablep->getVOVolume();
2289 LLVolume* volume = vobj->getVolume();
2290
2291 U32 te_idx = facep->getTEOffset();
2292 facep->mIndicesIndex = indices_index;
2293 facep->mGeomIndex = index_offset;
2294 facep->mVertexBuffer = buffer;
2295 {
2296 if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices,
2297 vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset))
2298 {
2299 clean = FALSE;
2300 buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(),
2301 facep->getIndicesStart(), facep->getIndicesCount());
2302 }
2303 }
2304
2305 indices_index += facep->mIndicesCount;
2306
2307 BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA;
2308 BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
2309 const LLTextureEntry* te = facep->getTextureEntry();
2310
2311 if (tex->getPrimaryFormat() == GL_ALPHA)
2312 {
2313 registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
2314 }
2315 else if (fullbright)
2316 {
2317 registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
2318 }
2319 else
2320 {
2321 registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
2322 }
2323
2324 facep->setPoolType(LLDrawPool::POOL_SIMPLE);
2325
2326 if (te->getShiny())
2327 {
2328 registerFace(group, facep, LLRenderPass::PASS_SHINY);
2329 }
2330
2331 if (!force_simple && te->getBumpmap())
2332 {
2333 registerFace(group, facep, LLRenderPass::PASS_BUMP);
2334 }
2335
2336 if (vobj->getIsLight())
2337 {
2338 registerFace(group, facep, LLRenderPass::PASS_GLOW);
2339 }
2340
2341
2342 ++face_iter;
2343 }
2344
2345 if (clean)
2346 {
2347 buffer->markClean();
2348 }
2349 }
2350
2351 group->mBufferMap.clear();
2352 for (LLSpatialGroup::buffer_map_t::iterator i = buffer_map.begin(); i != buffer_map.end(); ++i)
2353 {
2354 group->mBufferMap[i->first] = i->second;
2355 }
2356 }
2357
2358 //PROCESS ALPHA FACES
2359 if (!alpha_faces.empty())
2360 {
2361 //sort alpha faces by distance
2362 std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater());
2363
2364 //store alpha faces in root vertex buffer
2365 if (group->mVertexBuffer.isNull() || (LLVertexBuffer::sEnableVBOs && group->mBufferUsage != group->mVertexBuffer->getUsage()))
2366 {
2367 group->mVertexBuffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask,
2368 group->mBufferUsage);
2369 group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true);
2370 stop_glerror();
2371 }
2372 else
2373 {
2374 group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount);
2375 stop_glerror();
2376 }
2377
2378 //get vertex buffer striders
2379 LLVertexBuffer* buffer = group->mVertexBuffer;
2380
2381 BOOL clean = TRUE;
2382
2383 buffer->getVertexStrider(vertices);
2384 buffer->getNormalStrider(normals);
2385 buffer->getTexCoordStrider(texcoords);
2386 buffer->getTexCoord2Strider(texcoords2);
2387 buffer->getColorStrider(colors);
2388 buffer->getIndexStrider(indices);
2389
2390 U32 index_offset = 0;
2391 U32 indices_index = 0;
2392
2393 for (std::vector<LLFace*>::iterator i = alpha_faces.begin(); i != alpha_faces.end(); ++i)
2394 {
2395 LLFace* facep = *i;
2396 LLDrawable* drawablep = facep->getDrawable();
2397 LLVOVolume* vobj = drawablep->getVOVolume();
2398 LLVolume* volume = vobj->getVolume();
2399
2400 U32 te_idx = facep->getTEOffset();
2401 facep->mIndicesIndex = indices_index;
2402 facep->mGeomIndex = index_offset;
2403 facep->mVertexBuffer = group->mVertexBuffer;
2404 if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices,
2405 vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset))
2406 {
2407 clean = FALSE;
2408 buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(),
2409 facep->getIndicesStart(), facep->getIndicesCount());
2410 }
2411
2412 indices_index += facep->mIndicesCount;
2413
2414 registerFace(group, facep, LLRenderPass::PASS_ALPHA);
2415 }
2416
2417 if (clean)
2418 {
2419 buffer->markClean();
2420 }
2421 }
2422 else
2423 {
2424 group->mVertexBuffer = NULL;
2425 }
2426
2427 //get all the faces into a list, putting alpha faces in their own list
2428 for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
2429 {
2430 LLDrawable* drawablep = *drawable_iter;
2431 drawablep->clearState(LLDrawable::REBUILD_ALL);
2432 }
2433
2434 group->mLastUpdateTime = gFrameTimeSeconds;
2435 group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY |
2436 LLSpatialGroup::ALPHA_DIRTY);
2437
2438 mFaceList.clear();
2046} 2439}
2440
2441void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count)
2442{
2443 //initialize to default usage for this partition
2444 U32 usage = group->mSpatialPartition->mBufferUsage;
2445
2446 //clear off any old faces
2447 mFaceList.clear();
2448
2449 //for each drawable
2450 for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
2451 {
2452 LLDrawable* drawablep = *drawable_iter;
2453
2454 if (drawablep->isDead())
2455 {
2456 continue;
2457 }
2458
2459 if (drawablep->isAnimating())
2460 { //fall back to stream draw for animating verts
2461 usage = GL_STREAM_DRAW_ARB;
2462 }
2463
2464 //for each face
2465 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
2466 {
2467 //sum up face verts and indices
2468 drawablep->updateFaceSize(i);
2469 LLFace* facep = drawablep->getFace(i);
2470 if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
2471 {
2472 vertex_count += facep->getGeomCount();
2473 index_count += facep->getIndicesCount();
2474
2475 //remember face (for sorting)
2476 mFaceList.push_back(facep);
2477 }
2478 else
2479 {
2480 facep->mVertexBuffer = NULL;
2481 facep->mLastVertexBuffer = NULL;
2482 }
2483 }
2484 }
2485
2486 group->mBufferUsage = usage;
2487}
2488
2489LLHUDPartition::LLHUDPartition()
2490{
2491 mPartitionType = LLPipeline::PARTITION_HUD;
2492 mDrawableType = LLPipeline::RENDER_TYPE_HUD;
2493 mSlopRatio = 0.f;
2494 mLODPeriod = 16;
2495}
2496
2497void LLHUDPartition::shift(const LLVector3 &offset)
2498{
2499 //HUD objects don't shift with region crossing. That would be silly.
2500}
2501
2502