PageRenderTime 150ms CodeModel.GetById 34ms app.highlight 103ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llviewerobjectlist.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2113 lines | 1572 code | 296 blank | 245 comment | 292 complexity | 66c5db19f29db09b3ae32cb652eb3ab7 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llviewerobjectlist.cpp
   3 * @brief Implementation of LLViewerObjectList class.
   4 *
   5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include "llviewerobjectlist.h"
  30
  31#include "message.h"
  32#include "timing.h"
  33#include "llfasttimer.h"
  34#include "llrender.h"
  35#include "llwindow.h"		// decBusyCount()
  36
  37#include "llviewercontrol.h"
  38#include "llface.h"
  39#include "llvoavatar.h"
  40#include "llviewerobject.h"
  41#include "llviewerwindow.h"
  42#include "llnetmap.h"
  43#include "llagent.h"
  44#include "llagentcamera.h"
  45#include "pipeline.h"
  46#include "llspatialpartition.h"
  47#include "lltooltip.h"
  48#include "llworld.h"
  49#include "llstring.h"
  50#include "llhudnametag.h"
  51#include "lldrawable.h"
  52#include "xform.h"
  53#include "llsky.h"
  54#include "llviewercamera.h"
  55#include "llselectmgr.h"
  56#include "llresmgr.h"
  57#include "llsdutil.h"
  58#include "llviewerregion.h"
  59#include "llviewerstats.h"
  60#include "llviewerstatsrecorder.h"
  61#include "llvovolume.h"
  62#include "llvoavatarself.h"
  63#include "lltoolmgr.h"
  64#include "lltoolpie.h"
  65#include "llkeyboard.h"
  66#include "u64.h"
  67#include "llviewertexturelist.h"
  68#include "lldatapacker.h"
  69#ifdef LL_STANDALONE
  70#include <zlib.h>
  71#else
  72#include "zlib/zlib.h"
  73#endif
  74#include "object_flags.h"
  75
  76#include "llappviewer.h"
  77
  78extern F32 gMinObjectDistance;
  79extern BOOL gAnimateTextures;
  80
  81void dialog_refresh_all();
  82
  83#define CULL_VIS
  84//#define ORPHAN_SPAM
  85//#define IGNORE_DEAD
  86
  87// Global lists of objects - should go away soon.
  88LLViewerObjectList gObjectList;
  89
  90extern LLPipeline	gPipeline;
  91
  92// Statics for object lookup tables.
  93U32						LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check.
  94std::map<U64, U32>			LLViewerObjectList::sIPAndPortToIndex;
  95std::map<U64, LLUUID>	LLViewerObjectList::sIndexAndLocalIDToUUID;
  96
  97LLViewerObjectList::LLViewerObjectList()
  98{
  99	mNumVisCulled = 0;
 100	mNumSizeCulled = 0;
 101	mCurLazyUpdateIndex = 0;
 102	mCurBin = 0;
 103	mNumDeadObjects = 0;
 104	mNumOrphans = 0;
 105	mNumNewObjects = 0;
 106	mWasPaused = FALSE;
 107	mNumDeadObjectUpdates = 0;
 108	mNumUnknownKills = 0;
 109	mNumUnknownUpdates = 0;
 110}
 111
 112LLViewerObjectList::~LLViewerObjectList()
 113{
 114	destroy();
 115}
 116
 117void LLViewerObjectList::destroy()
 118{
 119	killAllObjects();
 120
 121	resetObjectBeacons();
 122	mActiveObjects.clear();
 123	mDeadObjects.clear();
 124	mMapObjects.clear();
 125	mUUIDObjectMap.clear();
 126}
 127
 128
 129void LLViewerObjectList::getUUIDFromLocal(LLUUID &id,
 130										  const U32 local_id,
 131										  const U32 ip,
 132										  const U32 port)
 133{
 134	U64 ipport = (((U64)ip) << 32) | (U64)port;
 135
 136	U32 index = sIPAndPortToIndex[ipport];
 137
 138	if (!index)
 139	{
 140		index = sSimulatorMachineIndex++;
 141		sIPAndPortToIndex[ipport] = index;
 142	}
 143
 144	U64	indexid = (((U64)index) << 32) | (U64)local_id;
 145
 146	id = get_if_there(sIndexAndLocalIDToUUID, indexid, LLUUID::null);
 147}
 148
 149U64 LLViewerObjectList::getIndex(const U32 local_id,
 150								 const U32 ip,
 151								 const U32 port)
 152{
 153	U64 ipport = (((U64)ip) << 32) | (U64)port;
 154
 155	U32 index = sIPAndPortToIndex[ipport];
 156
 157	if (!index)
 158	{
 159		return 0;
 160	}
 161
 162	return (((U64)index) << 32) | (U64)local_id;
 163}
 164
 165BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp)
 166{
 167	if(objectp && objectp->getRegion())
 168	{
 169		U32 local_id = objectp->mLocalID;		
 170		U32 ip = objectp->getRegion()->getHost().getAddress();
 171		U32 port = objectp->getRegion()->getHost().getPort();
 172		U64 ipport = (((U64)ip) << 32) | (U64)port;
 173		U32 index = sIPAndPortToIndex[ipport];
 174		
 175		// llinfos << "Removing object from table, local ID " << local_id << ", ip " << ip << ":" << port << llendl;
 176		
 177		U64	indexid = (((U64)index) << 32) | (U64)local_id;
 178		
 179		std::map<U64, LLUUID>::iterator iter = sIndexAndLocalIDToUUID.find(indexid);
 180		if (iter == sIndexAndLocalIDToUUID.end())
 181		{
 182			return FALSE;
 183		}
 184		
 185		// Found existing entry
 186		if (iter->second == objectp->getID())
 187		{   // Full UUIDs match, so remove the entry
 188			sIndexAndLocalIDToUUID.erase(iter);
 189			return TRUE;
 190		}
 191		// UUIDs did not match - this would zap a valid entry, so don't erase it
 192		//llinfos << "Tried to erase entry where id in table (" 
 193		//		<< iter->second	<< ") did not match object " << object.getID() << llendl;
 194	}
 195	
 196	return FALSE ;
 197}
 198
 199void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id,
 200										  const U32 local_id,
 201										  const U32 ip,
 202										  const U32 port)
 203{
 204	U64 ipport = (((U64)ip) << 32) | (U64)port;
 205
 206	U32 index = sIPAndPortToIndex[ipport];
 207
 208	if (!index)
 209	{
 210		index = sSimulatorMachineIndex++;
 211		sIPAndPortToIndex[ipport] = index;
 212	}
 213
 214	U64	indexid = (((U64)index) << 32) | (U64)local_id;
 215
 216	sIndexAndLocalIDToUUID[indexid] = id;
 217	
 218	//llinfos << "Adding object to table, full ID " << id
 219	//	<< ", local ID " << local_id << ", ip " << ip << ":" << port << llendl;
 220}
 221
 222S32 gFullObjectUpdates = 0;
 223S32 gTerseObjectUpdates = 0;
 224
 225void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, 
 226										   void** user_data, 
 227										   U32 i, 
 228										   const EObjectUpdateType update_type, 
 229										   LLDataPacker* dpp, 
 230										   BOOL just_created)
 231{
 232	LLMemType mt(LLMemType::MTYPE_OBJECT_PROCESS_UPDATE_CORE);
 233	LLMessageSystem* msg = gMessageSystem;
 234
 235	// ignore returned flags
 236	objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
 237		
 238	if (objectp->isDead())
 239	{
 240		// The update failed
 241		return;
 242	}
 243
 244	updateActive(objectp);
 245
 246	if (just_created) 
 247	{
 248		gPipeline.addObject(objectp);
 249	}
 250
 251	// Also sets the approx. pixel area
 252	objectp->setPixelAreaAndAngle(gAgent);
 253
 254	// RN: this must be called after we have a drawable 
 255	// (from gPipeline.addObject)
 256	// so that the drawable parent is set properly
 257	findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
 258	
 259	// If we're just wandering around, don't create new objects selected.
 260	if (just_created 
 261		&& update_type != OUT_TERSE_IMPROVED 
 262		&& objectp->mCreateSelected)
 263	{
 264		if ( LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() )
 265		{
 266			// llinfos << "DEBUG selecting " << objectp->mID << " " 
 267			// << objectp->mLocalID << llendl;
 268			LLSelectMgr::getInstance()->selectObjectAndFamily(objectp);
 269			dialog_refresh_all();
 270		}
 271
 272		objectp->mCreateSelected = false;
 273		gViewerWindow->getWindow()->decBusyCount();
 274		gViewerWindow->setCursor( UI_CURSOR_ARROW );
 275	}
 276}
 277
 278static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects");
 279
 280void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
 281											 void **user_data,
 282											 const EObjectUpdateType update_type,
 283											 bool cached, bool compressed)
 284{
 285	LLMemType mt(LLMemType::MTYPE_OBJECT_PROCESS_UPDATE);
 286	LLFastTimer t(FTM_PROCESS_OBJECTS);	
 287	
 288	LLVector3d camera_global = gAgentCamera.getCameraPositionGlobal();
 289	LLViewerObject *objectp;
 290	S32			num_objects;
 291	U32			local_id;
 292	LLPCode		pcode = 0;
 293	LLUUID		fullid;
 294	S32			i;
 295
 296	// figure out which simulator these are from and get it's index
 297	// Coordinates in simulators are region-local
 298	// Until we get region-locality working on viewer we
 299	// have to transform to absolute coordinates.
 300	num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
 301
 302	// I don't think this case is ever hit.  TODO* Test this.
 303	if (!cached && !compressed && update_type != OUT_FULL)
 304	{
 305		//llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl;
 306		gTerseObjectUpdates += num_objects;
 307		S32 size;
 308		if (mesgsys->getReceiveCompressedSize())
 309		{
 310			size = mesgsys->getReceiveCompressedSize();
 311		}
 312		else
 313		{
 314			size = mesgsys->getReceiveSize();
 315		}
 316		//llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
 317	}
 318	else
 319	{
 320		S32 size;
 321		if (mesgsys->getReceiveCompressedSize())
 322		{
 323			size = mesgsys->getReceiveCompressedSize();
 324		}
 325		else
 326		{
 327			size = mesgsys->getReceiveSize();
 328		}
 329
 330		// llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
 331		gFullObjectUpdates += num_objects;
 332	}
 333
 334	U64 region_handle;
 335	mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
 336	LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
 337
 338	if (!regionp)
 339	{
 340		llwarns << "Object update from unknown region! " << region_handle << llendl;
 341		return;
 342	}
 343
 344	U8 compressed_dpbuffer[2048];
 345	LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
 346	LLDataPacker *cached_dpp = NULL;
 347
 348#if LL_RECORD_VIEWER_STATS
 349	LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(regionp);
 350#endif
 351
 352	for (i = 0; i < num_objects; i++)
 353	{
 354		// timer is unused?
 355		LLTimer update_timer;
 356		BOOL justCreated = FALSE;
 357
 358		if (cached)
 359		{
 360			U32 id;
 361			U32 crc;
 362			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
 363			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
 364		
 365			// Lookup data packer and add this id to cache miss lists if necessary.
 366			U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
 367			cached_dpp = regionp->getDP(id, crc, cache_miss_type);
 368			if (cached_dpp)
 369			{
 370				// Cache Hit.
 371				cached_dpp->reset();
 372				cached_dpp->unpackUUID(fullid, "ID");
 373				cached_dpp->unpackU32(local_id, "LocalID");
 374				cached_dpp->unpackU8(pcode, "PCode");
 375			}
 376			else
 377			{
 378				// Cache Miss.
 379				#if LL_RECORD_VIEWER_STATS
 380				LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type);
 381				#endif
 382
 383				continue; // no data packer, skip this object
 384			}
 385		}
 386		else if (compressed)
 387		{
 388			U8							compbuffer[2048];
 389			S32							uncompressed_length = 2048;
 390			S32							compressed_length;
 391			compressed_dp.reset();
 392
 393			U32 flags = 0;
 394			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
 395			{
 396				mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
 397			}
 398			
 399			// I don't think we ever use this flag from the server.  DK 2010/12/09
 400			if (flags & FLAGS_ZLIB_COMPRESSED)
 401			{
 402				//llinfos << "TEST: flags & FLAGS_ZLIB_COMPRESSED" << llendl;
 403				compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
 404				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i);
 405				uncompressed_length = 2048;
 406				uncompress(compressed_dpbuffer, (unsigned long *)&uncompressed_length,
 407						   compbuffer, compressed_length);
 408				compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
 409			}
 410			else
 411			{
 412				uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
 413				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i);
 414				compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
 415			}
 416
 417
 418			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
 419			{
 420				compressed_dp.unpackUUID(fullid, "ID");
 421				compressed_dp.unpackU32(local_id, "LocalID");
 422				compressed_dp.unpackU8(pcode, "PCode");
 423			}
 424			else
 425			{
 426				compressed_dp.unpackU32(local_id, "LocalID");
 427				getUUIDFromLocal(fullid,
 428								 local_id,
 429								 gMessageSystem->getSenderIP(),
 430								 gMessageSystem->getSenderPort());
 431				if (fullid.isNull())
 432				{
 433					// llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << llendl;
 434					mNumUnknownUpdates++;
 435				}
 436			}
 437		}
 438		else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only?
 439		{
 440			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
 441			getUUIDFromLocal(fullid,
 442							local_id,
 443							gMessageSystem->getSenderIP(),
 444							gMessageSystem->getSenderPort());
 445			if (fullid.isNull())
 446			{
 447				// llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl;
 448				mNumUnknownUpdates++;
 449			}
 450		}
 451		else // OUT_FULL only?
 452		{
 453			mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
 454			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
 455			// llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl;
 456		}
 457		objectp = findObject(fullid);
 458
 459		// This looks like it will break if the local_id of the object doesn't change
 460		// upon boundary crossing, but we check for region id matching later...
 461		// Reset object local id and region pointer if things have changed
 462		if (objectp && 
 463			((objectp->mLocalID != local_id) ||
 464			 (objectp->getRegion() != regionp)))
 465		{
 466			//if (objectp->getRegion())
 467			//{
 468			//	llinfos << "Local ID change: Removing object from table, local ID " << objectp->mLocalID 
 469			//			<< ", id from message " << local_id << ", from " 
 470			//			<< LLHost(objectp->getRegion()->getHost().getAddress(), objectp->getRegion()->getHost().getPort())
 471			//			<< ", full id " << fullid 
 472			//			<< ", objects id " << objectp->getID()
 473			//			<< ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion()
 474			//			<< llendl;
 475			//}
 476			removeFromLocalIDTable(objectp);
 477			setUUIDAndLocal(fullid,
 478							local_id,
 479							gMessageSystem->getSenderIP(),
 480							gMessageSystem->getSenderPort());
 481			
 482			if (objectp->mLocalID != local_id)
 483			{	// Update local ID in object with the one sent from the region
 484				objectp->mLocalID = local_id;
 485			}
 486			
 487			if (objectp->getRegion() != regionp)
 488			{	// Object changed region, so update it
 489				objectp->updateRegion(regionp); // for LLVOAvatar
 490			}
 491		}
 492
 493		if (!objectp)
 494		{
 495			if (compressed)
 496			{
 497				if (update_type == OUT_TERSE_IMPROVED)
 498				{
 499					// llinfos << "terse update for an unknown object (compressed):" << fullid << llendl;
 500					#if LL_RECORD_VIEWER_STATS
 501					LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
 502					#endif
 503					continue;
 504				}
 505			}
 506			else if (cached) // Cache hit only?
 507			{
 508			}
 509			else
 510			{
 511				if (update_type != OUT_FULL)
 512				{
 513					//llinfos << "terse update for an unknown object:" << fullid << llendl;
 514					#if LL_RECORD_VIEWER_STATS
 515					LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
 516					#endif
 517					continue;
 518				}
 519
 520				mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i);
 521			}
 522#ifdef IGNORE_DEAD
 523			if (mDeadObjects.find(fullid) != mDeadObjects.end())
 524			{
 525				mNumDeadObjectUpdates++;
 526				//llinfos << "update for a dead object:" << fullid << llendl;
 527				#if LL_RECORD_VIEWER_STATS
 528				LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
 529				#endif
 530				continue;
 531			}
 532#endif
 533
 534			objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());
 535			if (!objectp)
 536			{
 537				llinfos << "createObject failure for object: " << fullid << llendl;
 538				#if LL_RECORD_VIEWER_STATS
 539				LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
 540				#endif
 541				continue;
 542			}
 543			justCreated = TRUE;
 544			mNumNewObjects++;
 545		}
 546
 547
 548		if (objectp->isDead())
 549		{
 550			llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
 551		}
 552
 553		bool bCached = false;
 554		if (compressed)
 555		{
 556			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
 557			{
 558				objectp->mLocalID = local_id;
 559			}
 560			processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
 561			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
 562			{
 563				bCached = true;
 564				#if LL_RECORD_VIEWER_STATS
 565				LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
 566				LLViewerStatsRecorder::instance()->recordCacheFullUpdate(local_id, update_type, result, objectp);
 567				#else
 568				objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
 569				#endif
 570			}
 571		}
 572		else if (cached) // Cache hit only?
 573		{
 574			objectp->mLocalID = local_id;
 575			processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated);
 576		}
 577		else
 578		{
 579			if (update_type == OUT_FULL)
 580			{
 581				objectp->mLocalID = local_id;
 582			}
 583			processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);
 584		}
 585		#if LL_RECORD_VIEWER_STATS
 586		LLViewerStatsRecorder::instance()->recordObjectUpdateEvent(local_id, update_type, objectp);
 587		#endif
 588		objectp->setLastUpdateType(update_type);
 589		objectp->setLastUpdateCached(bCached);
 590	}
 591
 592#if LL_RECORD_VIEWER_STATS
 593	LLViewerStatsRecorder::instance()->endObjectUpdateEvents();
 594#endif
 595
 596	LLVOAvatar::cullAvatarsByPixelArea();
 597}
 598
 599void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys,
 600											 void **user_data,
 601											 const EObjectUpdateType update_type)
 602{
 603	processObjectUpdate(mesgsys, user_data, update_type, false, true);
 604}
 605
 606void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
 607											 void **user_data,
 608											 const EObjectUpdateType update_type)
 609{
 610	processObjectUpdate(mesgsys, user_data, update_type, true, false);
 611}	
 612
 613void LLViewerObjectList::dirtyAllObjectInventory()
 614{
 615	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
 616	{
 617		(*iter)->dirtyInventory();
 618	}
 619}
 620
 621void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 622{
 623	S32 i;
 624	S32 num_objects = 0;
 625	LLViewerObject *objectp;
 626
 627	S32 num_updates, max_value;
 628	if (NUM_BINS - 1 == mCurBin)
 629	{
 630		num_updates = (S32) mObjects.size() - mCurLazyUpdateIndex;
 631		max_value = (S32) mObjects.size();
 632		gTextureList.setUpdateStats(TRUE);
 633	}
 634	else
 635	{
 636		num_updates = ((S32) mObjects.size() / NUM_BINS) + 1;
 637		max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates);
 638	}
 639
 640
 641	// Slam priorities for textures that we care about (hovered, selected, and focused)
 642	// Hovered
 643	// Assumes only one level deep of parenting
 644	LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
 645	if (nodep)
 646	{
 647		objectp = nodep->getObject();
 648		if (objectp)
 649		{
 650			objectp->boostTexturePriority();
 651		}
 652	}
 653
 654	// Focused
 655	objectp = gAgentCamera.getFocusObject();
 656	if (objectp)
 657	{
 658		objectp->boostTexturePriority();
 659	}
 660
 661	// Selected
 662	struct f : public LLSelectedObjectFunctor
 663	{
 664		virtual bool apply(LLViewerObject* objectp)
 665		{
 666			objectp->boostTexturePriority();
 667			return true;
 668		}
 669	} func;
 670	LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);
 671
 672	// Iterate through some of the objects and lazy update their texture priorities
 673	for (i = mCurLazyUpdateIndex; i < max_value; i++)
 674	{
 675		objectp = mObjects[i];
 676		if (!objectp->isDead())
 677		{
 678			num_objects++;
 679
 680			//  Update distance & gpw 
 681			objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
 682			objectp->updateTextures();	// Update the image levels of textures for this object.
 683		}
 684	}
 685
 686	mCurLazyUpdateIndex = max_value;
 687	if (mCurLazyUpdateIndex == mObjects.size())
 688	{
 689		mCurLazyUpdateIndex = 0;
 690	}
 691
 692	mCurBin = (mCurBin + 1) % NUM_BINS;
 693
 694	LLVOAvatar::cullAvatarsByPixelArea();
 695}
 696
 697class LLObjectCostResponder : public LLCurl::Responder
 698{
 699public:
 700	LLObjectCostResponder(const LLSD& object_ids)
 701		: mObjectIDs(object_ids)
 702	{
 703	}
 704
 705	// Clear's the global object list's pending
 706	// request list for all objects requested
 707	void clear_object_list_pending_requests()
 708	{
 709		// TODO*: No more hard coding
 710		for (
 711			LLSD::array_iterator iter = mObjectIDs.beginArray();
 712			iter != mObjectIDs.endArray();
 713			++iter)
 714		{
 715			gObjectList.onObjectCostFetchFailure(iter->asUUID());
 716		}
 717	}
 718
 719	void error(U32 statusNum, const std::string& reason)
 720	{
 721		llwarns
 722			<< "Transport error requesting object cost "
 723			<< "HTTP status: " << statusNum << ", reason: "
 724			<< reason << "." << llendl;
 725
 726		// TODO*: Error message to user
 727		// For now just clear the request from the pending list
 728		clear_object_list_pending_requests();
 729	}
 730
 731	void result(const LLSD& content)
 732	{
 733		if ( !content.isMap() || content.has("error") )
 734		{
 735			// Improper response or the request had an error,
 736			// show an error to the user?
 737			llwarns
 738				<< "Application level error when fetching object "
 739				<< "cost.  Message: " << content["error"]["message"].asString()
 740				<< ", identifier: " << content["error"]["identifier"].asString()
 741				<< llendl;
 742
 743			// TODO*: Adaptively adjust request size if the
 744			// service says we've requested too many and retry
 745
 746			// TODO*: Error message if not retrying
 747			clear_object_list_pending_requests();
 748			return;
 749		}
 750
 751		// Success, grab the resource cost and linked set costs
 752		// for an object if one was returned
 753		for (
 754			LLSD::array_iterator iter = mObjectIDs.beginArray();
 755			iter != mObjectIDs.endArray();
 756			++iter)
 757		{
 758			LLUUID object_id = iter->asUUID();
 759
 760			// Check to see if the request contains data for the object
 761			if ( content.has(iter->asString()) )
 762			{
 763				F32 link_cost =
 764					content[iter->asString()]["linked_set_resource_cost"].asReal();
 765				F32 object_cost =
 766					content[iter->asString()]["resource_cost"].asReal();
 767
 768				F32 physics_cost = content[iter->asString()]["physics_cost"].asReal();
 769				F32 link_physics_cost = content[iter->asString()]["linked_set_physics_cost"].asReal();
 770
 771				gObjectList.updateObjectCost(object_id, object_cost, link_cost, physics_cost, link_physics_cost);
 772			}
 773			else
 774			{
 775				// TODO*: Give user feedback about the missing data?
 776				gObjectList.onObjectCostFetchFailure(object_id);
 777			}
 778		}
 779	}
 780
 781private:
 782	LLSD mObjectIDs;
 783};
 784
 785
 786class LLPhysicsFlagsResponder : public LLCurl::Responder
 787{
 788public:
 789	LLPhysicsFlagsResponder(const LLSD& object_ids)
 790		: mObjectIDs(object_ids)
 791	{
 792	}
 793
 794	// Clear's the global object list's pending
 795	// request list for all objects requested
 796	void clear_object_list_pending_requests()
 797	{
 798		// TODO*: No more hard coding
 799		for (
 800			LLSD::array_iterator iter = mObjectIDs.beginArray();
 801			iter != mObjectIDs.endArray();
 802			++iter)
 803		{
 804			gObjectList.onPhysicsFlagsFetchFailure(iter->asUUID());
 805		}
 806	}
 807
 808	void error(U32 statusNum, const std::string& reason)
 809	{
 810		llwarns
 811			<< "Transport error requesting object physics flags "
 812			<< "HTTP status: " << statusNum << ", reason: "
 813			<< reason << "." << llendl;
 814
 815		// TODO*: Error message to user
 816		// For now just clear the request from the pending list
 817		clear_object_list_pending_requests();
 818	}
 819
 820	void result(const LLSD& content)
 821	{
 822		if ( !content.isMap() || content.has("error") )
 823		{
 824			// Improper response or the request had an error,
 825			// show an error to the user?
 826			llwarns
 827				<< "Application level error when fetching object "
 828				<< "physics flags.  Message: " << content["error"]["message"].asString()
 829				<< ", identifier: " << content["error"]["identifier"].asString()
 830				<< llendl;
 831
 832			// TODO*: Adaptively adjust request size if the
 833			// service says we've requested too many and retry
 834
 835			// TODO*: Error message if not retrying
 836			clear_object_list_pending_requests();
 837			return;
 838		}
 839
 840		// Success, grab the resource cost and linked set costs
 841		// for an object if one was returned
 842		for (
 843			LLSD::array_iterator iter = mObjectIDs.beginArray();
 844			iter != mObjectIDs.endArray();
 845			++iter)
 846		{
 847			LLUUID object_id = iter->asUUID();
 848
 849			// Check to see if the request contains data for the object
 850			if ( content.has(iter->asString()) )
 851			{
 852				const LLSD& data = content[iter->asString()];
 853
 854				S32 shape_type = data["PhysicsShapeType"].asInteger();
 855
 856				gObjectList.updatePhysicsShapeType(object_id, shape_type);
 857
 858				if (data.has("Density"))
 859				{
 860					F32 density = data["Density"].asReal();
 861					F32 friction = data["Friction"].asReal();
 862					F32 restitution = data["Restitution"].asReal();
 863					F32 gravity_multiplier = data["GravityMultiplier"].asReal();
 864					
 865					gObjectList.updatePhysicsProperties(object_id, 
 866						density, friction, restitution, gravity_multiplier);
 867				}
 868			}
 869			else
 870			{
 871				// TODO*: Give user feedback about the missing data?
 872				gObjectList.onPhysicsFlagsFetchFailure(object_id);
 873			}
 874		}
 875	}
 876
 877private:
 878	LLSD mObjectIDs;
 879};
 880
 881void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
 882{
 883	LLMemType mt(LLMemType::MTYPE_OBJECT);
 884
 885	// Update globals
 886	LLViewerObject::setVelocityInterpolate( gSavedSettings.getBOOL("VelocityInterpolate") );
 887	LLViewerObject::setPingInterpolate( gSavedSettings.getBOOL("PingInterpolate") );
 888	
 889	F32 interp_time = gSavedSettings.getF32("InterpolationTime");
 890	F32 phase_out_time = gSavedSettings.getF32("InterpolationPhaseOut");
 891	if (interp_time < 0.0 || 
 892		phase_out_time < 0.0 ||
 893		phase_out_time > interp_time)
 894	{
 895		llwarns << "Invalid values for InterpolationTime or InterpolationPhaseOut, resetting to defaults" << llendl;
 896		interp_time = 3.0f;
 897		phase_out_time = 1.0f;
 898	}
 899	LLViewerObject::setPhaseOutUpdateInterpolationTime( interp_time );
 900	LLViewerObject::setMaxUpdateInterpolationTime( phase_out_time );
 901
 902	gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
 903
 904	// update global timer
 905	F32 last_time = gFrameTimeSeconds;
 906	U64 time = totalTime();				 // this will become the new gFrameTime when the update is done
 907	// Time _can_ go backwards, for example if the user changes the system clock.
 908	// It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here.
 909//	llassert(time > gFrameTime);
 910	F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC;
 911	gFrameTime	= time;
 912	F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC;
 913	gFrameTimeSeconds = (F32)time_since_start;
 914
 915	gFrameIntervalSeconds = gFrameTimeSeconds - last_time;
 916	if (gFrameIntervalSeconds < 0.f)
 917	{
 918		gFrameIntervalSeconds = 0.f;
 919	}
 920
 921	//clear avatar LOD change counter
 922	LLVOAvatar::sNumLODChangesThisFrame = 0;
 923
 924	const F64 frame_time = LLFrameTimer::getElapsedSeconds();
 925	
 926	std::vector<LLViewerObject*> kill_list;
 927	S32 num_active_objects = 0;
 928	LLViewerObject *objectp = NULL;	
 929	
 930	// Make a copy of the list in case something in idleUpdate() messes with it
 931	std::vector<LLViewerObject*> idle_list;
 932	
 933	static LLFastTimer::DeclareTimer idle_copy("Idle Copy");
 934
 935	{
 936		LLFastTimer t(idle_copy);
 937		idle_list.reserve( mActiveObjects.size() );
 938
 939 		for (std::set<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin();
 940			active_iter != mActiveObjects.end(); active_iter++)
 941		{
 942			objectp = *active_iter;
 943			if (objectp)
 944			{
 945				idle_list.push_back( objectp );
 946			}
 947			else
 948			{	// There shouldn't be any NULL pointers in the list, but they have caused
 949				// crashes before.  This may be idleUpdate() messing with the list.
 950				llwarns << "LLViewerObjectList::update has a NULL objectp" << llendl;
 951			}
 952		}
 953	}
 954
 955	if (gSavedSettings.getBOOL("FreezeTime"))
 956	{
 957		for (std::vector<LLViewerObject*>::iterator iter = idle_list.begin();
 958			iter != idle_list.end(); iter++)
 959		{
 960			objectp = *iter;
 961			if (objectp->isAvatar())
 962			{
 963				objectp->idleUpdate(agent, world, frame_time);
 964			}
 965		}
 966	}
 967	else
 968	{
 969		for (std::vector<LLViewerObject*>::iterator idle_iter = idle_list.begin();
 970			idle_iter != idle_list.end(); idle_iter++)
 971		{
 972			objectp = *idle_iter;
 973			if (!objectp->idleUpdate(agent, world, frame_time))
 974			{
 975				//  If Idle Update returns false, kill object!
 976				kill_list.push_back(objectp);
 977			}
 978			else
 979			{
 980				num_active_objects++;
 981			}
 982		}
 983		for (std::vector<LLViewerObject*>::iterator kill_iter = kill_list.begin();
 984			kill_iter != kill_list.end(); kill_iter++)
 985		{
 986			objectp = *kill_iter;
 987			killObject(objectp);
 988		}
 989	}
 990
 991	fetchObjectCosts();
 992	fetchPhysicsFlags();
 993
 994	mNumSizeCulled = 0;
 995	mNumVisCulled = 0;
 996
 997	// update max computed render cost
 998	LLVOVolume::updateRenderComplexity();
 999
1000	// compute all sorts of time-based stats
1001	// don't factor frames that were paused into the stats
1002	if (! mWasPaused)
1003	{
1004		LLViewerStats::getInstance()->updateFrameStats(time_diff);
1005	}
1006
1007	/*
1008	// Debugging code for viewing orphans, and orphaned parents
1009	LLUUID id;
1010	for (i = 0; i < mOrphanParents.count(); i++)
1011	{
1012		id = sIndexAndLocalIDToUUID[mOrphanParents[i]];
1013		LLViewerObject *objectp = findObject(id);
1014		if (objectp)
1015		{
1016			std::string id_str;
1017			objectp->mID.toString(id_str);
1018			std::string tmpstr = std::string("Par:	") + id_str;
1019			addDebugBeacon(objectp->getPositionAgent(),
1020							tmpstr,
1021							LLColor4(1.f,0.f,0.f,1.f),
1022							LLColor4(1.f,1.f,1.f,1.f));
1023		}
1024	}
1025
1026	LLColor4 text_color;
1027	for (i = 0; i < mOrphanChildren.count(); i++)
1028	{
1029		OrphanInfo oi = mOrphanChildren[i];
1030		LLViewerObject *objectp = findObject(oi.mChildInfo);
1031		if (objectp)
1032		{
1033			std::string id_str;
1034			objectp->mID.toString(id_str);
1035			std::string tmpstr;
1036			if (objectp->getParent())
1037			{
1038				tmpstr = std::string("ChP:	") + id_str;
1039				text_color = LLColor4(0.f, 1.f, 0.f, 1.f);
1040			}
1041			else
1042			{
1043				tmpstr = std::string("ChNoP:	") + id_str;
1044				text_color = LLColor4(1.f, 0.f, 0.f, 1.f);
1045			}
1046			id = sIndexAndLocalIDToUUID[oi.mParentInfo];
1047			addDebugBeacon(objectp->getPositionAgent() + LLVector3(0.f, 0.f, -0.25f),
1048							tmpstr,
1049							LLColor4(0.25f,0.25f,0.25f,1.f),
1050							text_color);
1051		}
1052		i++;
1053	}
1054	*/
1055
1056	LLViewerStats::getInstance()->mNumObjectsStat.addValue((S32) mObjects.size());
1057	LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(num_active_objects);
1058	LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled);
1059	LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled);
1060}
1061
1062void LLViewerObjectList::fetchObjectCosts()
1063{
1064	// issue http request for stale object physics costs
1065	if (!mStaleObjectCost.empty())
1066	{
1067		LLViewerRegion* regionp = gAgent.getRegion();
1068
1069		if (regionp)
1070		{
1071			std::string url = regionp->getCapability("GetObjectCost");
1072
1073			if (!url.empty())
1074			{
1075				LLSD id_list;
1076				U32 object_index = 0;
1077
1078				U32 count = 0;
1079
1080				for (
1081					std::set<LLUUID>::iterator iter = mStaleObjectCost.begin();
1082					iter != mStaleObjectCost.end();
1083					)
1084				{
1085					// Check to see if a request for this object
1086					// has already been made.
1087					if ( mPendingObjectCost.find(*iter) ==
1088						 mPendingObjectCost.end() )
1089					{
1090						mPendingObjectCost.insert(*iter);
1091						id_list[object_index++] = *iter;
1092					}
1093
1094					mStaleObjectCost.erase(iter++);
1095
1096					if (count++ >= 450)
1097					{
1098						break;
1099					}
1100				}
1101									
1102				if ( id_list.size() > 0 )
1103				{
1104					LLSD post_data = LLSD::emptyMap();
1105
1106					post_data["object_ids"] = id_list;
1107					LLHTTPClient::post(
1108						url,
1109						post_data,
1110						new LLObjectCostResponder(id_list));
1111				}
1112			}
1113			else
1114			{
1115				mStaleObjectCost.clear();
1116				mPendingObjectCost.clear();
1117			}
1118		}
1119	}
1120}
1121
1122void LLViewerObjectList::fetchPhysicsFlags()
1123{
1124	// issue http request for stale object physics flags
1125	if (!mStalePhysicsFlags.empty())
1126	{
1127		LLViewerRegion* regionp = gAgent.getRegion();
1128
1129		if (regionp)
1130		{
1131			std::string url = regionp->getCapability("GetObjectPhysicsData");
1132
1133			if (!url.empty())
1134			{
1135				LLSD id_list;
1136				U32 object_index = 0;
1137
1138				for (
1139					std::set<LLUUID>::iterator iter = mStalePhysicsFlags.begin();
1140					iter != mStalePhysicsFlags.end();
1141					++iter)
1142				{
1143					// Check to see if a request for this object
1144					// has already been made.
1145					if ( mPendingPhysicsFlags.find(*iter) ==
1146						 mPendingPhysicsFlags.end() )
1147					{
1148						mPendingPhysicsFlags.insert(*iter);
1149						id_list[object_index++] = *iter;
1150					}
1151				}
1152
1153				// id_list should now contain all
1154				// requests in mStalePhysicsFlags before, so clear
1155				// it now
1156				mStalePhysicsFlags.clear();
1157
1158				if ( id_list.size() > 0 )
1159				{
1160					LLSD post_data = LLSD::emptyMap();
1161
1162					post_data["object_ids"] = id_list;
1163					LLHTTPClient::post(
1164						url,
1165						post_data,
1166						new LLPhysicsFlagsResponder(id_list));
1167				}
1168			}
1169			else
1170			{
1171				mStalePhysicsFlags.clear();
1172				mPendingPhysicsFlags.clear();
1173			}
1174		}
1175	}
1176}
1177
1178
1179void LLViewerObjectList::clearDebugText()
1180{
1181	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
1182	{
1183		(*iter)->setDebugText("");
1184	}
1185}
1186
1187
1188void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
1189{
1190	LLMemType mt(LLMemType::MTYPE_OBJECT);
1191	if (mDeadObjects.find(objectp->mID) != mDeadObjects.end())
1192	{
1193		llinfos << "Object " << objectp->mID << " already on dead list!" << llendl;	
1194	}
1195	else
1196	{
1197		mDeadObjects.insert(objectp->mID);
1198	}
1199
1200	// Cleanup any references we have to this object
1201	// Remove from object map so noone can look it up.
1202
1203	mUUIDObjectMap.erase(objectp->mID);
1204	
1205	//if (objectp->getRegion())
1206	//{
1207	//	llinfos << "cleanupReferences removing object from table, local ID " << objectp->mLocalID << ", ip " 
1208	//				<< objectp->getRegion()->getHost().getAddress() << ":" 
1209	//				<< objectp->getRegion()->getHost().getPort() << llendl;
1210	//}	
1211	
1212	removeFromLocalIDTable(objectp);
1213
1214	if (objectp->onActiveList())
1215	{
1216		//llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << llendl;
1217		objectp->setOnActiveList(FALSE);
1218		mActiveObjects.erase(objectp);
1219	}
1220
1221	if (objectp->isOnMap())
1222	{
1223		removeFromMap(objectp);
1224	}
1225
1226	// Don't clean up mObject references, these will be cleaned up more efficiently later!
1227	// Also, not cleaned up
1228	removeDrawable(objectp->mDrawable);
1229
1230	mNumDeadObjects++;
1231}
1232
1233static LLFastTimer::DeclareTimer FTM_REMOVE_DRAWABLE("Remove Drawable");
1234
1235void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
1236{
1237	LLFastTimer t(FTM_REMOVE_DRAWABLE);
1238
1239	if (!drawablep)
1240	{
1241		return;
1242	}
1243
1244	for (S32 i = 0; i < drawablep->getNumFaces(); i++)
1245	{
1246		LLFace* facep = drawablep->getFace(i) ;
1247		if(facep)
1248		{
1249			   LLViewerObject* objectp = facep->getViewerObject();
1250			   if(objectp)
1251			   {
1252					   mSelectPickList.erase(objectp);
1253			   }
1254		}
1255	}
1256}
1257
1258BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
1259{
1260	// Don't ever kill gAgentAvatarp, just force it to the agent's region
1261	// unless region is NULL which is assumed to mean you are logging out.
1262	if ((objectp == gAgentAvatarp) && gAgent.getRegion())
1263	{
1264		objectp->setRegion(gAgent.getRegion());
1265		return FALSE;
1266	}
1267
1268	// When we're killing objects, all we do is mark them as dead.
1269	// We clean up the dead objects later.
1270
1271	if (objectp)
1272	{
1273		if (objectp->isDead())
1274		{
1275			// This object is already dead.  Don't need to do more.
1276			return TRUE;
1277		}
1278		else
1279		{
1280			objectp->markDead();
1281		}
1282
1283		return TRUE;
1284	}
1285
1286	return FALSE;
1287}
1288
1289void LLViewerObjectList::killObjects(LLViewerRegion *regionp)
1290{
1291	LLViewerObject *objectp;
1292
1293	
1294	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
1295	{
1296		objectp = *iter;
1297		
1298		if (objectp->mRegionp == regionp)
1299		{
1300			killObject(objectp);
1301		}
1302	}
1303
1304	// Have to clean right away because the region is becoming invalid.
1305	cleanDeadObjects(FALSE);
1306}
1307
1308void LLViewerObjectList::killAllObjects()
1309{
1310	// Used only on global destruction.
1311	LLViewerObject *objectp;
1312
1313	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
1314	{
1315		objectp = *iter;
1316		killObject(objectp);
1317		// Object must be dead, or it's the LLVOAvatarSelf which never dies.
1318		llassert((objectp == gAgentAvatarp) || objectp->isDead());
1319	}
1320
1321	cleanDeadObjects(FALSE);
1322
1323	if(!mObjects.empty())
1324	{
1325		llwarns << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.size() << llendl;
1326		mObjects.clear();
1327	}
1328
1329	if (!mActiveObjects.empty())
1330	{
1331		llwarns << "Some objects still on active object list!" << llendl;
1332		mActiveObjects.clear();
1333	}
1334
1335	if (!mMapObjects.empty())
1336	{
1337		llwarns << "Some objects still on map object list!" << llendl;
1338		mMapObjects.clear();
1339	}
1340}
1341
1342void LLViewerObjectList::cleanDeadObjects(BOOL use_timer)
1343{
1344	if (!mNumDeadObjects)
1345	{
1346		// No dead objects, don't need to scan object list.
1347		return;
1348	}
1349
1350	S32 num_removed = 0;
1351	LLViewerObject *objectp;
1352	
1353	vobj_list_t::reverse_iterator target = mObjects.rbegin();
1354
1355	vobj_list_t::iterator iter = mObjects.begin();
1356	for ( ; iter != mObjects.end(); )
1357	{
1358		// Scan for all of the dead objects and put them all on the end of the list with no ref count ops
1359		objectp = *iter;
1360		if (objectp == NULL)
1361		{ //we caught up to the dead tail
1362			break;
1363		}
1364
1365		if (objectp->isDead())
1366		{
1367			LLPointer<LLViewerObject>::swap(*iter, *target);
1368			*target = NULL;
1369			++target;
1370			num_removed++;
1371
1372			if (num_removed == mNumDeadObjects || iter->isNull())
1373			{
1374				// We've cleaned up all of the dead objects or caught up to the dead tail
1375				break;
1376			}
1377		}
1378		else
1379		{
1380			++iter;
1381		}
1382	}
1383
1384	llassert(num_removed == mNumDeadObjects);
1385
1386	//erase as a block
1387	mObjects.erase(mObjects.begin()+(mObjects.size()-mNumDeadObjects), mObjects.end());
1388
1389	// We've cleaned the global object list, now let's do some paranoia testing on objects
1390	// before blowing away the dead list.
1391	mDeadObjects.clear();
1392	mNumDeadObjects = 0;
1393}
1394
1395void LLViewerObjectList::updateActive(LLViewerObject *objectp)
1396{
1397	LLMemType mt(LLMemType::MTYPE_OBJECT);
1398	if (objectp->isDead())
1399	{
1400		return; // We don't update dead objects!
1401	}
1402
1403	BOOL active = objectp->isActive();
1404	if (active != objectp->onActiveList())
1405	{
1406		if (active)
1407		{
1408			//llinfos << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << llendl;
1409			mActiveObjects.insert(objectp);
1410			objectp->setOnActiveList(TRUE);
1411		}
1412		else
1413		{
1414			//llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << llendl;
1415			mActiveObjects.erase(objectp);
1416			objectp->setOnActiveList(FALSE);
1417		}
1418	}
1419}
1420
1421void LLViewerObjectList::updateObjectCost(LLViewerObject* object)
1422{
1423	if (!object->isRoot())
1424	{ //always fetch cost for the parent when fetching cost for children
1425		mStaleObjectCost.insert(((LLViewerObject*)object->getParent())->getID());
1426	}
1427	mStaleObjectCost.insert(object->getID());
1428}
1429
1430void LLViewerObjectList::updateObjectCost(const LLUUID& object_id, F32 object_cost, F32 link_cost, F32 physics_cost, F32 link_physics_cost)
1431{
1432	mPendingObjectCost.erase(object_id);
1433
1434	LLViewerObject* object = findObject(object_id);
1435	if (object)
1436	{
1437		object->setObjectCost(object_cost);
1438		object->setLinksetCost(link_cost);
1439		object->setPhysicsCost(physics_cost);
1440		object->setLinksetPhysicsCost(link_physics_cost);
1441	}
1442}
1443
1444void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id)
1445{
1446	//llwarns << "Failed to fetch object cost for object: " << object_id << llendl;
1447	mPendingObjectCost.erase(object_id);
1448}
1449
1450void LLViewerObjectList::updatePhysicsFlags(const LLViewerObject* object)
1451{
1452	mStalePhysicsFlags.insert(object->getID());
1453}
1454
1455void LLViewerObjectList::updatePhysicsShapeType(const LLUUID& object_id, S32 type)
1456{
1457	mPendingPhysicsFlags.erase(object_id);
1458	LLViewerObject* object = findObject(object_id);
1459	if (object)
1460	{
1461		object->setPhysicsShapeType(type);
1462	}
1463}
1464
1465void LLViewerObjectList::updatePhysicsProperties(const LLUUID& object_id, 
1466												F32 density,
1467												F32 friction,
1468												F32 restitution,
1469												F32 gravity_multiplier)
1470{
1471	mPendingPhysicsFlags.erase(object_id);
1472
1473	LLViewerObject* object = findObject(object_id);
1474	if (object)
1475	{
1476		object->setPhysicsDensity(density);
1477		object->setPhysicsFriction(friction);
1478		object->setPhysicsGravity(gravity_multiplier);
1479		object->setPhysicsRestitution(restitution);
1480	}
1481}
1482
1483void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id)
1484{
1485	//llwarns << "Failed to fetch physics flags for object: " << object_id << llendl;
1486	mPendingPhysicsFlags.erase(object_id);
1487}
1488
1489void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
1490{
1491	// This is called when we shift our origin when we cross region boundaries...
1492	// We need to update many object caches, I'll document this more as I dig through the code
1493	// cleaning things out...
1494
1495	if (0 == offset.magVecSquared())
1496	{
1497		return;
1498	}
1499
1500	LLViewerObject *objectp;
1501	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
1502	{
1503		objectp = *iter;
1504		// There could be dead objects on the object list, so don't update stuff if the object is dead.
1505		if (!objectp->isDead())
1506		{
1507			objectp->updatePositionCaches();
1508
1509			if (objectp->mDrawable.notNull() && !objectp->mDrawable->isDead())
1510			{
1511				gPipeline.markShift(objectp->mDrawable);
1512			}
1513		}
1514	}
1515
1516	gPipeline.shiftObjects(offset);
1517	LLWorld::getInstance()->shiftRegions(offset);
1518}
1519
1520void LLViewerObjectList::repartitionObjects()
1521{
1522	for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
1523	{
1524		LLViewerObject* objectp = *iter;
1525		if (!objectp->isDead())
1526		{
1527			LLDrawable* drawable = objectp->mDrawable;
1528			if (drawable && !drawable->isDead())
1529			{
1530				drawable->updateBinRadius();
1531				drawable->updateSpatialExtents();
1532				drawable->movePartition();
1533			}
1534		}
1535	}
1536}
1537
1538//debug code
1539bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp) 
1540{
1541	for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
1542	{
1543		LLViewerObject* objectp = *iter;
1544
1545		if(objectp->isDead() || objectp->getRegion() == regionp)
1546		{
1547			return true ;
1548		}
1549	}
1550
1551	return false ;
1552}
1553
1554//make sure the region is cleaned up.
1555void LLViewerObjectList::clearAllMapObjectsInRegion(LLViewerRegion* regionp) 
1556{
1557	std::set<LLViewerObject*> dead_object_list ;
1558	std::set<LLViewerObject*> region_object_list ;
1559	for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
1560	{
1561		LLViewerObject* objectp = *iter;
1562
1563		if(objectp->isDead())
1564		{
1565			dead_object_list.insert(objectp) ;			
1566		}
1567		else if(objectp->getRegion() == regionp)
1568		{
1569			region_object_list.insert(objectp) ;
1570		}
1571	}
1572
1573	if(dead_object_list.size() > 0)
1574	{
1575		llwarns << "There are " << dead_object_list.size() << " dead objects on the map!" << llendl ;
1576
1577		for(std::set<LLViewerObject*>::iterator iter = dead_object_list.begin(); iter != dead_object_list.end(); ++iter)
1578		{
1579			cleanupReferences(*iter) ;
1580		}
1581	}
1582	if(region_object_list.size() > 0)
1583	{
1584		llwarns << "There are " << region_object_list.size() << " objects not removed from the deleted region!" << llendl ;
1585
1586		for(std::set<LLViewerObject*>::iterator iter = region_object_list.begin(); iter != region_object_list.end(); ++iter)
1587		{
1588			(*iter)->markDead() ;
1589		}
1590	}
1591}
1592
1593
1594void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
1595{
1596	LLColor4 above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" );
1597	LLColor4 below_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnBelowWater" );
1598	LLColor4 you_own_above_water_color = 
1599						LLUIColorTable::instance().getColor( "NetMapYouOwnAboveWater" );
1600	LLColor4 you_own_below_water_color = 
1601						LLUIColorTable::instance().getColor( "NetMapYouOwnBelowWater" );
1602	LLColor4 group_own_above_water_color = 
1603						LLUIColorTable::instance().getColor( "NetMapGroupOwnAboveWater" );
1604	LLColor4 group_own_below_water_color = 
1605						LLUIColorTable::instance().getColor( "NetMapGroupOwnBelowWater" );
1606
1607	F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius");
1608
1609	for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
1610	{
1611		LLViewerObject* objectp = *iter;
1612
1613		if(objectp->isDead())//some dead objects somehow not cleaned.
1614		{
1615			continue ;
1616		}
1617
1618		if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment())
1619		{
1620			continue;
1621		}
1622		const LLVector3& scale = objectp->getScale();
1623		const LLVector3d pos = objectp->getPositionGlobal();
1624		const F64 water_height = F64( objectp->getRegion()->getWaterHeight() );
1625		// LLWorld::getInstance()->getWaterHeight();
1626
1627		F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f;  // 1.3 is a fudge
1628
1629		// Limit the size of megaprims so they don't blot out everything on the minimap.
1630		// Attempting to draw very large megaprims also causes client lag.
1631		// See DEV-17370 and DEV-29869/SNOW-79 for details.
1632		approx_radius = llmin(approx_radius, max_radius);
1633
1634		LLColor4U color = above_water_color;
1635		if( objectp->permYouOwner() )
1636		{
1637			const F32 MIN_RADIUS_FOR_OWNED_OBJECTS = 2.f;
1638			if( approx_radius < MIN_RADIUS_FOR_OWNED_OBJECTS )
1639			{
1640				approx_radius = MIN_RADIUS_FOR_OWNED_OBJECTS;
1641			}
1642
1643			if( pos.mdV[VZ] >= water_height )
1644			{
1645				if ( objectp->permGroupOwner() )
1646				{
1647					color = group_own_above_water_color;
1648				}
1649				else
1650				{
1651				color = you_own_above_water_color;
1652			}
1653			}
1654			else
1655			{
1656				if ( objectp->permGroupOwner() )
1657				{
1658					color = group_own_below_water_color;
1659				}
1660			else
1661			{
1662				color = you_own_below_water_color;
1663			}
1664		}
1665		}
1666		else
1667		if( pos.mdV[VZ] < water_height )
1668		{
1669			color = below_water_color;
1670		}
1671
1672		netmap.renderScaledPointGlobal( 
1673			pos, 
1674			color,
1675			approx_radius );
1676	}
1677}
1678
1679void LLViewerObjectList::renderObjectBounds(const LLVector3 &center)
1680{
1681}
1682
1683void LLViewerObjectList::generatePickList(LLCamera &camera)
1684{
1685		LLViewerObject *objectp;
1686		S32 i;
1687		// Reset all of the GL names to zero.
1688		for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
1689		{
1690			(*iter)->mGLName = 0;
1691		}
1692
1693		mSelectPickList.clear();
1694
1695		std::vector<LLDrawable*> pick_drawables;
1696
1697		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
1698			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
1699		{
1700			LLViewerRegion* region = *iter;
1701			for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
1702			{
1703				LLSpatialPartition* part = region->getSpatialPartition(i);
1704				if (part)
1705				{	
1706					part->cull(camera, &pick_drawables, TRUE);
1707				}
1708			}
1709		}
1710
1711		for (std::vector<LLDrawable*>::iterator iter = pick_drawables.begin();
1712			iter != pick_drawables.end(); iter++)
1713		{
1714			LLDrawable* drawablep = *iter;
1715			if( !drawablep )
1716				continue;
1717
1718			LLViewerObject* last_objectp = NULL;
1719			for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
1720			{
1721				LLViewerObject* objectp = drawablep->getFace(face_num)->getViewerObject();
1722
1723				if (objectp && objectp != last_objectp)
1724				{
1725					mSelectPickList.insert(objectp);
1726					last_objectp = objectp;
1727				}
1728			}
1729		}
1730
1731		LLHUDNameTag::addPickable(mSelectPickList);
1732
1733		for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
1734			iter != LLCharacter::sInstances.end(); ++iter)
1735		{
1736			objectp = (LLVOAvatar*) *iter;
1737			if (!objectp->isDead())
1738			{
1739				if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible())
1740				{
1741					mSelectPickList.insert(objectp);
1742				}
1743			}
1744		}
1745
1746		// add all hud objects to pick list
1747		if (isAgentAvatarValid())
1748		{
1749			for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
1750				 iter != gAgentAvatarp->mAttachmentPoints.end(); )
1751			{
1752				LLVOAvatar::attachment_map_t::iterator curiter = iter++;
1753				LLViewerJointAttachment* attachment = curiter->second;
1754				if (attachment->getIsHUDAttachment())
1755				{
1756					for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
1757						 attachment_iter != attachment->mAttachedObjects.end();
1758						 ++attachment_iter)
1759					{
1760						if (LLViewerObject* attached_object = (*attachment_iter))
1761						{
1762							mSelectPickList.insert(attached_object);
1763							LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
1764							for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
1765								 iter != child_list.end(); iter++)
1766							{
1767								LLViewerObject* childp = *iter;
1768								if (childp)
1769								{
1770									mSelectPickList.insert(childp);
1771								}
1772							}
1773						}
1774					}
1775				}
1776			}
1777		}
1778		
1779		S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances();
1780
1781		if (num_pickables != 0)
1782		{
1783			S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
1784
1785			std::set<LLViewerObject*>::iterator pick_it;
1786			i = 0;
1787			for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
1788			{
1789				LLViewerObject* objp = (*pick_it);
1790				if (!objp || objp->isDead() || !objp->mbCanSelect)
1791				{
1792					mSelectPickList.erase(pick_it++);
1793					continue;
1794				}
1795				
1796				objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
1797				i++;
1798				++pick_it;
1799			}
1800
1801			LLHUDIcon::generatePickIDs(i * step, step);
1802	}
1803}
1804
1805LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
1806{
1807	std::set<LLViewerObject*>::iterator pick_it;
1808	for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it)
1809	{
1810		if ((*pick_it)->mGLName == object_id)
1811		{
1812			return (*pick_it);
1813		}
1814	}
1815	return NULL;
1816}
1817
1818void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
1819										const std::string &string,
1820										const LLColor4 &color,
1821										const LLColor4 &text_color,
1822										S32 line_width)
1823{
1824	LLDebugBeacon beacon;
1825	beacon.mPositionAgent = pos_agent;
1826	beacon.mString = string;
1827	beacon.mColor = color;
1828	beacon.mTextColor = text_color;
1829	beacon.mLineWidth = line_width;
1830
1831	mDebugBeacons.push_back(beacon);
1832}
1833
1834void LLViewerObjectList::resetObjectBeacons()
1835{
1836	mDebugBeacons.clear();
1837}
1838
1839LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp)
1840{
1841	LLMemType mt(LLMemType::MTYPE_OBJECT);
1842	LLUUID fullid;
1843	fullid.generate();
1844
1845	LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
1846	if (!objectp)
1847	{
1848// 		llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << llendl;
1849		return NULL;
1850	}
1851
1852	mUUIDObjectMap[fullid] = objectp;
1853
1854	mObjects.push_back(objectp);
1855
1856	updateActive(objectp);
1857
1858	return objectp;
1859}
1860
1861
1862static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object");
1863
1864LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp,
1865												 const LLUUID &uuid, const U32 local_id, const LLHost &sender)
1866{
1867	LLMemType mt(LLMemType::MTYPE_OBJECT);
1868	LLFastTimer t(FTM_CREATE_OBJECT);
1869	
1870	LLUUID fullid;
1871	if (uuid == LLUUID::null)
1872	{
1873		fullid.generate();
1874	}
1875	else
1876	{
1877		fullid = uuid;
1878	}
1879
1880	LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
1881	if (!objectp)
1882	{
1883// 		llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) <<…

Large files files are truncated, but you can click here to view the full file