00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "lldrawable.h"
00035
00036
00037 #include "material_codes.h"
00038
00039
00040 #include "llcriticaldamp.h"
00041 #include "llface.h"
00042 #include "lllightconstants.h"
00043 #include "llsky.h"
00044 #include "llsurfacepatch.h"
00045 #include "llviewercamera.h"
00046 #include "llviewerregion.h"
00047 #include "llvolume.h"
00048 #include "llvoavatar.h"
00049 #include "llvovolume.h"
00050 #include "llvosurfacepatch.h"
00051 #include "llworld.h"
00052 #include "pipeline.h"
00053 #include "llspatialpartition.h"
00054 #include "llviewerobjectlist.h"
00055 #include "llviewerwindow.h"
00056
00057 const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f;
00058 const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f;
00059 const F32 OBJECT_DAMPING_TIME_CONSTANT = 0.06f;
00060 const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f;
00061
00063
00064
00065
00066
00067
00068
00069
00071
00072
00073
00074
00075
00076
00077 U32 LLDrawable::sCurVisible = 0;
00078 U32 LLDrawable::sNumZombieDrawables = 0;
00079 F32 LLDrawable::sCurPixelAngle = 0;
00080 LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList;
00081
00082 #define FORCE_INVISIBLE_AREA 16.f
00083
00084
00085 void LLDrawable::incrementVisible()
00086 {
00087 sCurVisible++;
00088 sCurPixelAngle = (F32) gViewerWindow->getWindowDisplayHeight()/gCamera->getView();
00089 }
00090 void LLDrawable::init()
00091 {
00092
00093 mParent = NULL;
00094 mRenderType = 0;
00095 mCurrentScale = LLVector3(1,1,1);
00096 mDistanceWRTCamera = 0.0f;
00097
00098 mUVZ = 0.f;
00099
00100
00101
00102 mQuietCount = 0;
00103
00104 mState = 0;
00105 mVObjp = NULL;
00106
00107 mSpatialGroupp = NULL;
00108 mVisible = 0;
00109 mRadius = 0.f;
00110 mSunShadowFactor = 1.f;
00111
00112 mGeneration = -1;
00113 mBinRadius = 1.f;
00114 mSpatialBridge = NULL;
00115 }
00116
00117
00118 void LLDrawable::initClass()
00119 {
00120 }
00121
00122
00123 void LLDrawable::destroy()
00124 {
00125 if (isDead())
00126 {
00127 sNumZombieDrawables--;
00128 }
00129
00130 std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
00131 mFaces.clear();
00132
00133
00134
00135
00136
00137
00138 }
00139
00140 void LLDrawable::markDead()
00141 {
00142 if (isDead())
00143 {
00144 llwarns << "Warning! Marking dead multiple times!" << llendl;
00145 return;
00146 }
00147
00148 if (mSpatialBridge)
00149 {
00150 mSpatialBridge->markDead();
00151 mSpatialBridge = NULL;
00152 }
00153
00154 sNumZombieDrawables++;
00155
00156
00157 setState(DEAD);
00158 cleanupReferences();
00159
00160 }
00161
00162 LLVOVolume* LLDrawable::getVOVolume() const
00163 {
00164 LLViewerObject* objectp = mVObjp;
00165 if ( !isDead() && objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
00166 {
00167 return ((LLVOVolume*)objectp);
00168 }
00169 else
00170 {
00171 return NULL;
00172 }
00173 }
00174
00175 BOOL LLDrawable::isLight() const
00176 {
00177 LLViewerObject* objectp = mVObjp;
00178 if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME) && !isDead())
00179 {
00180 return ((LLVOVolume*)objectp)->getIsLight();
00181 }
00182 else
00183 {
00184 return FALSE;
00185 }
00186 }
00187
00188 void LLDrawable::clearLightSet()
00189 {
00190
00191 for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++)
00192 {
00193 LLDrawable *targetp = *iter;
00194 if (targetp != this && !targetp->isDead())
00195 {
00196 targetp->mLightSet.erase(this);
00197 gPipeline.markRelight(targetp);
00198 }
00199 }
00200 mLightSet.clear();
00201 }
00202
00203 void LLDrawable::cleanupReferences()
00204 {
00205 LLFastTimer t(LLFastTimer::FTM_PIPELINE);
00206
00207 std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
00208 mFaces.clear();
00209
00210 clearLightSet();
00211
00212 gObjectList.removeDrawable(this);
00213
00214 mBlockSet.clear();
00215
00216 gPipeline.unlinkDrawable(this);
00217
00218
00219 mVObjp = NULL;
00220 mParent = NULL;
00221 }
00222
00223 void LLDrawable::cleanupDeadDrawables()
00224 {
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 sDeadList.reset();
00237 }
00238
00239 S32 LLDrawable::findReferences(LLDrawable *drawablep)
00240 {
00241 S32 count = 0;
00242 if (mLightSet.count(drawablep) > 0)
00243 {
00244 llinfos << this << ": lightset reference" << llendl;
00245 count++;
00246 }
00247 if (mBlockSet.count(drawablep) > 0)
00248 {
00249 llinfos << this << ": blockset reference" << llendl;
00250 count++;
00251 }
00252 if (mParent == drawablep)
00253 {
00254 llinfos << this << ": parent reference" << llendl;
00255 count++;
00256 }
00257 return count;
00258 }
00259
00260 #if 0
00261
00262 void LLDrawable::removeFace(const S32 i)
00263 {
00264 LLFace *face= mFaces[i];
00265
00266 if (face)
00267 {
00268 mFaces.erase(mFaces.begin() + i);
00269 delete face;
00270 }
00271 }
00272 #endif
00273
00274 LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerImage *texturep)
00275 {
00276 LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00277
00278 LLFace *face = new LLFace(this, mVObjp);
00279 if (!face) llerrs << "Allocating new Face: " << mFaces.size() << llendl;
00280
00281 if (face)
00282 {
00283 mFaces.push_back(face);
00284
00285 if (poolp)
00286 {
00287 face->setPool(poolp, texturep);
00288 }
00289
00290 if (isState(UNLIT))
00291 {
00292 face->setState(LLFace::FULLBRIGHT);
00293 }
00294 }
00295 return face;
00296 }
00297
00298 LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerImage *texturep)
00299 {
00300 LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00301
00302 LLFace *face = new LLFace(this, mVObjp);
00303
00304 face->setTEOffset(mFaces.size());
00305 face->setTexture(texturep);
00306 face->setPoolType(gPipeline.getPoolTypeFromTE(te, texturep));
00307 mFaces.push_back(face);
00308
00309 if (isState(UNLIT))
00310 {
00311 face->setState(LLFace::FULLBRIGHT);
00312 }
00313
00314 return face;
00315
00316 }
00317
00318 void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep)
00319 {
00320 if (newFaces == (S32)mFaces.size())
00321 {
00322 return;
00323 }
00324 else if (newFaces < (S32)mFaces.size())
00325 {
00326 std::for_each(mFaces.begin() + newFaces, mFaces.end(), DeletePointer());
00327 mFaces.erase(mFaces.begin() + newFaces, mFaces.end());
00328 }
00329 else
00330 {
00331 mFaces.reserve(newFaces);
00332 for (int i = mFaces.size(); i<newFaces; i++)
00333 {
00334 addFace(poolp, texturep);
00335 }
00336 }
00337 }
00338
00339 void LLDrawable::setNumFacesFast(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep)
00340 {
00341 if (newFaces <= (S32)mFaces.size() && newFaces >= (S32)mFaces.size()/2)
00342 {
00343 return;
00344 }
00345 else if (newFaces < (S32)mFaces.size())
00346 {
00347 std::for_each(mFaces.begin() + newFaces, mFaces.end(), DeletePointer());
00348 mFaces.erase(mFaces.begin() + newFaces, mFaces.end());
00349 }
00350 else
00351 {
00352 mFaces.reserve(newFaces);
00353 for (int i = mFaces.size(); i<newFaces; i++)
00354 {
00355 addFace(poolp, texturep);
00356 }
00357 }
00358 }
00359
00360 void LLDrawable::mergeFaces(LLDrawable* src)
00361 {
00362 U32 face_count = mFaces.size() + src->mFaces.size();
00363
00364 mFaces.reserve(face_count);
00365 for (U32 i = 0; i < src->mFaces.size(); i++)
00366 {
00367 LLFace* facep = src->mFaces[i];
00368 facep->setDrawable(this);
00369 mFaces.push_back(facep);
00370 }
00371 src->mFaces.clear();
00372 }
00373
00374 void LLDrawable::deleteFaces(S32 offset, S32 count)
00375 {
00376 face_list_t::iterator face_begin = mFaces.begin() + offset;
00377 face_list_t::iterator face_end = face_begin + count;
00378 std::for_each(face_begin, face_end, DeletePointer());
00379 mFaces.erase(face_begin, face_end);
00380 }
00381
00382 void LLDrawable::update()
00383 {
00384 llerrs << "Shouldn't be called!" << llendl;
00385 }
00386
00387
00388 void LLDrawable::updateMaterial()
00389 {
00390 }
00391
00392 void LLDrawable::makeActive()
00393 {
00394 #if !LL_RELEASE_FOR_DOWNLOAD
00395 if (mVObjp.notNull())
00396 {
00397 U32 pcode = mVObjp->getPCode();
00398 if (pcode == LLViewerObject::LL_VO_WATER ||
00399 pcode == LLViewerObject::LL_VO_SURFACE_PATCH ||
00400 pcode == LLViewerObject::LL_VO_PART_GROUP ||
00401 pcode == LLViewerObject::LL_VO_CLOUDS ||
00402 pcode == LLViewerObject::LL_VO_STARS ||
00403 pcode == LLViewerObject::LL_VO_GROUND ||
00404 pcode == LLViewerObject::LL_VO_SKY)
00405 {
00406 llerrs << "Static viewer object has active drawable!" << llendl;
00407 }
00408 }
00409 #endif
00410
00411 if (!isState(ACTIVE))
00412 {
00413 setState(ACTIVE);
00414
00415
00416 if (!isRoot() && !mParent->isActive())
00417 {
00418 mParent->makeActive();
00419 }
00420
00421 gPipeline.setActive(this, TRUE);
00422
00423
00424 for (U32 i = 0; i < getChildCount(); i++)
00425 {
00426 LLDrawable* drawable = getChild(i);
00427 if (drawable)
00428 {
00429 drawable->makeActive();
00430 }
00431 }
00432
00433 if (mVObjp->getPCode() == LL_PCODE_VOLUME)
00434 {
00435 if (mVObjp->getVolume()->getPathType() == LL_PCODE_PATH_FLEXIBLE)
00436 {
00437 return;
00438 }
00439 }
00440
00441 clearState(LLDrawable::LIGHTING_BUILT);
00442 if (mVObjp->getPCode() == LL_PCODE_VOLUME)
00443 {
00444 gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE);
00445 }
00446 }
00447 updatePartition();
00448 if (isRoot())
00449 {
00450 mQuietCount = 0;
00451 }
00452 else
00453 {
00454 getParent()->mQuietCount = 0;
00455 }
00456 }
00457
00458
00459 void LLDrawable::makeStatic()
00460 {
00461 if (isState(ACTIVE))
00462 {
00463 clearState(ACTIVE);
00464 gPipeline.setActive(this, FALSE);
00465
00466 if (mParent.notNull() && mParent->isActive())
00467 {
00468 llwarns << "Drawable becamse static with active parent!" << llendl;
00469 }
00470
00471 S32 child_count = mVObjp->mChildList.size();
00472 for (S32 child_num = 0; child_num < child_count; child_num++)
00473 {
00474 LLDrawable* child_drawable = mVObjp->mChildList[child_num]->mDrawable;
00475 if (child_drawable)
00476 {
00477 if (child_drawable->getParent() != this)
00478 {
00479 llwarns << "Child drawable has unknown parent." << llendl;
00480 }
00481 child_drawable->makeStatic();
00482 }
00483 }
00484
00485 gPipeline.markRelight(this);
00486 if (mVObjp->getPCode() == LL_PCODE_VOLUME)
00487 {
00488 gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE);
00489 }
00490
00491 if (mSpatialBridge)
00492 {
00493 mSpatialBridge->markDead();
00494 setSpatialBridge(NULL);
00495 }
00496 }
00497 updatePartition();
00498 }
00499
00500
00501 F32 LLDrawable::updateXform(BOOL undamped)
00502 {
00503 BOOL damped = !undamped;
00504
00505
00506 LLVector3 old_pos(mXform.getPosition());
00507 LLVector3 target_pos;
00508 if (mXform.isRoot())
00509 {
00510
00511 target_pos = mVObjp->getPositionAgent();
00512 }
00513 else
00514 {
00515
00516 target_pos = mVObjp->getPosition();
00517 }
00518
00519
00520 LLQuaternion old_rot(mXform.getRotation());
00521 LLQuaternion target_rot = mVObjp->getRotation();
00522
00523 LLVector3 target_scale = mVObjp->getScale();
00524 LLVector3 old_scale = mCurrentScale;
00525 LLVector3 dest_scale = target_scale;
00526
00527
00528 F32 dist_squared = 0.f;
00529 F32 scaled = 0.f;
00530
00531 if (damped && mDistanceWRTCamera > 0.0f)
00532 {
00533 F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f);
00534 LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt);
00535 dist_squared = dist_vec_squared(new_pos, target_pos);
00536
00537 LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot);
00538 dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f;
00539
00540 LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt);
00541 scaled = dist_vec_squared(new_scale, target_scale);
00542
00543 dist_squared += scaled;
00544 F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera);
00545 if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) &&
00546 (dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED))
00547 {
00548
00549 target_pos = new_pos;
00550 target_rot = new_rot;
00551 target_scale = new_scale;
00552
00553 if (scaled >= MIN_INTERPOLATE_DISTANCE_SQUARED)
00554 {
00555
00556 gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
00557 }
00558 }
00559 else
00560 {
00561
00562 dist_squared = 0.0f;
00563 }
00564 }
00565
00566
00567 mXform.setPosition(target_pos);
00568 mXform.setRotation(target_rot);
00569 mXform.setScale(LLVector3(1,1,1));
00570 mXform.updateMatrix();
00571
00572 mCurrentScale = target_scale;
00573
00574 return dist_squared;
00575 }
00576
00577 void LLDrawable::setRadius(F32 radius)
00578 {
00579 if (mRadius != radius)
00580 {
00581 mRadius = radius;
00582 }
00583 }
00584
00585 void LLDrawable::moveUpdatePipeline(BOOL moved)
00586 {
00587 makeActive();
00588
00589
00590 for (S32 i = 0; i < getNumFaces(); i++)
00591 {
00592 getFace(i)->updateCenterAgent();
00593 }
00594
00595 if (moved || !isState(LLDrawable::BUILT))
00596 {
00597 LLVector3 tmp = mSavePos - mXform.getPositionW();
00598 F32 dist = tmp.magVecSquared();
00599
00600 if (dist > 1.0f || !isState(LLDrawable::BUILT) || isLight())
00601 {
00602 mSavePos = mXform.getPositionW();
00603 gPipeline.markRelight(this);
00604 }
00605 }
00606 }
00607
00608 void LLDrawable::movePartition()
00609 {
00610 LLSpatialPartition* part = getSpatialPartition();
00611 if (part)
00612 {
00613 part->move(this, getSpatialGroup());
00614 }
00615 }
00616
00617 BOOL LLDrawable::updateMove()
00618 {
00619 if (isDead())
00620 {
00621 llwarns << "Update move on dead drawable!" << llendl;
00622 return TRUE;
00623 }
00624
00625 if (mVObjp.isNull())
00626 {
00627 return FALSE;
00628 }
00629
00630 makeActive();
00631
00632 BOOL done;
00633
00634 if (isState(MOVE_UNDAMPED))
00635 {
00636 done = updateMoveUndamped();
00637 }
00638 else
00639 {
00640 done = updateMoveDamped();
00641 }
00642 return done;
00643 }
00644
00645 BOOL LLDrawable::updateMoveUndamped()
00646 {
00647 F32 dist_squared = updateXform(TRUE);
00648
00649 mGeneration++;
00650
00651 if (!isState(LLDrawable::INVISIBLE))
00652 {
00653 BOOL moved = (dist_squared > 0.001f && dist_squared < 255.99f);
00654 moveUpdatePipeline(moved);
00655 mVObjp->updateText();
00656 }
00657
00658 mVObjp->clearChanged(LLXform::MOVED);
00659
00660 return TRUE;
00661 }
00662
00663 void LLDrawable::updatePartition()
00664 {
00665 if (!getVOVolume())
00666 {
00667 movePartition();
00668 }
00669 else if (mSpatialBridge)
00670 {
00671 gPipeline.markMoved(mSpatialBridge, FALSE);
00672 }
00673 else
00674 {
00675
00676 gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
00677 }
00678 }
00679
00680 BOOL LLDrawable::updateMoveDamped()
00681 {
00682 F32 dist_squared = updateXform(FALSE);
00683
00684 mGeneration++;
00685
00686 if (!isState(LLDrawable::INVISIBLE))
00687 {
00688 BOOL moved = (dist_squared > 0.001f && dist_squared < 128.0f);
00689 moveUpdatePipeline(moved);
00690 mVObjp->updateText();
00691 }
00692
00693 BOOL done_moving = (dist_squared == 0.0f) ? TRUE : FALSE;
00694
00695 if (done_moving)
00696 {
00697 mVObjp->clearChanged(LLXform::MOVED);
00698 }
00699
00700 return done_moving;
00701 }
00702
00703 void LLDrawable::updateDistance(LLCamera& camera)
00704 {
00705
00706 LLSpatialGroup* sg = getSpatialGroup();
00707
00708 LLVector3 pos;
00709
00710 if (!sg || sg->changeLOD())
00711 {
00712 LLVOVolume* volume = getVOVolume();
00713 if (volume)
00714 {
00715 volume->updateRelativeXform();
00716 pos = LLVector3(0,0,0) * volume->getRelativeXform();
00717
00718 for (S32 i = 0; i < getNumFaces(); i++)
00719 {
00720 LLFace* facep = getFace(i);
00721 if (facep->getPoolType() == LLDrawPool::POOL_ALPHA)
00722 {
00723 LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f;
00724 LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
00725 LLVector3 at = camera.getAtAxis();
00726 for (U32 j = 0; j < 3; j++)
00727 {
00728 v.mV[j] -= box.mV[j] * at.mV[j];
00729 }
00730 facep->mDistance = v * camera.getAtAxis();
00731 }
00732 }
00733 }
00734 else
00735 {
00736 pos = LLVector3(getPositionGroup());
00737 }
00738
00739 pos -= camera.getOrigin();
00740 mDistanceWRTCamera = llround(pos.magVec(), 0.01f);
00741 mVObjp->updateLOD();
00742 }
00743 }
00744
00745 void LLDrawable::updateTexture()
00746 {
00747 LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00748
00749 if (isDead())
00750 {
00751 llwarns << "Dead drawable updating texture!" << llendl;
00752 return;
00753 }
00754
00755 if (getNumFaces() != mVObjp->getNumTEs())
00756 {
00757 return;
00758 }
00759
00760 if (getVOVolume())
00761 {
00762 if (!isActive())
00763 {
00764 gPipeline.markMoved(this);
00765 }
00766 else
00767 {
00768 if (isRoot())
00769 {
00770 mQuietCount = 0;
00771 }
00772 else
00773 {
00774 getParent()->mQuietCount = 0;
00775 }
00776 }
00777
00778 gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE);
00779 }
00780 }
00781
00782 BOOL LLDrawable::updateGeometry(BOOL priority)
00783 {
00784 llassert(mVObjp.notNull());
00785 BOOL res = mVObjp->updateGeometry(this);
00786 if (isState(REBUILD_LIGHTING))
00787 {
00788 updateLighting(priority ? FALSE : TRUE);
00789 if (priority)
00790 {
00791 gPipeline.markRelight(this);
00792 }
00793 else
00794 {
00795 clearState(REBUILD_LIGHTING);
00796 }
00797 }
00798 return res;
00799 }
00800
00801 void LLDrawable::shiftPos(const LLVector3 &shift_vector)
00802 {
00803 if (isDead())
00804 {
00805 llwarns << "Shifting dead drawable" << llendl;
00806 return;
00807 }
00808
00809 if (mParent)
00810 {
00811 mXform.setPosition(mVObjp->getPosition());
00812 }
00813 else
00814 {
00815 mXform.setPosition(mVObjp->getPositionAgent());
00816 }
00817
00818 mXform.setRotation(mVObjp->getRotation());
00819 mXform.setScale(1,1,1);
00820 mXform.updateMatrix();
00821
00822 if (isStatic())
00823 {
00824 gPipeline.markRebuild(this, LLDrawable::REBUILD_GEOMETRY, TRUE);
00825
00826 for (S32 i = 0; i < getNumFaces(); i++)
00827 {
00828 LLFace *facep = getFace(i);
00829 facep->mCenterAgent += shift_vector;
00830 facep->mExtents[0] += shift_vector;
00831 facep->mExtents[1] += shift_vector;
00832
00833 if (facep->hasGeometry())
00834 {
00835 facep->mVertexBuffer = NULL;
00836 facep->mLastVertexBuffer = NULL;
00837 }
00838 }
00839
00840 mExtents[0] += shift_vector;
00841 mExtents[1] += shift_vector;
00842 mPositionGroup += LLVector3d(shift_vector);
00843 }
00844 else if (mSpatialBridge)
00845 {
00846 mSpatialBridge->shiftPos(shift_vector);
00847 }
00848
00849 mSavePos = mXform.getPositionW();
00850
00851 mVObjp->onShift(shift_vector);
00852 }
00853
00854 const LLVector3& LLDrawable::getBounds(LLVector3& min, LLVector3& max) const
00855 {
00856 mXform.getMinMax(min,max);
00857 return mXform.getPositionW();
00858 }
00859
00860 const LLVector3* LLDrawable::getSpatialExtents() const
00861 {
00862 return mExtents;
00863 }
00864
00865 void LLDrawable::setSpatialExtents(LLVector3 min, LLVector3 max)
00866 {
00867 LLVector3 size = max - min;
00868 mExtents[0] = min;
00869 mExtents[1] = max;
00870 }
00871
00872 void LLDrawable::setPositionGroup(const LLVector3d& pos)
00873 {
00874 mPositionGroup.setVec(pos);
00875 }
00876
00877 void LLDrawable::updateSpatialExtents()
00878 {
00879 if (mVObjp)
00880 {
00881 mVObjp->updateSpatialExtents(mExtents[0], mExtents[1]);
00882 }
00883
00884 updateBinRadius();
00885
00886 if (mSpatialBridge.notNull())
00887 {
00888 mPositionGroup.setVec(0,0,0);
00889 }
00890 }
00891
00892
00893 void LLDrawable::updateBinRadius()
00894 {
00895 if (mVObjp.notNull())
00896 {
00897 mBinRadius = mVObjp->getBinRadius();
00898 }
00899 else
00900 {
00901 mBinRadius = getRadius()*4.f;
00902 }
00903 }
00904
00905 void LLDrawable::updateLightSet()
00906 {
00907 if (isDead())
00908 {
00909 llwarns << "Updating light set for dead drawable!" << llendl;
00910 return;
00911 }
00912
00913 LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME);
00914 LLVOVolume* light = getVOVolume();
00915 if (isLight() && light)
00916 {
00917
00918 for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++)
00919 {
00920 gPipeline.markRelight(*iter);
00921 }
00922 mLightSet.clear();
00923 part->getObjects(getPositionAgent(), light->getLightRadius(), mLightSet);
00924 for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++)
00925 {
00926 gPipeline.markRelight(*iter);
00927 }
00928 }
00929 else
00930 {
00931
00932 mLightSet.clear();
00933 part->getLights(getPositionAgent(), getRadius(), mLightSet);
00934 const drawable_set_t::size_type MAX_LIGHTS = 16;
00935 if (mLightSet.size() > MAX_LIGHTS)
00936 {
00937 typedef std::set<std::pair<F32,LLPointer<LLDrawable> > > sorted_pair_set_t;
00938 sorted_pair_set_t sorted_set;
00939 for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++)
00940 {
00941 LLDrawable* drawable = *iter;
00942 LLVector3 dvec = drawable->getPositionAgent() - getPositionAgent();
00943 F32 dist2 = dvec.magVecSquared();
00944 sorted_set.insert(std::make_pair(dist2, drawable));
00945 }
00946 mLightSet.clear();
00947 S32 count = 0;
00948 for (sorted_pair_set_t::iterator iter = sorted_set.begin(); iter != sorted_set.end(); iter++)
00949 {
00950 if (++count > 16)
00951 break;
00952 mLightSet.insert((*iter).second);
00953 }
00954 }
00955 }
00956 }
00957
00958 void LLDrawable::updateSpecialHoverCursor(BOOL enabled)
00959 {
00960
00961
00962
00963 }
00964
00965 BOOL LLDrawable::updateLighting(BOOL do_lighting)
00966 {
00967 if (do_lighting)
00968 {
00969 if (gPipeline.getLightingDetail() >= 2 && (getLit() || isLight()))
00970 {
00971 LLFastTimer t(LLFastTimer::FTM_UPDATE_LIGHTS);
00972 updateLightSet();
00973 do_lighting = isLight() ? FALSE : TRUE;
00974 }
00975 else
00976 {
00977 do_lighting = FALSE;
00978 }
00979 }
00980 if (gPipeline.getLightingDetail() >= 2)
00981 {
00982 LLFastTimer t(LLFastTimer::FTM_GEO_LIGHT);
00983 if (mVObjp->updateLighting(do_lighting))
00984 {
00985 setState(LIGHTING_BUILT);
00986 }
00987 }
00988
00989 return TRUE;
00990 }
00991
00992 void LLDrawable::applyLightsAsPoint(LLColor4& result)
00993 {
00994 LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
00995
00996 LLVector3 point_agent(getPositionAgent());
00997 LLVector3 normal(-gCamera->getXAxis());
00998
00999 F32 sun_int = normal * gPipeline.mSunDir;
01000 LLColor4 color(gSky.getTotalAmbientColor());
01001 color += gPipeline.mSunDiffuse * sun_int;
01002
01003 for (drawable_set_t::iterator iter = mLightSet.begin();
01004 iter != mLightSet.end(); ++iter)
01005 {
01006 LLDrawable* drawable = *iter;
01007 LLVOVolume* light = drawable->getVOVolume();
01008 if (!light)
01009 {
01010 continue;
01011 }
01012 LLColor4 light_color;
01013 light->calcLightAtPoint(point_agent, normal, light_color);
01014 color += light_color;
01015 }
01016
01017
01018 color.mV[0] = llmax(color.mV[0], 0.f);
01019 color.mV[1] = llmax(color.mV[1], 0.f);
01020 color.mV[2] = llmax(color.mV[2], 0.f);
01021
01022 F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]);
01023 if (max_color > 1.f)
01024 {
01025 color *= 1.f/max_color;
01026 }
01027
01028 result = color;
01029 }
01030
01031 F32 LLDrawable::getVisibilityRadius() const
01032 {
01033 if (isDead())
01034 {
01035 return 0.f;
01036 }
01037 else if (isLight())
01038 {
01039 return llmax(getRadius(), getVOVolume()->getLightRadius());
01040 }
01041 else
01042 {
01043 return getRadius();
01044 }
01045 }
01046
01047 void LLDrawable::updateUVMinMax()
01048 {
01049 }
01050
01051 void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)
01052 {
01053 if (mSpatialGroupp && (groupp != mSpatialGroupp))
01054 {
01055 mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY);
01056 }
01057 mSpatialGroupp = groupp;
01058 }
01059
01060 LLSpatialPartition* LLDrawable::getSpatialPartition()
01061 {
01062 LLSpatialPartition* retval = NULL;
01063
01064 if (!mVObjp ||
01065 !getVOVolume() ||
01066 isStatic())
01067 {
01068 retval = gPipeline.getSpatialPartition((LLViewerObject*) mVObjp);
01069 }
01070 else if (isRoot())
01071 {
01072 if (!mSpatialBridge)
01073 {
01074 if (mVObjp->isHUDAttachment())
01075 {
01076 setSpatialBridge(new LLHUDBridge(this));
01077 }
01078 else
01079 {
01080 setSpatialBridge(new LLVolumeBridge(this));
01081 }
01082 }
01083 return mSpatialBridge->asPartition();
01084 }
01085 else
01086 {
01087 retval = getParent()->getSpatialPartition();
01088 }
01089
01090 if (retval && mSpatialBridge.notNull())
01091 {
01092 mSpatialBridge->markDead();
01093 setSpatialBridge(NULL);
01094 }
01095
01096 return retval;
01097 }
01098
01099
01100 BOOL LLDrawable::isVisible() const
01101 {
01102 if (mVisible == sCurVisible)
01103 {
01104 return TRUE;
01105 }
01106
01107 if (isActive())
01108 {
01109 if (isRoot())
01110 {
01111 LLSpatialGroup* group = mSpatialBridge.notNull() ? mSpatialBridge->getSpatialGroup() :
01112 getSpatialGroup();
01113 if (!group || group->isVisible())
01114 {
01115 mVisible = sCurVisible;
01116 return TRUE;
01117 }
01118 }
01119 else
01120 {
01121 if (getParent()->isVisible())
01122 {
01123 mVisible = sCurVisible;
01124 return TRUE;
01125 }
01126 }
01127 }
01128 else
01129 {
01130 LLSpatialGroup* group = getSpatialGroup();
01131 if (!group || group->isVisible())
01132 {
01133 mVisible = sCurVisible;
01134 return TRUE;
01135 }
01136 }
01137
01138 return FALSE;
01139 }
01140
01141
01142
01143
01144
01145 LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask)
01146 : LLSpatialPartition(data_mask, FALSE)
01147 {
01148 mDrawable = root;
01149 root->setSpatialBridge(this);
01150
01151 mRenderType = mDrawable->mRenderType;
01152 mDrawableType = mDrawable->mRenderType;
01153
01154 mPartitionType = LLPipeline::PARTITION_VOLUME;
01155
01156 mOctree->balance();
01157
01158 gPipeline.getSpatialPartition(mPartitionType)->put(this);
01159 }
01160
01161 LLSpatialBridge::~LLSpatialBridge()
01162 {
01163 if (getSpatialGroup())
01164 {
01165 gPipeline.getSpatialPartition(mPartitionType)->remove(this, getSpatialGroup());
01166 }
01167 }
01168
01169 void LLSpatialBridge::updateSpatialExtents()
01170 {
01171 LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0);
01172
01173 {
01174 LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND);
01175 root->rebound();
01176 }
01177
01178 LLXformMatrix* mat = mDrawable->getXform();
01179
01180 LLVector3 offset = root->mBounds[0];
01181 LLVector3 size = root->mBounds[1];
01182
01183 LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix();
01184 LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix());
01185
01186 offset *= rotation;
01187 center += offset;
01188
01189 LLVector3 v[4];
01190
01191 v[0] = (size * rotation);
01192 v[1] = (LLVector3(-size.mV[0], -size.mV[1], size.mV[2]) * rotation);
01193 v[2] = (LLVector3(size.mV[0], -size.mV[1], -size.mV[2]) * rotation);
01194 v[3] = (LLVector3(-size.mV[0], size.mV[1], -size.mV[2]) * rotation);
01195
01196 LLVector3& newMin = mExtents[0];
01197 LLVector3& newMax = mExtents[1];
01198
01199 newMin = newMax = center;
01200
01201 for (U32 i = 0; i < 4; i++)
01202 {
01203 for (U32 j = 0; j < 3; j++)
01204 {
01205 F32 delta = fabsf(v[i].mV[j]);
01206 F32 min = center.mV[j] - delta;
01207 F32 max = center.mV[j] + delta;
01208
01209 if (min < newMin.mV[j])
01210 {
01211 newMin.mV[j] = min;
01212 }
01213
01214 if (max > newMax.mV[j])
01215 {
01216 newMax.mV[j] = max;
01217 }
01218 }
01219 }
01220
01221 LLVector3 diagonal = newMax - newMin;
01222 mRadius = diagonal.magVec() * 0.5f;
01223
01224 mPositionGroup.setVec((newMin + newMax) * 0.5f);
01225 updateBinRadius();
01226 }
01227
01228 void LLSpatialBridge::updateBinRadius()
01229 {
01230 mBinRadius = llmin((F32) mOctree->getSize().mdV[0]*0.5f, 256.f);
01231 }
01232
01233 LLCamera LLSpatialBridge::transformCamera(LLCamera& camera)
01234 {
01235 LLCamera ret = camera;
01236 LLXformMatrix* mat = mDrawable->getXform();
01237 LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix();
01238 LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix());
01239
01240 LLVector3 delta = ret.getOrigin() - center;
01241 LLQuaternion rot = ~mat->getRotation();
01242
01243 delta *= rot;
01244 LLVector3 lookAt = ret.getAtAxis();
01245 LLVector3 up_axis = ret.getUpAxis();
01246 LLVector3 left_axis = ret.getLeftAxis();
01247
01248 lookAt *= rot;
01249 up_axis *= rot;
01250 left_axis *= rot;
01251
01252 ret.setOrigin(delta);
01253 ret.setAxes(lookAt, left_axis, up_axis);
01254
01255 return ret;
01256 }
01257
01258 void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, BOOL for_select)
01259 {
01260 mVisible = sCurVisible;
01261
01262 #if 0 && !LL_RELEASE_FOR_DOWNLOAD
01263
01264 if (getVOVolume())
01265 {
01266 if (!isRoot())
01267 {
01268 if (isActive() && !mParent->isActive())
01269 {
01270 llerrs << "Active drawable has static parent!" << llendl;
01271 }
01272
01273 if (isStatic() && !mParent->isStatic())
01274 {
01275 llerrs << "Static drawable has active parent!" << llendl;
01276 }
01277
01278 if (mSpatialBridge)
01279 {
01280 llerrs << "Child drawable has spatial bridge!" << llendl;
01281 }
01282 }
01283 else if (isActive() && !mSpatialBridge)
01284 {
01285 llerrs << "Active root drawable has no spatial bridge!" << llendl;
01286 }
01287 else if (isStatic() && mSpatialBridge.notNull())
01288 {
01289 llerrs << "Static drawable has spatial bridge!" << llendl;
01290 }
01291 }
01292 #endif
01293 }
01294
01295 class LLOctreeMarkNotCulled: public LLOctreeTraveler<LLDrawable>
01296 {
01297 public:
01298 LLCamera* mCamera;
01299
01300 LLOctreeMarkNotCulled(LLCamera* camera_in) : mCamera(camera_in) { }
01301
01302 virtual void traverse(const LLOctreeNode<LLDrawable>* node)
01303 {
01304 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
01305 group->clearState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED);
01306 LLOctreeTraveler<LLDrawable>::traverse(node);
01307 }
01308
01309 void visit(const LLOctreeState<LLDrawable>* branch)
01310 {
01311 gPipeline.markNotCulled((LLSpatialGroup*) branch->getListener(0), *mCamera, TRUE);
01312 }
01313 };
01314
01315 void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results, BOOL for_select)
01316 {
01317 if (!gPipeline.hasRenderType(mDrawableType))
01318 {
01319 return;
01320 }
01321
01322 LLViewerObject *vobj = mDrawable->getVObj();
01323 if (vobj && vobj->isAttachment() && !vobj->isHUDAttachment())
01324 {
01325 LLVOAvatar* av;
01326 LLDrawable* parent = mDrawable->getParent();
01327
01328 if (parent)
01329 {
01330 av = (LLVOAvatar*) parent->getVObj().get();
01331
01332 if (!av->isVisible())
01333 {
01334 return;
01335 }
01336 }
01337 }
01338
01339
01340 LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
01341 group->rebound();
01342
01343 LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f;
01344 LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f;
01345
01346 if (camera_in.AABBInFrustum(center, size))
01347 {
01348 if (LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
01349 {
01350 return;
01351 }
01352
01353 LLDrawable::setVisible(camera_in);
01354
01355 if (for_select)
01356 {
01357 results->push_back(mDrawable);
01358 for (U32 i = 0; i < mDrawable->getChildCount(); i++)
01359 {
01360 results->push_back(mDrawable->getChild(i));
01361 }
01362 }
01363 else
01364 {
01365 LLCamera trans_camera = transformCamera(camera_in);
01366 LLOctreeMarkNotCulled culler(&trans_camera);
01367 culler.traverse(mOctree);
01368 }
01369 }
01370 }
01371
01372 void LLSpatialBridge::updateDistance(LLCamera& camera_in)
01373 {
01374 if (mDrawable == NULL)
01375 {
01376 markDead();
01377 return;
01378 }
01379
01380 LLCamera camera = transformCamera(camera_in);
01381
01382 mDrawable->updateDistance(camera);
01383
01384 for (U32 i = 0; i < mDrawable->getChildCount(); ++i)
01385 {
01386 LLDrawable* child = mDrawable->getChild(i);
01387 if (!child)
01388 {
01389 llwarns << "Corrupt drawable found while updating spatial bridge distance." << llendl;
01390 continue;
01391 }
01392 child->updateDistance(camera);
01393 }
01394 }
01395
01396 void LLSpatialBridge::makeActive()
01397 {
01398 llerrs << "makeActive called on spatial bridge" << llendl;
01399 }
01400
01401 void LLSpatialBridge::makeStatic()
01402 {
01403 llerrs << "makeStatic called on spatial bridge" << llendl;
01404 }
01405
01406 void LLSpatialBridge::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate)
01407 {
01408 LLSpatialPartition::move(drawablep, curp, immediate);
01409 gPipeline.markMoved(this, FALSE);
01410 }
01411
01412 BOOL LLSpatialBridge::updateMove()
01413 {
01414 mOctree->balance();
01415 gPipeline.getSpatialPartition(mPartitionType)->move(this, getSpatialGroup(), TRUE);
01416 return TRUE;
01417 }
01418
01419 void LLSpatialBridge::shiftPos(const LLVector3& vec)
01420 {
01421 mExtents[0] += vec;
01422 mExtents[1] += vec;
01423 mPositionGroup += LLVector3d(vec);
01424 }
01425
01426 void LLSpatialBridge::cleanupReferences()
01427 {
01428 LLDrawable::cleanupReferences();
01429 if (mDrawable)
01430 {
01431 mDrawable->setSpatialGroup(NULL);
01432 for (U32 i = 0; i < mDrawable->getChildCount(); i++)
01433 {
01434 LLDrawable* drawable = mDrawable->getChild(i);
01435 if (drawable)
01436 {
01437 drawable->setSpatialGroup(NULL);
01438 }
01439 }
01440
01441 LLDrawable* drawablep = mDrawable;
01442 mDrawable = NULL;
01443 drawablep->setSpatialBridge(NULL);
01444 }
01445 }
01446
01447 const LLVector3 LLDrawable::getPositionAgent() const
01448 {
01449 if (getVOVolume())
01450 {
01451 if (isActive())
01452 {
01453 if (isRoot())
01454 {
01455 return LLVector3(0,0,0) * getWorldMatrix();
01456 }
01457 else
01458 {
01459 return mVObjp->getPosition() * getParent()->getWorldMatrix();
01460 }
01461 }
01462 else
01463 {
01464 return mVObjp->getPositionAgent();
01465 }
01466 }
01467 else
01468 {
01469 return getWorldPosition();
01470 }
01471 }
01472
01473 BOOL LLDrawable::isAnimating() const
01474 {
01475 if (!getVObj())
01476 {
01477 return TRUE;
01478 }
01479
01480 if (getScale() != mVObjp->getScale())
01481 {
01482 return TRUE;
01483 }
01484
01485 if (mVObjp->isFlexible())
01486 {
01487 return TRUE;
01488 }
01489
01490 if (mVObjp->getPCode() == LLViewerObject::LL_VO_PART_GROUP)
01491 {
01492 return TRUE;
01493 }
01494
01495 if (mVObjp->getPCode() == LLViewerObject::LL_VO_CLOUDS)
01496 {
01497 return TRUE;
01498 }
01499
01500 LLVOVolume* vol = getVOVolume();
01501 if (vol && vol->mTextureAnimp)
01502 {
01503 return TRUE;
01504 }
01505
01506 if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero())
01507 {
01508 return TRUE;
01509 }
01510
01511 return FALSE;
01512 }
01513
01514 void LLDrawable::updateFaceSize(S32 idx)
01515 {
01516 if (mVObjp.notNull())
01517 {
01518 mVObjp->updateFaceSize(idx);
01519 }
01520 }
01521
01522 LLBridgePartition::LLBridgePartition()
01523 : LLSpatialPartition(0, TRUE)
01524 {
01525 mRenderByGroup = FALSE;
01526 mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
01527 mPartitionType = LLPipeline::PARTITION_BRIDGE;
01528 mLODPeriod = 1;
01529 mSlopRatio = 0.f;
01530 }
01531
01532 LLHUDBridge::LLHUDBridge(LLDrawable* drawablep)
01533 : LLVolumeBridge(drawablep)
01534 {
01535 mDrawableType = LLPipeline::RENDER_TYPE_HUD;
01536 mPartitionType = LLPipeline::PARTITION_HUD;
01537 mSlopRatio = 0.0f;
01538 }
01539
01540 F32 LLHUDBridge::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
01541 {
01542 return 1024.f;
01543 }
01544
01545
01546 void LLHUDBridge::shiftPos(const LLVector3& vec)
01547 {
01548
01549 }
01550