diff options
Diffstat (limited to 'indra/newview/llworld.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/llworld.cpp | 751 |
1 files changed, 307 insertions, 444 deletions
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 399442e5c4..5d657f7eef 100644..100755 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -50,16 +50,18 @@ #include "llviewerstats.h" #include "llvlcomposition.h" #include "llvoavatar.h" +#include "llvocache.h" #include "llvowater.h" #include "message.h" #include "pipeline.h" #include "llappviewer.h" // for do_disconnect() - +#include "llscenemonitor.h" #include <deque> #include <queue> #include <map> #include <cstring> + // // Globals // @@ -68,7 +70,6 @@ U32 gAgentPauseSerialNum = 0; // // Constants // -const S32 MAX_NUMBER_OF_CLOUDS = 750; const S32 WORLD_PATCH_SIZE = 16; extern LLColor4U MAX_WATER_COLOR; @@ -90,19 +91,13 @@ LLWorld::LLWorld() : mLastPacketsIn(0), mLastPacketsOut(0), mLastPacketsLost(0), - mSpaceTimeUSec(0), - mClassicCloudsEnabled(TRUE) + mSpaceTimeUSec(0) { for (S32 i = 0; i < 8; i++) { mEdgeWaterObjects[i] = NULL; } - if (gNoRender) - { - return; - } - LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4); U8 *default_texture = raw->getData(); *(default_texture++) = MAX_WATER_COLOR.mV[0]; @@ -114,6 +109,7 @@ LLWorld::LLWorld() : gGL.getTexUnit(0)->bind(mDefaultWaterTexturep); mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + LLViewerRegion::sVOCacheCullingEnabled = gSavedSettings.getBOOL("RequestFullRegionCache") && gSavedSettings.getBOOL("ObjectCacheEnabled"); } @@ -126,52 +122,68 @@ void LLWorld::destroyClass() LLViewerRegion* region_to_delete = *region_it++; removeRegion(region_to_delete->getHost()); } - if(LLVOCache::hasInstance()) + + LLViewerPartSim::getInstance()->destroyClass(); + + mDefaultWaterTexturep = NULL ; + for (S32 i = 0; i < 8; i++) { - LLVOCache::getInstance()->destroyClass() ; + mEdgeWaterObjects[i] = NULL; } - LLViewerPartSim::getInstance()->destroyClass(); + + //make all visible drawbles invisible. + LLDrawable::incrementVisible(); + + LLSceneMonitor::deleteSingleton(); } LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) { - LLMemType mt(LLMemType::MTYPE_REGIONS); - llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl; + LL_INFOS() << "Add region with handle: " << region_handle << " on host " << host << LL_ENDL; LLViewerRegion *regionp = getRegionFromHandle(region_handle); + std::string seedUrl; if (regionp) { - llinfos << "Region exists, removing it " << llendl; LLHost old_host = regionp->getHost(); // region already exists! if (host == old_host && regionp->isAlive()) { // This is a duplicate for the same host and it's alive, don't bother. + LL_INFOS() << "Region already exists and is alive, using existing region" << LL_ENDL; return regionp; } if (host != old_host) { - llwarns << "LLWorld::addRegion exists, but old host " << old_host - << " does not match new host " << host << llendl; + LL_WARNS() << "LLWorld::addRegion exists, but old host " << old_host + << " does not match new host " << host + << ", removing old region and creating new" << LL_ENDL; } if (!regionp->isAlive()) { - llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl; + LL_WARNS() << "LLWorld::addRegion exists, but isn't alive. Removing old region and creating new" << LL_ENDL; } + // Save capabilities seed URL + seedUrl = regionp->getCapability("Seed"); + // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host // matches, because all the agent state for the new camera is completely different. removeRegion(old_host); } + else + { + LL_INFOS() << "Region does not exist, creating new one" << LL_ENDL; + } U32 iindex = 0; U32 jindex = 0; from_region_handle(region_handle, &iindex, &jindex); S32 x = (S32)(iindex/mWidth); S32 y = (S32)(jindex/mWidth); - llinfos << "Adding new region (" << x << ":" << y << ")" << llendl; - llinfos << "Host: " << host << llendl; + LL_INFOS() << "Adding new region (" << x << ":" << y << ")" + << " on host: " << host << LL_ENDL; LLVector3d origin_global; @@ -184,12 +196,13 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) getRegionWidthInMeters() ); if (!regionp) { - llerrs << "Unable to create new region!" << llendl; + LL_ERRS() << "Unable to create new region!" << LL_ENDL; } - regionp->mCloudLayer.create(regionp); - regionp->mCloudLayer.setWidth((F32)mWidth); - regionp->mCloudLayer.setWindPointer(®ionp->mWind); + if ( !seedUrl.empty() ) + { + regionp->setCapability("Seed", seedUrl); + } mRegionList.push_back(regionp); mActiveRegionList.push_back(regionp); @@ -221,7 +234,7 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) neighborp = getRegionFromHandle(adj_handle); if (neighborp) { - //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl; + //LL_INFOS() << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << LL_ENDL; regionp->connectNeighbor(neighborp, dir); } } @@ -239,7 +252,7 @@ void LLWorld::removeRegion(const LLHost &host) LLViewerRegion *regionp = getRegion(host); if (!regionp) { - llwarns << "Trying to remove region that doesn't exist!" << llendl; + LL_WARNS() << "Trying to remove region that doesn't exist!" << LL_ENDL; return; } @@ -249,21 +262,21 @@ void LLWorld::removeRegion(const LLHost &host) iter != mRegionList.end(); ++iter) { LLViewerRegion* reg = *iter; - llwarns << "RegionDump: " << reg->getName() + LL_WARNS() << "RegionDump: " << reg->getName() << " " << reg->getHost() << " " << reg->getOriginGlobal() - << llendl; + << LL_ENDL; } - llwarns << "Agent position global " << gAgent.getPositionGlobal() + LL_WARNS() << "Agent position global " << gAgent.getPositionGlobal() << " agent " << gAgent.getPositionAgent() - << llendl; + << LL_ENDL; - llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl; + LL_WARNS() << "Regions visited " << gAgent.getRegionsVisited() << LL_ENDL; - llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl; + LL_WARNS() << "gFrameTimeSeconds " << gFrameTimeSeconds << LL_ENDL; - llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl; + LL_WARNS() << "Disabling region " << regionp->getName() << " that agent is in!" << LL_ENDL; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected")); regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed. @@ -271,16 +284,22 @@ void LLWorld::removeRegion(const LLHost &host) } from_region_handle(regionp->getHandle(), &x, &y); - llinfos << "Removing region " << x << ":" << y << llendl; + LL_INFOS() << "Removing region " << x << ":" << y << LL_ENDL; mRegionList.remove(regionp); mActiveRegionList.remove(regionp); mCulledRegionList.remove(regionp); mVisibleRegionList.remove(regionp); - + + mRegionRemovedSignal(regionp); + delete regionp; updateWaterObjects(); + + //double check all objects of this region are removed. + gObjectList.clearAllMapObjectsInRegion(regionp) ; + //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ; } @@ -401,6 +420,19 @@ LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle) return NULL; } +LLViewerRegion* LLWorld::getRegionFromID(const LLUUID& region_id) +{ + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if (regionp->getRegionID() == region_id) + { + return regionp; + } + } + return NULL; +} void LLWorld::updateAgentOffset(const LLVector3d &offset_global) { @@ -587,22 +619,23 @@ void LLWorld::updateVisibilities() { F32 cur_far_clip = LLViewerCamera::getInstance()->getFar(); - LLViewerCamera::getInstance()->setFar(mLandFarClip); - - F32 diagonal_squared = F_SQRT2 * F_SQRT2 * mWidth * mWidth; - // Go through the culled list and check for visible regions + // Go through the culled list and check for visible regions (region is visible if land is visible) for (region_list_t::iterator iter = mCulledRegionList.begin(); iter != mCulledRegionList.end(); ) { region_list_t::iterator curiter = iter++; LLViewerRegion* regionp = *curiter; - F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); - F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); - if (!regionp->getLand().hasZData() - || LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius)) + + LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); + if (part) { - mCulledRegionList.erase(curiter); - mVisibleRegionList.push_back(regionp); + LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); + const LLVector4a* bounds = group->getBounds(); + if (LLViewerCamera::getInstance()->AABBInFrustum(bounds[0], bounds[1])) + { + mCulledRegionList.erase(curiter); + mVisibleRegionList.push_back(regionp); + } } } @@ -617,20 +650,21 @@ void LLWorld::updateVisibilities() continue; } - F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); - F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); - if (LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius)) + LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); + if (part) { - regionp->calculateCameraDistance(); - if (!gNoRender) + LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); + const LLVector4a* bounds = group->getBounds(); + if (LLViewerCamera::getInstance()->AABBInFrustum(bounds[0], bounds[1])) { + regionp->calculateCameraDistance(); regionp->getLand().updatePatchVisibilities(gAgent); } - } - else - { - mVisibleRegionList.erase(curiter); - mCulledRegionList.push_back(regionp); + else + { + mVisibleRegionList.erase(curiter); + mCulledRegionList.push_back(regionp); + } } } @@ -640,115 +674,82 @@ void LLWorld::updateVisibilities() LLViewerCamera::getInstance()->setFar(cur_far_clip); } +static LLTrace::SampleStatHandle<> sNumActiveCachedObjects("numactivecachedobjects", "Number of objects loaded from cache"); + void LLWorld::updateRegions(F32 max_update_time) { - LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS); LLTimer update_timer; - BOOL did_one = FALSE; + mNumOfActiveCachedObjects = 0; - // Perform idle time updates for the regions (and associated surfaces) - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) + if(LLViewerCamera::getInstance()->isChanged()) { - LLViewerRegion* regionp = *iter; - F32 max_time = max_update_time - update_timer.getElapsedTimeF32(); - if (did_one && max_time <= 0.f) - break; - max_time = llmin(max_time, max_update_time*.1f); - did_one |= regionp->idleUpdate(max_update_time); + LLViewerRegion::sLastCameraUpdated = LLViewerOctreeEntryData::getCurrentFrame() + 1; } -} - -void LLWorld::updateParticles() -{ - LLViewerPartSim::getInstance()->updateSimulation(); -} - -void LLWorld::updateClouds(const F32 dt) -{ - static LLFastTimer::DeclareTimer ftm("World Clouds"); - LLFastTimer t(ftm); - - if ( gSavedSettings.getBOOL("FreezeTime") ) + LLViewerRegion::calcNewObjectCreationThrottle(); + if(LLViewerRegion::isNewObjectCreationThrottleDisabled()) { - // don't move clouds in snapshot mode - return; + max_update_time = llmax(max_update_time, 1.0f); //seconds, loosen the time throttle. } - if ( - mClassicCloudsEnabled != - gSavedSettings.getBOOL("SkyUseClassicClouds") ) - { - // The classic cloud toggle has been flipped - // gotta update all of the cloud layers - mClassicCloudsEnabled = - gSavedSettings.getBOOL("SkyUseClassicClouds"); + F32 max_time = llmin((F32)(max_update_time - update_timer.getElapsedTimeF32()), max_update_time * 0.25f); + //update the self avatar region + LLViewerRegion* self_regionp = gAgent.getRegion(); + if(self_regionp) + { + self_regionp->idleUpdate(max_time); + } - if ( !mClassicCloudsEnabled && mActiveRegionList.size() ) + //sort regions by its mLastUpdate + //smaller mLastUpdate first to make sure every region has chance to get updated. + LLViewerRegion::region_priority_list_t region_list; + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + LLViewerRegion* regionp = *iter; + if(regionp != self_regionp) { - // We've transitioned to having classic clouds disabled - // reset all cloud layers. - for ( - region_list_t::iterator iter = mActiveRegionList.begin(); - iter != mActiveRegionList.end(); - ++iter) - { - LLViewerRegion* regionp = *iter; - regionp->mCloudLayer.reset(); - } - - return; + region_list.insert(regionp); } + mNumOfActiveCachedObjects += regionp->getNumOfActiveCachedObjects(); } - else if ( !mClassicCloudsEnabled ) return; - if (mActiveRegionList.size()) + // Perform idle time updates for the regions (and associated surfaces) + for (LLViewerRegion::region_priority_list_t::iterator iter = region_list.begin(); + iter != region_list.end(); ++iter) { - for (region_list_t::iterator iter = mActiveRegionList.begin(); - iter != mActiveRegionList.end(); ++iter) + if(max_time > 0.f) { - LLViewerRegion* regionp = *iter; - regionp->mCloudLayer.updatePuffs(dt); + max_time = llmin((F32)(max_update_time - update_timer.getElapsedTimeF32()), max_update_time * 0.25f); } - // Reshuffle who owns which puffs - for (region_list_t::iterator iter = mActiveRegionList.begin(); - iter != mActiveRegionList.end(); ++iter) + if(max_time > 0.f) { - LLViewerRegion* regionp = *iter; - regionp->mCloudLayer.updatePuffOwnership(); + (*iter)->idleUpdate(max_time); } - - // Add new puffs - for (region_list_t::iterator iter = mActiveRegionList.begin(); - iter != mActiveRegionList.end(); ++iter) + else { - LLViewerRegion* regionp = *iter; - regionp->mCloudLayer.updatePuffCount(); - } + //perform some necessary but very light updates. + (*iter)->lightIdleUpdate(); + } } -} -LLCloudGroup* LLWorld::findCloudGroup(const LLCloudPuff &puff) + sample(sNumActiveCachedObjects, mNumOfActiveCachedObjects); + } + +void LLWorld::clearAllVisibleObjects() { - if (mActiveRegionList.size()) + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) { - // Update all the cloud puff positions, and timer based stuff - // such as death decay - for (region_list_t::iterator iter = mActiveRegionList.begin(); - iter != mActiveRegionList.end(); ++iter) - { - LLViewerRegion* regionp = *iter; - LLCloudGroup *groupp = regionp->mCloudLayer.findCloudGroup(puff); - if (groupp) - { - return groupp; - } - } + //clear all cached visible objects. + (*iter)->clearCachedVisibleObjects(); } - return NULL; } +void LLWorld::updateParticles() +{ + LLViewerPartSim::getInstance()->updateSimulation(); +} void LLWorld::renderPropertyLines() { @@ -767,7 +768,7 @@ void LLWorld::renderPropertyLines() void LLWorld::updateNetStats() { - F32 bits = 0.f; + F64Bits bits; U32 packets = 0; for (region_list_t::iterator iter = mActiveRegionList.begin(); @@ -775,29 +776,31 @@ void LLWorld::updateNetStats() { LLViewerRegion* regionp = *iter; regionp->updateNetStats(); - bits += regionp->mBitStat.getCurrent(); - packets += llfloor( regionp->mPacketsStat.getCurrent() ); + bits += regionp->mBitsReceived; + packets += llfloor( regionp->mPacketsReceived ); + regionp->mBitsReceived = (F32Bits)0.f; + regionp->mPacketsReceived = 0.f; } S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn; S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut; S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost; - S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits(); - S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits(); - LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f); - LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f); - LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f); - LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in); - LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out); - LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets); - if (packets_in) - { - LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in)); - } - else + F64Bits actual_in_bits(gMessageSystem->mPacketRing.getAndResetActualInBits()); + F64Bits actual_out_bits(gMessageSystem->mPacketRing.getAndResetActualOutBits()); + + add(LLStatViewer::MESSAGE_SYSTEM_DATA_IN, actual_in_bits); + add(LLStatViewer::MESSAGE_SYSTEM_DATA_OUT, actual_out_bits); + add(LLStatViewer::ACTIVE_MESSAGE_DATA_RECEIVED, bits); + add(LLStatViewer::PACKETS_IN, packets_in); + add(LLStatViewer::PACKETS_OUT, packets_out); + add(LLStatViewer::PACKETS_LOST, packets_lost); + + F32 total_packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN); + if (total_packets_in > 0) { - LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f); + F32 total_packets_lost = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_LOST); + sample(LLStatViewer::PACKETS_LOST_PERCENT, LLUnits::Ratio::fromValue((F32)total_packets_lost/(F32)total_packets_in)); } mLastPacketsIn = gMessageSystem->mPacketsIn; @@ -808,8 +811,8 @@ void LLWorld::updateNetStats() void LLWorld::printPacketsLost() { - llinfos << "Simulators:" << llendl; - llinfos << "----------" << llendl; + LL_INFOS() << "Simulators:" << LL_ENDL; + LL_INFOS() << "----------" << LL_ENDL; LLCircuitData *cdp = NULL; for (region_list_t::iterator iter = mActiveRegionList.begin(); @@ -821,8 +824,8 @@ void LLWorld::printPacketsLost() { LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal(); - llinfos << regionp->getHost() << ", range: " << range.length() - << " packets lost: " << cdp->getPacketsLost() << llendl; + LL_INFOS() << regionp->getHost() << ", range: " << range.length() + << " packets lost: " << cdp->getPacketsLost() << LL_ENDL; } } } @@ -870,42 +873,6 @@ void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_heigh } } -// There are three types of water objects: -// Region water objects: the water in a region. -// Hole water objects: water in the void but within current draw distance. -// Edge water objects: the water outside the draw distance, up till the horizon. -// -// For example: -// -// -----------------------horizon------------------------- -// | | | | -// | Edge Water | | | -// | | | | -// | | | | -// | | | | -// | | | | -// | | rwidth | | -// | | <-----> | | -// ------------------------------------------------------- -// | |Hole |other| | | -// | |Water|reg. | | | -// | |-----------------| | -// | |other|cur. |<--> | | -// | |reg. | reg.| \__|_ draw distance | -// | |-----------------| | -// | | | |<--->| | -// | | | | \__|_ range | -// ------------------------------------------------------- -// | |<----width------>|<--horizon ext.->| -// | | | | -// | | | | -// | | | | -// | | | | -// | | | | -// | | | | -// | | | | -// ------------------------------------------------------- -// void LLWorld::updateWaterObjects() { if (!gAgent.getRegion()) @@ -914,191 +881,32 @@ void LLWorld::updateWaterObjects() } if (mRegionList.empty()) { - llwarns << "No regions!" << llendl; + LL_WARNS() << "No regions!" << LL_ENDL; return; } - // Region width in meters. - S32 const rwidth = (S32)REGION_WIDTH_U32; + // First, determine the min and max "box" of water objects + S32 min_x = 0; + S32 min_y = 0; + S32 max_x = 0; + S32 max_y = 0; + U32 region_x, region_y; - // The distance we might see into the void - // when standing on the edge of a region, in meters. - S32 const draw_distance = llceil(mLandFarClip); + S32 rwidth = 256; - // We can only have "holes" in the water (where there no region) if we - // can have existing regions around it. Taking into account that this - // code is only executed when we enter a region, and not when we walk - // around in it, we (only) need to take into account regions that fall - // within the draw_distance. - // - // Set 'range' to draw_distance, rounded up to the nearest multiple of rwidth. - S32 const nsims = (draw_distance + rwidth - 1) / rwidth; - S32 const range = nsims * rwidth; + // We only want to fill in water for stuff that's near us, say, within 256 or 512m + S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256; - // Get South-West corner of current region. - LLViewerRegion const* regionp = gAgent.getRegion(); - U32 region_x, region_y; + LLViewerRegion* regionp = gAgent.getRegion(); from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); - // The min. and max. coordinates of the South-West corners of the Hole water objects. - S32 const min_x = (S32)region_x - range; - S32 const min_y = (S32)region_y - range; - S32 const max_x = (S32)region_x + range; - S32 const max_y = (S32)region_y + range; - - // Attempt to determine a sensible water height for all the - // Hole Water objects. - // - // It make little sense to try to guess what the best water - // height should be when that isn't completely obvious: if it's - // impossible to satisfy every region's water height without - // getting a jump in the water height. - // - // In order to keep the reasoning simple, we assume something - // logical as a group of connected regions, where the coastline - // is at the outer edge. Anything more complex that would "break" - // under such an assumption would probably break anyway (would - // depend on terrain editing and existing mega prims, say, if - // anything would make sense at all). - // - // So, what we do is find all connected regions within the - // draw distance that border void, and then pick the lowest - // water height of those (coast) regions. - S32 const n = 2 * nsims + 1; - S32 const origin = nsims + nsims * n; - std::vector<F32> water_heights(n * n); - std::vector<U8> checked(n * n, 0); // index = nx + ny * n + origin; - U8 const region_bit = 1; - U8 const hole_bit = 2; - U8 const bordering_hole_bit = 4; - U8 const bordering_edge_bit = 8; - // Use the legacy waterheight for the Edge water in the case - // that we don't find any Hole water at all. - F32 water_height = DEFAULT_WATER_HEIGHT; - int max_count = 0; - LL_DEBUGS("WaterHeight") << "Current region: " << regionp->getName() << "; water height: " << regionp->getWaterHeight() << " m." << LL_ENDL; - std::map<S32, int> water_height_counts; - typedef std::queue<std::pair<S32, S32>, std::deque<std::pair<S32, S32> > > nxny_pairs_type; - nxny_pairs_type nxny_pairs; - nxny_pairs.push(nxny_pairs_type::value_type(0, 0)); - water_heights[origin] = regionp->getWaterHeight(); - checked[origin] = region_bit; - // For debugging purposes. - int number_of_connected_regions = 1; - int uninitialized_regions = 0; - int bordering_hole = 0; - int bordering_edge = 0; - while(!nxny_pairs.empty()) - { - S32 const nx = nxny_pairs.front().first; - S32 const ny = nxny_pairs.front().second; - LL_DEBUGS("WaterHeight") << "nx,ny = " << nx << "," << ny << LL_ENDL; - S32 const index = nx + ny * n + origin; - nxny_pairs.pop(); - for (S32 dir = 0; dir < 4; ++dir) - { - S32 const cnx = nx + gDirAxes[dir][0]; - S32 const cny = ny + gDirAxes[dir][1]; - LL_DEBUGS("WaterHeight") << "dir = " << dir << "; cnx,cny = " << cnx << "," << cny << LL_ENDL; - S32 const cindex = cnx + cny * n + origin; - bool is_hole = false; - bool is_edge = false; - LLViewerRegion* new_region_found = NULL; - if (cnx < -nsims || cnx > nsims || - cny < -nsims || cny > nsims) - { - LL_DEBUGS("WaterHeight") << " Edge Water!" << LL_ENDL; - // Bumped into Edge water object. - is_edge = true; - } - else if (checked[cindex]) - { - LL_DEBUGS("WaterHeight") << " Already checked before!" << LL_ENDL; - // Already checked. - is_hole = (checked[cindex] & hole_bit); - } - else - { - S32 x = (S32)region_x + cnx * rwidth; - S32 y = (S32)region_y + cny * rwidth; - U64 region_handle = to_region_handle(x, y); - new_region_found = getRegionFromHandle(region_handle); - is_hole = !new_region_found; - checked[cindex] = is_hole ? hole_bit : region_bit; - } - if (is_hole) - { - // This was a region that borders at least one 'hole'. - // Count the found coastline. - F32 new_water_height = water_heights[index]; - LL_DEBUGS("WaterHeight") << " This is void; counting coastline with water height of " << new_water_height << LL_ENDL; - S32 new_water_height_cm = llround(new_water_height * 100); - int count = (water_height_counts[new_water_height_cm] += 1); - // Just use the lowest water height: this is mainly about the horizon water, - // and whatever we do, we don't want it to be possible to look under the water - // when looking in the distance: it is better to make a step downwards in water - // height when going away from the avie than a step upwards. However, since - // everyone is used to DEFAULT_WATER_HEIGHT, don't allow a single region - // to drag the water level below DEFAULT_WATER_HEIGHT on it's own. - if (bordering_hole == 0 || // First time we get here. - (new_water_height >= DEFAULT_WATER_HEIGHT && - new_water_height < water_height) || - (new_water_height < DEFAULT_WATER_HEIGHT && - count > max_count) - ) - { - water_height = new_water_height; - } - if (count > max_count) - { - max_count = count; - } - if (!(checked[index] & bordering_hole_bit)) - { - checked[index] |= bordering_hole_bit; - ++bordering_hole; - } - } - else if (is_edge && !(checked[index] & bordering_edge_bit)) - { - checked[index] |= bordering_edge_bit; - ++bordering_edge; - } - if (!new_region_found) - { - // Dead end, there is no region here. - continue; - } - // Found a new connected region. - ++number_of_connected_regions; - if (new_region_found->getName().empty()) - { - // Uninitialized LLViewerRegion, don't use it's water height. - LL_DEBUGS("WaterHeight") << " Uninitialized region." << LL_ENDL; - ++uninitialized_regions; - continue; - } - nxny_pairs.push(nxny_pairs_type::value_type(cnx, cny)); - water_heights[cindex] = new_region_found->getWaterHeight(); - LL_DEBUGS("WaterHeight") << " Found a new region (name: " << new_region_found->getName() << "; water height: " << water_heights[cindex] << " m)!" << LL_ENDL; - } - } - llinfos << "Number of connected regions: " << number_of_connected_regions << " (" << uninitialized_regions << - " uninitialized); number of regions bordering Hole water: " << bordering_hole << - "; number of regions bordering Edge water: " << bordering_edge << llendl; - llinfos << "Coastline count (height, count): "; - bool first = true; - for (std::map<S32, int>::iterator iter = water_height_counts.begin(); iter != water_height_counts.end(); ++iter) - { - if (!first) llcont << ", "; - llcont << "(" << (iter->first / 100.f) << ", " << iter->second << ")"; - first = false; - } - llcont << llendl; - llinfos << "Water height used for Hole and Edge water objects: " << water_height << llendl; + min_x = (S32)region_x - range; + min_y = (S32)region_y - range; + max_x = (S32)region_x + range; + max_y = (S32)region_y + range; - // Update all Region water objects. - for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter) + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) { LLViewerRegion* regionp = *iter; LLVOWater* waterp = regionp->getLand().getWaterObj(); @@ -1108,75 +916,96 @@ void LLWorld::updateWaterObjects() } } - // Clean up all existing Hole water objects. for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin(); - iter != mHoleWaterObjects.end(); ++iter) + iter != mHoleWaterObjects.end(); ++ iter) { LLVOWater* waterp = *iter; gObjectList.killObject(waterp); } mHoleWaterObjects.clear(); - // Let the Edge and Hole water boxes be 1024 meter high so that they - // are never too small to be drawn (A LL_VO_*_WATER box has water - // rendered on it's bottom surface only), and put their bottom at - // the current regions water height. - F32 const box_height = 1024; - F32 const water_center_z = water_height + box_height / 2; + // Use the water height of the region we're on for areas where there is no region + F32 water_height = gAgent.getRegion()->getWaterHeight(); - // Create new Hole water objects within 'range' where there is no region. - for (S32 x = min_x; x <= max_x; x += rwidth) + // Now, get a list of the holes + S32 x, y; + for (x = min_x; x <= max_x; x += rwidth) { - for (S32 y = min_y; y <= max_y; y += rwidth) + for (y = min_y; y <= max_y; y += rwidth) { U64 region_handle = to_region_handle(x, y); if (!getRegionFromHandle(region_handle)) - { - LLVOWater* waterp = (LLVOWater*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion()); + { // No region at that area, so make water + LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); waterp->setUseTexture(FALSE); - waterp->setPositionGlobal(LLVector3d(x + rwidth / 2, y + rwidth / 2, water_center_z)); - waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, box_height)); + waterp->setPositionGlobal(LLVector3d(x + rwidth/2, + y + rwidth/2, + 256.f + water_height)); + waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); } } } - // Center of the region. - S32 const center_x = region_x + rwidth / 2; - S32 const center_y = region_y + rwidth / 2; - // Width of the area with Hole water objects. - S32 const width = rwidth + 2 * range; - S32 const horizon_extend = 2048 + 512 - range; // Legacy value. - // The overlap is needed to get rid of sky pixels being visible between the - // Edge and Hole water object at greater distances (due to floating point - // round off errors). - S32 const edge_hole_overlap = 1; // Twice the actual overlap. + // Update edge water objects + S32 wx, wy; + S32 center_x, center_y; + wx = (max_x - min_x) + rwidth; + wy = (max_y - min_y) + rwidth; + center_x = min_x + (wx >> 1); + center_y = min_y + (wy >> 1); + + S32 add_boundary[4] = { + 512 - (max_x - region_x), + 512 - (max_y - region_y), + 512 - (region_x - min_x), + 512 - (region_y - min_y) }; - for (S32 dir = 0; dir < 8; ++dir) + S32 dir; + for (dir = 0; dir < 8; dir++) { - // Size of the Edge water objects. - S32 const dim_x = (gDirAxes[dir][0] == 0) ? width : (horizon_extend + edge_hole_overlap); - S32 const dim_y = (gDirAxes[dir][1] == 0) ? width : (horizon_extend + edge_hole_overlap); - // And their position. - S32 const water_center_x = center_x + (width + horizon_extend) / 2 * gDirAxes[dir][0]; - S32 const water_center_y = center_y + (width + horizon_extend) / 2 * gDirAxes[dir][1]; + S32 dim[2] = { 0 }; + switch (gDirAxes[dir][0]) + { + case -1: dim[0] = add_boundary[2]; break; + case 0: dim[0] = wx; break; + default: dim[0] = add_boundary[0]; break; + } + switch (gDirAxes[dir][1]) + { + case -1: dim[1] = add_boundary[3]; break; + case 0: dim[1] = wy; break; + default: dim[1] = add_boundary[1]; break; + } + // Resize and reshape the water objects + const S32 water_center_x = center_x + ll_round((wx + dim[0]) * 0.5f * gDirAxes[dir][0]); + const S32 water_center_y = center_y + ll_round((wy + dim[1]) * 0.5f * gDirAxes[dir][1]); + LLVOWater* waterp = mEdgeWaterObjects[dir]; if (!waterp || waterp->isDead()) { // The edge water objects can be dead because they're attached to the region that the // agent was in when they were originally created. - mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion()); + mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, + gAgent.getRegion()); waterp = mEdgeWaterObjects[dir]; waterp->setUseTexture(FALSE); - waterp->setIsEdgePatch(TRUE); // Mark that this is edge water and not hole water. + waterp->setIsEdgePatch(TRUE); gPipeline.createObject(waterp); } waterp->setRegion(gAgent.getRegion()); - LLVector3d water_pos(water_center_x, water_center_y, water_center_z); - LLVector3 water_scale((F32) dim_x, (F32) dim_y, box_height); + LLVector3d water_pos(water_center_x, water_center_y, 256.f + water_height) ; + LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); + + //stretch out to horizon + water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]); + water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]); + + water_pos.mdV[0] += 1024.f * gDirAxes[dir][0]; + water_pos.mdV[1] += 1024.f * gDirAxes[dir][1]; waterp->setPositionGlobal(water_pos); waterp->setScale(water_scale); @@ -1185,6 +1014,7 @@ void LLWorld::updateWaterObjects() } } + void LLWorld::shiftRegions(const LLVector3& offset) { for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i) @@ -1201,12 +1031,12 @@ LLViewerTexture* LLWorld::getDefaultWaterTexture() return mDefaultWaterTexturep; } -void LLWorld::setSpaceTimeUSec(const U64 space_time_usec) +void LLWorld::setSpaceTimeUSec(const U64MicrosecondsImplicit space_time_usec) { mSpaceTimeUSec = space_time_usec; } -U64 LLWorld::getSpaceTimeUSec() const +U64MicrosecondsImplicit LLWorld::getSpaceTimeUSec() const { return mSpaceTimeUSec; } @@ -1246,7 +1076,7 @@ void LLWorld::disconnectRegions() continue; } - llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl; + LL_INFOS() << "Sending AgentQuitCopy to: " << regionp->getHost() << LL_ENDL; msg->newMessageFast(_PREHASH_AgentQuitCopy); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -1257,11 +1087,11 @@ void LLWorld::disconnectRegions() } } -static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim"); +static LLTrace::BlockTimerStatHandle FTM_ENABLE_SIMULATOR("Enable Sim"); void process_enable_simulator(LLMessageSystem *msg, void **user_data) { - LLFastTimer t(FTM_ENABLE_SIMULATOR); + LL_RECORD_BLOCK_TIME(FTM_ENABLE_SIMULATOR); // enable the appropriate circuit for this simulator and // add its values into the gSimulator structure U64 handle; @@ -1280,7 +1110,7 @@ void process_enable_simulator(LLMessageSystem *msg, void **user_data) LLWorld::getInstance()->addRegion(handle, sim); // give the simulator a message it can use to get ip and port - llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl; + LL_INFOS() << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << LL_ENDL; msg->newMessageFast(_PREHASH_UseCircuitCode); msg->nextBlockFast(_PREHASH_CircuitCode); msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode()); @@ -1308,7 +1138,7 @@ public: !input["body"].has("sim-ip-and-port") || !input["body"].has("seed-capability")) { - llwarns << "invalid parameters" << llendl; + LL_WARNS() << "invalid parameters" << LL_ENDL; return; } @@ -1317,10 +1147,12 @@ public: LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim); if (!regionp) { - llwarns << "Got EstablishAgentCommunication for unknown region " - << sim << llendl; + LL_WARNS() << "Got EstablishAgentCommunication for unknown region " + << sim << LL_ENDL; return; } + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == " + << input["body"]["seed-capability"] << LL_ENDL; regionp->setSeedCapability(input["body"]["seed-capability"]); } }; @@ -1331,7 +1163,7 @@ void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data) { LLHost host = mesgsys->getSender(); - //llinfos << "Disabling simulator with message from " << host << llendl; + //LL_INFOS() << "Disabling simulator with message from " << host << LL_ENDL; LLWorld::getInstance()->removeRegion(host); mesgsys->disableCircuit(host); @@ -1344,8 +1176,8 @@ void process_region_handshake(LLMessageSystem* msg, void** user_data) LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host); if (!regionp) { - llwarns << "Got region handshake for unknown region " - << host << llendl; + LL_WARNS() << "Got region handshake for unknown region " + << host << LL_ENDL; return; } @@ -1383,6 +1215,7 @@ void send_agent_pause() } gObjectList.mWasPaused = TRUE; + LLViewerStats::instance().getRecording().stop(); } @@ -1412,36 +1245,27 @@ void send_agent_resume() gMessageSystem->sendReliable(regionp->getHost()); } - // Reset the FPS counter to avoid an invalid fps - LLViewerStats::getInstance()->mFPSStat.start(); + // Resume data collection to ignore invalid rates + LLViewerStats::instance().getRecording().resume(); LLAppViewer::instance()->resumeMainloopTimeout(); } static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin) { - LLVector3d pos_global; - LLVector3 pos_local; - U8 bits; - - bits = compact_local & 0xFF; - pos_local.mV[VZ] = F32(bits) * 4.f; - compact_local >>= 8; + LLVector3d pos_local; - bits = compact_local & 0xFF; - pos_local.mV[VY] = (F32)bits; - compact_local >>= 8; + pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4; + pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU; + pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU; - bits = compact_local & 0xFF; - pos_local.mV[VX] = (F32)bits; - - pos_global.setVec( pos_local ); - pos_global += region_origin; - return pos_global; + return region_origin + pos_local; } void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const { + F32 radius_squared = radius * radius; + if(avatar_ids != NULL) { avatar_ids->clear(); @@ -1450,30 +1274,69 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi { positions->clear(); } + // get the list of avatars from the character list first, so distances are correct + // when agent is above 1020m and other avatars are nearby + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; + + if (!pVOAvatar->isDead() && !pVOAvatar->mIsDummy) + { + LLVector3d pos_global = pVOAvatar->getPositionGlobal(); + LLUUID uuid = pVOAvatar->getID(); + + if (!uuid.isNull() + && dist_vec_squared(pos_global, relative_to) <= radius_squared) + { + if(positions != NULL) + { + positions->push_back(pos_global); + } + if(avatar_ids !=NULL) + { + avatar_ids->push_back(uuid); + } + } + } + } + // region avatars added for situations where radius is greater than RenderFarClip for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* regionp = *iter; const LLVector3d& origin_global = regionp->getOriginGlobal(); - S32 count = regionp->mMapAvatars.count(); + S32 count = regionp->mMapAvatars.size(); for (S32 i = 0; i < count; i++) { - LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global); - if(dist_vec(pos_global, relative_to) <= radius) + LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.at(i), origin_global); + if(dist_vec_squared(pos_global, relative_to) <= radius_squared) { - if(positions != NULL) - { - positions->push_back(pos_global); - } - if(avatar_ids != NULL) + LLUUID uuid = regionp->mMapAvatarIDs.at(i); + // if this avatar doesn't already exist in the list, add it + if(uuid.notNull() && avatar_ids != NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) { - avatar_ids->push_back(regionp->mMapAvatarIDs.get(i)); + if (positions != NULL) + { + positions->push_back(pos_global); + } + avatar_ids->push_back(uuid); } } } } } +bool LLWorld::isRegionListed(const LLViewerRegion* region) const +{ + region_list_t::const_iterator it = find(mRegionList.begin(), mRegionList.end(), region); + return it != mRegionList.end(); +} + +boost::signals2::connection LLWorld::setRegionRemovedCallback(const region_remove_signal_t::slot_type& cb) +{ + return mRegionRemovedSignal.connect(cb); +} LLHTTPRegistration<LLEstablishAgentCommunication> gHTTPRegistrationEstablishAgentCommunication( |