00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerobjectlist.h"
00035 
00036 #include "message.h"
00037 #include "timing.h"
00038 #include "llfasttimer.h"
00039 
00040 #include "llviewercontrol.h"
00041 #include "llface.h"
00042 #include "llvoavatar.h"
00043 #include "llviewerobject.h"
00044 #include "llviewerwindow.h"
00045 #include "viewer.h"
00046 #include "llnetmap.h"
00047 #include "llagent.h"
00048 #include "pipeline.h"
00049 #include "llhoverview.h"
00050 #include "llworld.h"
00051 #include "llstring.h"
00052 #include "llhudtext.h"
00053 #include "lldrawable.h"
00054 #include "xform.h"
00055 #include "llsky.h"
00056 #include "llviewercamera.h"
00057 #include "llselectmgr.h"
00058 #include "llresmgr.h"
00059 #include "llviewerregion.h"
00060 #include "llviewerstats.h"
00061 #include "lltoolmgr.h"
00062 #include "lltoolpie.h"
00063 #include "llkeyboard.h"
00064 #include "u64.h"
00065 #include "llviewerimagelist.h"
00066 #include "lldatapacker.h"
00067 #ifdef LL_STANDALONE
00068 #include <zlib.h>
00069 #else
00070 #include "zlib/zlib.h"
00071 #endif
00072 #include "object_flags.h"
00073 
00074 extern BOOL gVelocityInterpolate;
00075 extern BOOL gPingInterpolate;
00076 extern F32 gMinObjectDistance;
00077 extern U32 gFrameCount;
00078 extern LLTimer gRenderStartTime;
00079 extern BOOL gAnimateTextures;
00080 
00081 void dialog_refresh_all();
00082 
00083 #define CULL_VIS
00084 
00085 
00086 
00087 
00088 LLViewerObjectList gObjectList;
00089 
00090 extern LLPipeline       gPipeline;
00091 
00092 
00093 U32                                             LLViewerObjectList::sSimulatorMachineIndex = 1; 
00094 LLMap<U64, U32>                 LLViewerObjectList::sIPAndPortToIndex;
00095 std::map<U64, LLUUID>   LLViewerObjectList::sIndexAndLocalIDToUUID;
00096 
00097 LLViewerObjectList::LLViewerObjectList()
00098 {
00099         mNumVisCulled = 0;
00100         mNumSizeCulled = 0;
00101         mCurLazyUpdateIndex = 0;
00102         mCurBin = 0;
00103         mNumDeadObjects = 0;
00104         mNumOrphans = 0;
00105         mNumNewObjects = 0;
00106         mWasPaused = FALSE;
00107         mNumDeadObjectUpdates = 0;
00108         mNumUnknownKills = 0;
00109         mNumUnknownUpdates = 0;
00110 }
00111 
00112 LLViewerObjectList::~LLViewerObjectList()
00113 {
00114         destroy();
00115 }
00116 
00117 void LLViewerObjectList::destroy()
00118 {
00119         killAllObjects();
00120 
00121         resetObjectBeacons();
00122         mActiveObjects.clear();
00123         mDeadObjects.clear();
00124         mMapObjects.clear();
00125         mUUIDObjectMap.clear();
00126 }
00127 
00128 
00129 void LLViewerObjectList::getUUIDFromLocal(LLUUID &id,
00130                                                                                   const U32 local_id,
00131                                                                                   const U32 ip,
00132                                                                                   const U32 port)
00133 {
00134         U64 ipport = (((U64)ip) << 32) | (U64)port;
00135 
00136         U32 index = sIPAndPortToIndex[ipport];
00137 
00138         if (!index)
00139         {
00140                 index = sSimulatorMachineIndex++;
00141                 sIPAndPortToIndex[ipport] = index;
00142         }
00143 
00144         U64     indexid = (((U64)index) << 32) | (U64)local_id;
00145 
00146         id = get_if_there(sIndexAndLocalIDToUUID, indexid, LLUUID::null);
00147 }
00148 
00149 U64 LLViewerObjectList::getIndex(const U32 local_id,
00150                                                                  const U32 ip,
00151                                                                  const U32 port)
00152 {
00153         U64 ipport = (((U64)ip) << 32) | (U64)port;
00154 
00155         U32 index = sIPAndPortToIndex[ipport];
00156 
00157         if (!index)
00158         {
00159                 return 0;
00160         }
00161 
00162         return (((U64)index) << 32) | (U64)local_id;
00163 }
00164 
00165 BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
00166 {
00167         U32 local_id = object.mLocalID;
00168         LLHost region_host = object.getRegion()->getHost();
00169         U32 ip = region_host.getAddress();
00170         U32 port = region_host.getPort();
00171         U64 ipport = (((U64)ip) << 32) | (U64)port;
00172         U32 index = sIPAndPortToIndex[ipport];
00173 
00174         U64     indexid = (((U64)index) << 32) | (U64)local_id;
00175         return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE;
00176 }
00177 
00178 void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id,
00179                                                                                   const U32 local_id,
00180                                                                                   const U32 ip,
00181                                                                                   const U32 port)
00182 {
00183         U64 ipport = (((U64)ip) << 32) | (U64)port;
00184 
00185         U32 index = sIPAndPortToIndex[ipport];
00186 
00187         if (!index)
00188         {
00189                 index = sSimulatorMachineIndex++;
00190                 sIPAndPortToIndex[ipport] = index;
00191         }
00192 
00193         U64     indexid = (((U64)index) << 32) | (U64)local_id;
00194 
00195         sIndexAndLocalIDToUUID[indexid] = id;
00196 }
00197 
00198 S32 gFullObjectUpdates = 0;
00199 S32 gTerseObjectUpdates = 0;
00200 
00201 void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, 
00202                                                                                    void** user_data, 
00203                                                                                    U32 i, 
00204                                                                                    const EObjectUpdateType update_type, 
00205                                                                                    LLDataPacker* dpp, 
00206                                                                                    BOOL just_created)
00207 {
00208         LLMessageSystem* msg = gMessageSystem;
00209 
00210         
00211         objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
00212 
00213         if (objectp->isDead())
00214         {
00215                 
00216                 return;
00217         }
00218         updateActive(objectp);
00219 
00220         
00221         objectp->setPixelAreaAndAngle(gAgent);
00222 
00223         
00224         objectp->updateTextures(gAgent);
00225 
00226         if (just_created) 
00227         {
00228                 gPipeline.addObject(objectp);
00229         }
00230 
00231         
00232         
00233         
00234         findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
00235 
00236         
00237         if (just_created 
00238                 && update_type != OUT_TERSE_IMPROVED 
00239                 && objectp->mCreateSelected)
00240         {
00241                 if ( gToolMgr->getCurrentTool() != gToolPie )
00242                 {
00243                         
00244                         
00245                         gSelectMgr->selectObjectAndFamily(objectp);
00246                         dialog_refresh_all();
00247                 }
00248 
00249                 objectp->mCreateSelected = false;
00250                 gViewerWindow->getWindow()->decBusyCount();
00251                 gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW );
00252         }
00253 }
00254 
00255 void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
00256                                                                                          void **user_data,
00257                                                                                          const EObjectUpdateType update_type,
00258                                                                                          bool cached, bool compressed)
00259 {
00260         LLFastTimer t(LLFastTimer::FTM_PROCESS_OBJECTS);        
00261         
00262         LLVector3d camera_global = gAgent.getCameraPositionGlobal();
00263         LLViewerObject *objectp;
00264         S32                     num_objects;
00265         U32                     local_id;
00266         LLPCode         pcode = 0;
00267         LLUUID          fullid;
00268         S32                     i;
00269 
00270         
00271         
00272         
00273         
00274         num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
00275 
00276         if (!cached && !compressed && update_type != OUT_FULL)
00277         {
00278                 gTerseObjectUpdates += num_objects;
00279                 S32 size;
00280                 if (mesgsys->getReceiveCompressedSize())
00281                 {
00282                         size = mesgsys->getReceiveCompressedSize();
00283                 }
00284                 else
00285                 {
00286                         size = mesgsys->getReceiveSize();
00287                 }
00288 
00289         }
00290         else
00291         {
00292                 S32 size;
00293                 if (mesgsys->getReceiveCompressedSize())
00294                 {
00295                         size = mesgsys->getReceiveCompressedSize();
00296                 }
00297                 else
00298                 {
00299                         size = mesgsys->getReceiveSize();
00300                 }
00301 
00302 
00303                 gFullObjectUpdates += num_objects;
00304         }
00305 
00306         U64 region_handle;
00307         mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
00308         LLViewerRegion *regionp = gWorldPointer->getRegionFromHandle(region_handle);
00309 
00310         if (!regionp)
00311         {
00312                 llwarns << "Object update from unknown region!" << llendl;
00313                 return;
00314         }
00315 
00316         U8 compressed_dpbuffer[2048];
00317         LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
00318         LLDataPacker *cached_dpp = NULL;
00319         
00320         for (i = 0; i < num_objects; i++)
00321         {
00322                 LLTimer update_timer;
00323                 BOOL justCreated = FALSE;
00324 
00325                 if (cached)
00326                 {
00327                         U32 id;
00328                         U32 crc;
00329                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
00330                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
00331                 
00332                         
00333                         cached_dpp = regionp->getDP(id, crc);
00334                         if (cached_dpp)
00335                         {
00336                                 cached_dpp->reset();
00337                                 cached_dpp->unpackUUID(fullid, "ID");
00338                                 cached_dpp->unpackU32(local_id, "LocalID");
00339                                 cached_dpp->unpackU8(pcode, "PCode");
00340                         }
00341                         else
00342                         {
00343                                 continue; 
00344                         }
00345                 }
00346                 else if (compressed)
00347                 {
00348                         U8                                                      compbuffer[2048];
00349                         S32                                                     uncompressed_length = 2048;
00350                         S32                                                     compressed_length;
00351                         
00352                         compressed_dp.reset();
00353 
00354                         U32 flags = 0;
00355                         if (update_type != OUT_TERSE_IMPROVED)
00356                         {
00357                                 mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
00358                         }
00359                         
00360                         if (flags & FLAGS_ZLIB_COMPRESSED)
00361                         {
00362                                 compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
00363                                 mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i);
00364                                 uncompressed_length = 2048;
00365                                 uncompress(compressed_dpbuffer, (unsigned long *)&uncompressed_length,
00366                                                    compbuffer, compressed_length);
00367                                 compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
00368                         }
00369                         else
00370                         {
00371                                 uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
00372                                 mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i);
00373                                 compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
00374                         }
00375 
00376 
00377                         if (update_type != OUT_TERSE_IMPROVED)
00378                         {
00379                                 compressed_dp.unpackUUID(fullid, "ID");
00380                                 compressed_dp.unpackU32(local_id, "LocalID");
00381                                 compressed_dp.unpackU8(pcode, "PCode");
00382                         }
00383                         else
00384                         {
00385                                 compressed_dp.unpackU32(local_id, "LocalID");
00386                                 getUUIDFromLocal(fullid,
00387                                                                  local_id,
00388                                                                  gMessageSystem->getSenderIP(),
00389                                                                  gMessageSystem->getSenderPort());
00390                                 if (fullid.isNull())
00391                                 {
00392                                         
00393                                         mNumUnknownUpdates++;
00394                                 }
00395                         }
00396                 }
00397                 else if (update_type != OUT_FULL)
00398                 {
00399                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
00400                         getUUIDFromLocal(fullid,
00401                                                         local_id,
00402                                                         gMessageSystem->getSenderIP(),
00403                                                         gMessageSystem->getSenderPort());
00404                         if (fullid.isNull())
00405                         {
00406                                 
00407                                 mNumUnknownUpdates++;
00408                         }
00409                 }
00410                 else
00411                 {
00412                         mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
00413                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
00414                 
00415                 }
00416                 objectp = findObject(fullid);
00417 
00418                 
00419                 
00420                 if (objectp && (objectp->mLocalID != local_id))
00421                 {
00422                         removeFromLocalIDTable(*objectp);
00423                         setUUIDAndLocal(fullid,
00424                                                         local_id,
00425                                                         gMessageSystem->getSenderIP(),
00426                                                         gMessageSystem->getSenderPort());
00427                 }
00428 
00429                 if (!objectp)
00430                 {
00431                         if (compressed)
00432                         {
00433                                 if (update_type == OUT_TERSE_IMPROVED)
00434                                 {
00435                                         
00436                                         continue;
00437                                 }
00438                         }
00439                         else if (cached)
00440                         {
00441                         }
00442                         else
00443                         {
00444                                 if (update_type != OUT_FULL)
00445                                 {
00446 
00447                                         continue;
00448                                 }
00449 
00450                                 mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i);
00451                         }
00452 #ifdef IGNORE_DEAD
00453                         if (mDeadObjects.find(fullid) != mDeadObjects.end())
00454                         {
00455                                 mNumDeadObjectUpdates++;
00456                                 
00457                                 continue;
00458                         }
00459 #endif
00460 
00461                         objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());
00462                         if (!objectp)
00463                         {
00464                                 continue;
00465                         }
00466                         justCreated = TRUE;
00467                         mNumNewObjects++;
00468                 }
00469                 else
00470                 {
00471                         if (objectp->getRegion() != regionp)
00472                         {
00473                                 
00474                                 removeFromLocalIDTable(*objectp);
00475                                 setUUIDAndLocal(fullid,
00476                                                                 local_id,
00477                                                                 gMessageSystem->getSenderIP(),
00478                                                                 gMessageSystem->getSenderPort());
00479                                 objectp->setRegion(regionp);
00480                         }
00481                         objectp->updateRegion(regionp); 
00482                 }
00483 
00484 
00485                 if (objectp->isDead())
00486                 {
00487                         llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
00488                 }
00489 
00490                 if (compressed)
00491                 {
00492                         if (update_type != OUT_TERSE_IMPROVED)
00493                         {
00494                                 objectp->mLocalID = local_id;
00495                         }
00496                         processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
00497                         if (update_type != OUT_TERSE_IMPROVED)
00498                         {
00499                                 objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
00500                         }
00501                 }
00502                 else if (cached)
00503                 {
00504                         objectp->mLocalID = local_id;
00505                         processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated);
00506                 }
00507                 else
00508                 {
00509                         if (update_type == OUT_FULL)
00510                         {
00511                                 objectp->mLocalID = local_id;
00512                         }
00513                         processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);
00514                 }
00515         }
00516 
00517         LLVOAvatar::cullAvatarsByPixelArea();
00518 }
00519 
00520 void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys,
00521                                                                                          void **user_data,
00522                                                                                          const EObjectUpdateType update_type)
00523 {
00524         processObjectUpdate(mesgsys, user_data, update_type, false, true);
00525 }
00526 
00527 void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
00528                                                                                          void **user_data,
00529                                                                                          const EObjectUpdateType update_type)
00530 {
00531         processObjectUpdate(mesgsys, user_data, update_type, true, false);
00532 }       
00533 
00534 void LLViewerObjectList::relightAllObjects()
00535 {
00536         for (S32 i = 0; i < mObjects.count(); i++)
00537         {
00538                 LLDrawable *drawable = mObjects[i]->mDrawable;
00539                 if (drawable)
00540                 {
00541                         gPipeline.markRelight(drawable);
00542                 }
00543         }
00544 }
00545 
00546 void LLViewerObjectList::dirtyAllObjectInventory()
00547 {
00548         S32 count = mObjects.count();
00549         for(S32 i = 0; i < count; ++i)
00550         {
00551                 mObjects[i]->dirtyInventory();
00552         }
00553 }
00554 
00555 void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
00556 {
00557         S32 i;
00558         S32 num_objects = 0;
00559         LLViewerObject *objectp;
00560 
00561         S32 num_updates, max_value;
00562         if (NUM_BINS - 1 == mCurBin)
00563         {
00564                 num_updates = mObjects.count() - mCurLazyUpdateIndex;
00565                 max_value = mObjects.count();
00566                 gImageList.setUpdateStats(TRUE);
00567         }
00568         else
00569         {
00570                 num_updates = (mObjects.count() / NUM_BINS) + 1;
00571                 max_value = llmin(mObjects.count(), mCurLazyUpdateIndex + num_updates);
00572         }
00573 
00574 
00575         if (!gNoRender)
00576         {
00577                 
00578                 
00579                 
00580                 objectp = gHoverView->getLastHoverObject();
00581                 if (objectp)
00582                 {
00583                         objectp->boostTexturePriority();
00584                 }
00585         }
00586 
00587         
00588         objectp = gAgent.getFocusObject();
00589         if (objectp)
00590         {
00591                 objectp->boostTexturePriority();
00592         }
00593 
00594         
00595         struct f : public LLSelectedObjectFunctor
00596         {
00597                 virtual bool apply(LLViewerObject* objectp)
00598                 {
00599                         objectp->boostTexturePriority();
00600                         return true;
00601                 }
00602         } func;
00603         gSelectMgr->getSelection()->applyToRootObjects(&func);
00604 
00605         
00606         for (i = mCurLazyUpdateIndex; i < max_value; i++)
00607         {
00608                 objectp = mObjects[i];
00609                 if (!objectp->isDead())
00610                 {
00611                         num_objects++;
00612 
00613                         
00614                         objectp->setPixelAreaAndAngle(agent); 
00615                         objectp->updateTextures(agent); 
00616                 }
00617         }
00618 
00619         mCurLazyUpdateIndex = max_value;
00620         if (mCurLazyUpdateIndex == mObjects.count())
00621         {
00622                 mCurLazyUpdateIndex = 0;
00623         }
00624 
00625         mCurBin = (++mCurBin) % NUM_BINS;
00626 
00627         LLVOAvatar::cullAvatarsByPixelArea();
00628 }
00629 
00630 
00631 void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
00632 {
00633         LLMemType mt(LLMemType::MTYPE_OBJECT);
00634         
00635         gVelocityInterpolate = gSavedSettings.getBOOL("VelocityInterpolate");
00636         gPingInterpolate = gSavedSettings.getBOOL("PingInterpolate");
00637         gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
00638 
00639         
00640         F32 last_time = gFrameTimeSeconds;
00641         U64 time = totalTime();                 
00642         
00643         
00644 
00645         F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC;
00646         gFrameTime    = time;
00647         F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC;
00648         gFrameTimeSeconds = (F32)time_since_start;
00649 
00650         gFrameIntervalSeconds = gFrameTimeSeconds - last_time;
00651         if (gFrameIntervalSeconds < 0.f)
00652         {
00653                 gFrameIntervalSeconds = 0.f;
00654         }
00655 
00656         
00657         LLVOAvatar::sNumLODChangesThisFrame = 0;
00658 
00659         const F64 frame_time = LLFrameTimer::getElapsedSeconds();
00660         
00661         std::vector<LLViewerObject*> kill_list;
00662         S32 num_active_objects = 0;
00663         LLViewerObject *objectp = NULL; 
00664         
00665         
00666         std::vector<LLViewerObject*> idle_list;
00667         idle_list.reserve( mActiveObjects.size() );
00668 
00669         for (std::set<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin();
00670                 active_iter != mActiveObjects.end(); active_iter++)
00671         {
00672                 objectp = *active_iter;
00673                 if (objectp)
00674                 {
00675                         idle_list.push_back( objectp );
00676                 }
00677                 else
00678                 {       
00679                         
00680                         llwarns << "LLViewerObjectList::update has a NULL objectp" << llendl;
00681                 }
00682         }
00683 
00684         if (gSavedSettings.getBOOL("FreezeTime"))
00685         {
00686                 for (std::vector<LLViewerObject*>::iterator iter = idle_list.begin();
00687                         iter != idle_list.end(); iter++)
00688                 {
00689                         objectp = *iter;
00690                         if (objectp->getPCode() == LLViewerObject::LL_VO_CLOUDS ||
00691                                 objectp->isAvatar())
00692                         {
00693                                 objectp->idleUpdate(agent, world, frame_time);
00694                         }
00695                 }
00696         }
00697         else
00698         {
00699                 for (std::vector<LLViewerObject*>::iterator idle_iter = idle_list.begin();
00700                         idle_iter != idle_list.end(); idle_iter++)
00701                 {
00702                         objectp = *idle_iter;
00703                         if (!objectp->idleUpdate(agent, world, frame_time))
00704                         {
00705                                 
00706                                 kill_list.push_back(objectp);
00707                         }
00708                         else
00709                         {
00710                                 num_active_objects++;
00711                         }
00712                 }
00713                 for (std::vector<LLViewerObject*>::iterator kill_iter = kill_list.begin();
00714                         kill_iter != kill_list.end(); kill_iter++)
00715                 {
00716                         objectp = *kill_iter;
00717                         killObject(objectp);
00718                 }
00719         }
00720 
00721         mNumSizeCulled = 0;
00722         mNumVisCulled = 0;
00723 
00724         
00725         
00726         if (! mWasPaused)
00727         {
00728                 gViewerStats->updateFrameStats(time_diff);
00729         }
00730 
00731         
00732 
00733 
00734 
00735 
00736 
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 
00777 
00778         mNumObjectsStat.addValue(mObjects.count());
00779         mNumActiveObjectsStat.addValue(num_active_objects);
00780         mNumSizeCulledStat.addValue(mNumSizeCulled);
00781         mNumVisCulledStat.addValue(mNumVisCulled);
00782 }
00783 
00784 void LLViewerObjectList::clearDebugText()
00785 {
00786         for (S32 i = 0; i < mObjects.count(); i++)
00787         {
00788                 mObjects[i]->setDebugText("");
00789         }
00790 }
00791 
00792 
00793 void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
00794 {
00795         LLMemType mt(LLMemType::MTYPE_OBJECT);
00796         if (mDeadObjects.count(objectp->mID))
00797         {
00798                 llinfos << "Object " << objectp->mID << " already on dead list, ignoring cleanup!" << llendl;   
00799                 return;
00800         }
00801 
00802         mDeadObjects.insert(std::pair<LLUUID, LLPointer<LLViewerObject> >(objectp->mID, objectp));
00803 
00804         
00805         
00806 
00807         mUUIDObjectMap.erase(objectp->mID);
00808         removeFromLocalIDTable(*objectp);
00809 
00810         if (objectp->onActiveList())
00811         {
00812                 
00813                 objectp->setOnActiveList(FALSE);
00814                 mActiveObjects.erase(objectp);
00815         }
00816 
00817         if (objectp->isOnMap())
00818         {
00819                 mMapObjects.removeObj(objectp);
00820         }
00821 
00822         
00823         
00824         removeDrawable(objectp->mDrawable);
00825 
00826         mNumDeadObjects++;
00827 }
00828 
00829 void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
00830 {
00831         if (!drawablep)
00832         {
00833                 return;
00834         }
00835 
00836         for (S32 i = 0; i < drawablep->getNumFaces(); i++)
00837         {
00838                 LLViewerObject* objectp = drawablep->getFace(i)->getViewerObject();
00839                 mSelectPickList.erase(objectp);
00840         }
00841 }
00842 
00843 BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
00844 {
00845         
00846         
00847 
00848         if (objectp)
00849         {
00850                 if (objectp->isDead())
00851                 {
00852                         
00853                         return TRUE;
00854                 }
00855                 else
00856                 {
00857                         objectp->markDead();
00858                 }
00859 
00860                 return TRUE;
00861         }
00862         return FALSE;
00863 }
00864 
00865 void LLViewerObjectList::killObjects(LLViewerRegion *regionp)
00866 {
00867         LLViewerObject *objectp;
00868 
00869         S32 i;
00870         for (i = 0; i < mObjects.count(); i++)
00871         {
00872                 objectp = mObjects[i];
00873                 
00874                 if (objectp->mRegionp == regionp)
00875                 {
00876                         killObject(objectp);
00877                 }
00878         }
00879 
00880         
00881         cleanDeadObjects(FALSE);
00882 }
00883 
00884 void LLViewerObjectList::killAllObjects()
00885 {
00886         
00887         LLViewerObject *objectp;
00888 
00889         for (S32 i = 0; i < mObjects.count(); i++)
00890         {
00891                 objectp = mObjects[i];
00892                 
00893                 killObject(objectp);
00894                 llassert(objectp->isDead());
00895         }
00896 
00897         cleanDeadObjects(FALSE);
00898 
00899         if(!mObjects.empty())
00900         {
00901                 llwarns << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.count() << llendl;
00902                 mObjects.clear();
00903         }
00904 
00905         if (!mActiveObjects.empty())
00906         {
00907                 llwarns << "Some objects still on active object list!" << llendl;
00908                 mActiveObjects.clear();
00909         }
00910 
00911         if (!mMapObjects.empty())
00912         {
00913                 llwarns << "Some objects still on map object list!" << llendl;
00914                 mActiveObjects.clear();
00915         }
00916 }
00917 
00918 void LLViewerObjectList::cleanDeadObjects(BOOL use_timer)
00919 {
00920         if (!mNumDeadObjects)
00921         {
00922                 
00923                 return;
00924         }
00925 
00926         S32 i = 0;
00927         S32 num_removed = 0;
00928         LLViewerObject *objectp;
00929         while (i < mObjects.count())
00930         {
00931                 
00932                 objectp = mObjects[i];
00933                 if (objectp->isDead())
00934                 {
00935                         mObjects.remove(i);
00936                         num_removed++;
00937 
00938                         if (num_removed == mNumDeadObjects)
00939                         {
00940                                 
00941                                 break;
00942                         }
00943                 }
00944                 else
00945                 {
00946                         
00947                         i++;
00948                 }
00949         }
00950 
00951         
00952         
00953         mDeadObjects.clear();
00954         mNumDeadObjects = 0;
00955 }
00956 
00957 void LLViewerObjectList::updateActive(LLViewerObject *objectp)
00958 {
00959         LLMemType mt(LLMemType::MTYPE_OBJECT);
00960         if (objectp->isDead())
00961         {
00962                 return; 
00963         }
00964 
00965         BOOL active = objectp->isActive();
00966         if (active != objectp->onActiveList())
00967         {
00968                 if (active)
00969                 {
00970                         
00971                         mActiveObjects.insert(objectp);
00972                         objectp->setOnActiveList(TRUE);
00973                 }
00974                 else
00975                 {
00976                         
00977                         mActiveObjects.erase(objectp);
00978                         objectp->setOnActiveList(FALSE);
00979                 }
00980         }
00981 }
00982 
00983 
00984 
00985 void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
00986 {
00987         
00988         
00989         
00990 
00991         if (gNoRender || 0 == offset.magVecSquared())
00992         {
00993                 return;
00994         }
00995 
00996         LLViewerObject *objectp;
00997         S32 i;
00998         for (i = 0; i < mObjects.count(); i++)
00999         {
01000                 objectp = getObject(i);
01001                 
01002                 if (objectp)
01003                 {
01004                         objectp->updatePositionCaches();
01005 
01006                         if (objectp->mDrawable.notNull() && !objectp->mDrawable->isDead())
01007                         {
01008                                 gPipeline.markShift(objectp->mDrawable);
01009                         }
01010                 }
01011         }
01012 
01013         gPipeline.shiftObjects(offset);
01014         gWorldPointer->mPartSim.shift(offset);
01015 }
01016 
01017 void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
01018 {
01019         LLColor4 above_water_color = gColors.getColor( "NetMapOtherOwnAboveWater" );
01020         LLColor4 below_water_color = gColors.getColor( "NetMapOtherOwnBelowWater" );
01021         LLColor4 you_own_above_water_color = 
01022                                                 gColors.getColor( "NetMapYouOwnAboveWater" );
01023         LLColor4 you_own_below_water_color = 
01024                                                 gColors.getColor( "NetMapYouOwnBelowWater" );
01025         LLColor4 group_own_above_water_color = 
01026                                                 gColors.getColor( "NetMapGroupOwnAboveWater" );
01027         LLColor4 group_own_below_water_color = 
01028                                                 gColors.getColor( "NetMapGroupOwnBelowWater" );
01029 
01030 
01031         for (S32 i = 0; i < mMapObjects.count(); i++)
01032         {
01033                 LLViewerObject* objectp = mMapObjects[i];
01034                 if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment())
01035                 {
01036                         continue;
01037                 }
01038                 const LLVector3& scale = objectp->getScale();
01039                 const LLVector3d pos = objectp->getPositionGlobal();
01040                 const F64 water_height = F64( objectp->getRegion()->getWaterHeight() );
01041                 
01042 
01043                 F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f;  
01044 
01045                 LLColor4U color = above_water_color;
01046                 if( objectp->permYouOwner() )
01047                 {
01048                         const F32 MIN_RADIUS_FOR_OWNED_OBJECTS = 2.f;
01049                         if( approx_radius < MIN_RADIUS_FOR_OWNED_OBJECTS )
01050                         {
01051                                 approx_radius = MIN_RADIUS_FOR_OWNED_OBJECTS;
01052                         }
01053 
01054                         if( pos.mdV[VZ] >= water_height )
01055                         {
01056                                 if ( objectp->permGroupOwner() )
01057                                 {
01058                                         color = group_own_above_water_color;
01059                                 }
01060                                 else
01061                                 {
01062                                 color = you_own_above_water_color;
01063                         }
01064                         }
01065                         else
01066                         {
01067                                 if ( objectp->permGroupOwner() )
01068                                 {
01069                                         color = group_own_below_water_color;
01070                                 }
01071                         else
01072                         {
01073                                 color = you_own_below_water_color;
01074                         }
01075                 }
01076                 }
01077                 else
01078                 if( pos.mdV[VZ] < water_height )
01079                 {
01080                         color = below_water_color;
01081                 }
01082 
01083                 netmap.renderScaledPointGlobal( 
01084                         pos, 
01085                         color,
01086                         approx_radius );
01087         }
01088 }
01089 
01090 void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er)
01091 {
01092 }
01093 
01094 
01095 U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall, BOOL keep_pick_list)
01096 {
01097         gRenderForSelect = TRUE;
01098 
01099         
01100         if (!keep_pick_list)
01101         {
01102                 LLViewerObject *objectp;
01103                 S32 i;
01104                 
01105                 for (i = 0; i < mObjects.count(); i++)
01106                 {
01107                         objectp = mObjects[i];
01108                         objectp->mGLName = 0;
01109                 }
01110 
01111                 mSelectPickList.clear();
01112 
01113                 std::vector<LLDrawable*> pick_drawables;
01114 
01115                 for (i = 0; i < LLPipeline::NUM_PARTITIONS-1; i++)
01116                 {
01117                         LLSpatialPartition* part = gPipeline.getSpatialPartition(i);
01118                         if (part)
01119                         {
01120                                 part->cull(camera, &pick_drawables, TRUE);
01121                         }
01122                 }
01123 
01124                 for (std::vector<LLDrawable*>::iterator iter = pick_drawables.begin();
01125                         iter != pick_drawables.end(); iter++)
01126                 {
01127                         LLDrawable* drawablep = *iter;
01128                         if( !drawablep )
01129                                 continue;
01130 
01131                         LLViewerObject* last_objectp = NULL;
01132                         for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
01133                         {
01134                                 LLViewerObject* objectp = drawablep->getFace(face_num)->getViewerObject();
01135 
01136                                 if (objectp && objectp != last_objectp)
01137                                 {
01138                                         mSelectPickList.insert(objectp);
01139                                         last_objectp = objectp;
01140                                 }
01141                         }
01142                 }
01143 
01144                 LLHUDText::addPickable(mSelectPickList);
01145 
01146                 for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
01147                         iter != LLCharacter::sInstances.end(); ++iter)
01148                 {
01149                         objectp = (LLVOAvatar*) *iter;
01150                         if (!objectp->isDead())
01151                         {
01152                                 if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible())
01153                                 {
01154                                         mSelectPickList.insert(objectp);
01155                                 }
01156                         }
01157                 }
01158 
01159                 
01160                 LLVOAvatar* avatarp = gAgent.getAvatarObject();
01161                 if (avatarp)
01162                 {
01163                         LLViewerJointAttachment* attachmentp;
01164                         for (attachmentp = avatarp->mAttachmentPoints.getFirstData();
01165                                 attachmentp;
01166                                 attachmentp = avatarp->mAttachmentPoints.getNextData())
01167                         {
01168                                 if (attachmentp->getIsHUDAttachment())
01169                                 {
01170                                         LLViewerObject* objectp = attachmentp->getObject();
01171                                         if (objectp)
01172                                         {
01173                                                 mSelectPickList.insert(objectp);                
01174                                                 for (U32 i = 0; i < objectp->mChildList.size(); i++)
01175                                                 {
01176                                                         LLViewerObject* childp = objectp->mChildList[i];
01177                                                         if (childp)
01178                                                         {
01179                                                                 mSelectPickList.insert(childp);
01180                                                         }
01181                                                 }
01182                                         }
01183                                 }
01184                         }
01185                 }
01186                 
01187                 S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances();
01188 
01189                 if (num_pickables != 0)
01190                 {
01191                         S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
01192 
01193                         std::set<LLViewerObject*>::iterator pick_it;
01194                         i = 0;
01195                         for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
01196                         {
01197                                 LLViewerObject* objp = (*pick_it);
01198                                 if (!objp || objp->isDead() || !objp->mbCanSelect)
01199                                 {
01200                                         mSelectPickList.erase(pick_it++);
01201                                         continue;
01202                                 }
01203                                 
01204                                 objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
01205                                 i++;
01206                                 ++pick_it;
01207                         }
01208 
01209                         LLHUDIcon::generatePickIDs(i * step, step);
01210                 
01211                         
01212                         gPipeline.renderForSelect(mSelectPickList);
01213                 }
01214         }
01215 
01216         
01217         
01218         
01219         gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE );
01220 
01221         
01222         LLHUDObject::renderAllForSelect();
01223 
01224         gRenderForSelect = FALSE;
01225 
01226         
01227         
01228         return 0;
01229 }
01230 
01231 LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
01232 {
01233         std::set<LLViewerObject*>::iterator pick_it;
01234         for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it)
01235         {
01236                 if ((*pick_it)->mGLName == object_id)
01237                 {
01238                         return (*pick_it);
01239                 }
01240         }
01241         return NULL;
01242 }
01243 
01244 void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
01245                                                                                 const LLString &string,
01246                                                                                 const LLColor4 &color,
01247                                                                                 const LLColor4 &text_color,
01248                                                                                 S32 line_width)
01249 {
01250         LLDebugBeacon *beaconp = mDebugBeacons.reserve_block(1);
01251         beaconp->mPositionAgent = pos_agent;
01252         beaconp->mString = string;
01253         beaconp->mColor = color;
01254         beaconp->mTextColor = text_color;
01255         beaconp->mLineWidth = line_width;
01256 }
01257 
01258 void LLViewerObjectList::resetObjectBeacons()
01259 {
01260         mDebugBeacons.reset();
01261 }
01262 
01263 LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp)
01264 {
01265         LLMemType mt(LLMemType::MTYPE_OBJECT);
01266         LLUUID fullid;
01267         fullid.generate();
01268 
01269         LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
01270         if (!objectp)
01271         {
01272 
01273                 return NULL;
01274         }
01275 
01276         mUUIDObjectMap[fullid] = objectp;
01277 
01278         mObjects.put(objectp);
01279 
01280         updateActive(objectp);
01281 
01282         return objectp;
01283 }
01284 
01285 
01286 
01287 LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp,
01288                                                                                                  const LLUUID &uuid, const U32 local_id, const LLHost &sender)
01289 {
01290         LLMemType mt(LLMemType::MTYPE_OBJECT);
01291         LLFastTimer t(LLFastTimer::FTM_CREATE_OBJECT);
01292         
01293         LLUUID fullid;
01294         if (uuid == LLUUID::null)
01295         {
01296                 fullid.generate();
01297         }
01298         else
01299         {
01300                 fullid = uuid;
01301         }
01302 
01303         LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
01304         if (!objectp)
01305         {
01306 
01307                 return NULL;
01308         }
01309 
01310         mUUIDObjectMap[fullid] = objectp;
01311         setUUIDAndLocal(fullid,
01312                                         local_id,
01313                                         gMessageSystem->getSenderIP(),
01314                                         gMessageSystem->getSenderPort());
01315 
01316         mObjects.put(objectp);
01317 
01318         updateActive(objectp);
01319 
01320         return objectp;
01321 }
01322 
01323 LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
01324 {
01325         LLViewerObject *old_instance = findObject(id);
01326         if (old_instance)
01327         {
01328                 cleanupReferences(old_instance);
01329                 old_instance->markDead();
01330                 
01331                 return createObject(pcode, regionp, id, old_instance->getLocalID(), LLHost());
01332         }
01333         return NULL;
01334 }
01335 
01336 S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const
01337 {
01338         LLViewerObject *objectp;
01339         S32 i;
01340         S32 num_refs = 0;
01341         for (i = 0; i < mObjects.count(); i++)
01342         {
01343                 objectp = mObjects[i];
01344                 if (objectp->mDrawable.notNull())
01345                 {
01346                         num_refs += objectp->mDrawable->findReferences(drawablep);
01347                 }
01348         }
01349         return num_refs;
01350 }
01351 
01352 
01353 void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip, U32 port)
01354 {
01355         LLMemType mt(LLMemType::MTYPE_OBJECT);
01356 #ifdef ORPHAN_SPAM
01357         llinfos << "Orphaning object " << childp->getID() << " with parent " << parent_id << llendl;
01358 #endif
01359 
01360         
01361         childp->mOrphaned = TRUE;
01362         if (childp->mDrawable.notNull())
01363         {
01364                 bool make_invisible = true;
01365                 LLViewerObject *parentp = (LLViewerObject *)childp->getParent();
01366                 if (parentp)
01367                 {
01368                         if (parentp->getRegion() != childp->getRegion())
01369                         {
01370                                 
01371                                 
01372                                 
01373                                 make_invisible = false;
01374                                 
01375                         }
01376                 }
01377 
01378                 if (make_invisible)
01379                 {
01380                         
01381                         childp->mDrawable->setState(LLDrawable::FORCE_INVISIBLE);
01382                 }
01383         }
01384 
01385         
01386         U64 parent_info = getIndex(parent_id, ip, port);
01387 
01388         if (-1 == mOrphanParents.find(parent_info))
01389         {
01390                 mOrphanParents.put(parent_info);
01391         }
01392 
01393         LLViewerObjectList::OrphanInfo oi(parent_info, childp->mID);
01394         if (-1 == mOrphanChildren.find(oi))
01395         {
01396                 mOrphanChildren.put(oi);
01397                 mNumOrphans++;
01398         }
01399 }
01400 
01401 
01402 void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
01403 {
01404         if (gNoRender)
01405         {
01406                 return;
01407         }
01408 
01409         if (objectp->isDead())
01410         {
01411                 llwarns << "Trying to find orphans for dead obj " << objectp->mID 
01412                         << ":" << objectp->getPCodeString() << llendl;
01413                 return;
01414         }
01415 
01416         
01417         
01418         
01419         if (0 == mOrphanParents.count())
01420         {
01421                 
01422                 return;
01423         }
01424         if (-1 == mOrphanParents.find(getIndex(objectp->mLocalID, ip, port)))
01425         {
01426                 
01427                 return;
01428         }
01429 
01430         S32 i;
01431         U64 parent_info = getIndex(objectp->mLocalID, ip, port);
01432         BOOL orphans_found = FALSE;
01433         
01434         for (i = 0; i < mOrphanChildren.count(); i++)
01435         {
01436                 if (mOrphanChildren[i].mParentInfo != parent_info)
01437                 {
01438                         continue;
01439                 }
01440                 LLViewerObject *childp = findObject(mOrphanChildren[i].mChildInfo);
01441                 if (childp)
01442                 {
01443                         if (childp == objectp)
01444                         {
01445                                 llwarns << objectp->mID << " has self as parent, skipping!" 
01446                                         << llendl;
01447                                 continue;
01448                         }
01449 
01450 #ifdef ORPHAN_SPAM
01451                         llinfos << "Reunited parent " << objectp->mID 
01452                                 << " with child " << childp->mID << llendl;
01453                         llinfos << "Glob: " << objectp->getPositionGlobal() << llendl;
01454                         llinfos << "Agent: " << objectp->getPositionAgent() << llendl;
01455                         addDebugBeacon(objectp->getPositionAgent(),"");
01456 #endif
01457             gPipeline.markMoved(objectp->mDrawable);                
01458             objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);
01459 
01460                         
01461                         childp->mOrphaned = FALSE;
01462                         if (childp->mDrawable.notNull())
01463                         {
01464                                 
01465                                 childp->mDrawable->setState(LLDrawable::CLEAR_INVISIBLE);
01466                                 childp->setDrawableParent(objectp->mDrawable); 
01467                         }
01468 
01469                         
01470                         childp->hideExtraDisplayItems( FALSE );
01471 
01472                         objectp->addChild(childp);
01473                         orphans_found = TRUE;
01474                 }
01475                 else
01476                 {
01477                         llinfos << "Missing orphan child, removing from list" << llendl;
01478                         mOrphanChildren.remove(i);
01479                         i--;
01480                 }
01481         }
01482 
01483         
01484         mOrphanParents.remove(mOrphanParents.find(parent_info));
01485 
01486         i = 0;
01487         while (i < mOrphanChildren.count())
01488         {
01489                 if (mOrphanChildren[i].mParentInfo == parent_info)
01490                 {
01491                         mOrphanChildren.remove(i);
01492                         mNumOrphans--;
01493                 }
01494                 else
01495                 {
01496                         i++;
01497                 }
01498         }
01499 
01500         if (orphans_found && objectp->isSelected())
01501         {
01502                 LLSelectNode* nodep = gSelectMgr->getSelection()->findNode(objectp);
01503                 if (nodep && !nodep->mIndividualSelection)
01504                 {
01505                         
01506                         gSelectMgr->deselectObjectAndFamily(objectp);
01507                         gSelectMgr->selectObjectAndFamily(objectp);
01508                 }
01509         }
01510 }
01511 
01513 
01514 LLViewerObjectList::OrphanInfo::OrphanInfo()
01515 {
01516 }
01517 
01518 LLViewerObjectList::OrphanInfo::OrphanInfo(const U64 parent_info, const LLUUID child_info)
01519         : mParentInfo(parent_info), mChildInfo(child_info)
01520 {
01521 }
01522 
01523 bool LLViewerObjectList::OrphanInfo::operator==(const OrphanInfo &rhs) const
01524 {
01525         return (mParentInfo == rhs.mParentInfo) && (mChildInfo == rhs.mChildInfo);
01526 }
01527 
01528 bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const
01529 {
01530         return !operator==(rhs);
01531 }
01532