lldrawable.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "lldrawable.h"
00035 
00036 // library includes
00037 #include "material_codes.h"
00038 
00039 // viewer includes
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" // for debugging
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 // Inline implementations.
00065 //
00066 //
00067 
00068 
00069 
00071 //
00072 // Drawable code
00073 //
00074 //
00075 
00076 // static
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 // static
00085 void LLDrawable::incrementVisible() 
00086 {
00087         sCurVisible++;
00088         sCurPixelAngle = (F32) gViewerWindow->getWindowDisplayHeight()/LLViewerCamera::getInstance()->getView();
00089 }
00090 void LLDrawable::init()
00091 {
00092         // mXform
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         // mFaces
00103         mSpatialGroupp = NULL;
00104         mVisible = 0;
00105         mRadius = 0.f;
00106         
00107         mGeneration = -1;
00108         mBinRadius = 1.f;
00109         mSpatialBridge = NULL;
00110 }
00111 
00112 // static
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         /*if (!(sNumZombieDrawables % 10))
00130         {
00131                 llinfos << "- Zombie drawables: " << sNumZombieDrawables << llendl;
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         // We're dead.  Free up all of our references to other objects
00152         setState(DEAD);
00153         cleanupReferences();
00154 //      sDeadList.put(this);
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         // Cleanup references to other objects
00195         mVObjp = NULL;
00196         mParent = NULL;
00197 }
00198 
00199 void LLDrawable::cleanupDeadDrawables()
00200 {
00201         /*
00202         S32 i;
00203         for (i = 0; i < sDeadList.count(); i++)
00204         {
00205                 if (sDeadList[i]->getNumRefs() > 1)
00206                 {
00207                         llwarns << "Dead drawable has " << sDeadList[i]->getNumRefs() << " remaining refs" << llendl;
00208                         gPipeline.findReferences(sDeadList[i]);
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 // (newFaces > mFaces.size())
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 // (newFaces > mFaces.size())
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)) // && mGeneration > 0)
00365         {
00366                 setState(ACTIVE);
00367                 
00368                 //parent must be made active first
00369                 if (!isRoot() && !mParent->isActive())
00370                 {
00371                         mParent->makeActive();
00372                 }
00373 
00374                 gPipeline.setActive(this, TRUE);
00375 
00376                 //all child objects must also be active
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 // Returns "distance" between target destination and resulting xfrom
00453 F32 LLDrawable::updateXform(BOOL undamped)
00454 {
00455         BOOL damped = !undamped;
00456 
00457         // Position
00458         LLVector3 old_pos(mXform.getPosition());
00459         LLVector3 target_pos;
00460         if (mXform.isRoot())
00461         {
00462                 // get root position in your agent's region
00463                 target_pos = mVObjp->getPositionAgent();
00464         }
00465         else
00466         {
00467                 // parent-relative position
00468                 target_pos = mVObjp->getPosition();
00469         }
00470         
00471         // Rotation
00472         LLQuaternion old_rot(mXform.getRotation());
00473         LLQuaternion target_rot = mVObjp->getRotation();
00474         //scaling
00475         LLVector3 target_scale = mVObjp->getScale();
00476         LLVector3 old_scale = mCurrentScale;
00477         LLVector3 dest_scale = target_scale;
00478         
00479         // Damping
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                         // interpolate
00499                         target_pos = new_pos;
00500                         target_rot = new_rot;
00501                         target_scale = new_scale;
00502                 }
00503                 else
00504                 {
00505                         // snap to final position
00506                         dist_squared = 0.0f;
00507                 }
00508         }
00509 
00510         if ((mCurrentScale != target_scale) ||
00511                 (!isRoot() && (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED*camdist2)))
00512         { //child prim moving or scale change requires immediate rebuild
00513                 gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
00514         }
00515         else if (!getVOVolume() && !isAvatar())
00516         {
00517                 movePartition();
00518         }
00519 
00520         // Update
00521         mXform.setPosition(target_pos);
00522         mXform.setRotation(target_rot);
00523         mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)
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         // Update the face centers.
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                 //a child prim moved and needs its verts regenerated
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         //switch LOD with the spatial group to avoid artifacts
00652         //LLSpatialGroup* sg = getSpatialGroup();
00653 
00654         LLVector3 pos;
00655 
00656         //if (!sg || sg->changeLOD())
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         { //drawable is transitioning its face count
00707                 return;
00708         }
00709 
00710         if (getVOVolume())
00711         {
00712                 if (!isActive())
00713                 {
00714                         //gPipeline.markMoved(this);
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         // TODO: maintain a list of objects that have special
00854         // hover cursors, then use that list for per-frame
00855         // hover cursor selection. JC
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                         // llwarns ?
00872                 }
00873         }
00874         return getRadius();
00875 }
00876 
00877 void LLDrawable::updateUVMinMax()
00878 {
00879 }
00880 
00881 void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)
00882 {
00883 /*if (mSpatialGroupp && (groupp != mSpatialGroupp))
00884         {
00885                 mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY);
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         {       //must be an active volume
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 // Spatial Partition Bridging Drawable
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         //get 4 corners of bounding box
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         //crazy paranoid rules checking
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         //HACK don't draw attachments for avatars that haven't been visible in more than a frame
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 { //it is an error to make a spatial bridge active (it's already active)
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         //don't shift hud bridges on region crossing
01384 }
01385 

Generated on Fri May 16 08:33:17 2008 for SecondLife by  doxygen 1.5.5