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