diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/llworld.cpp |
Print done when done.
Diffstat (limited to 'indra/newview/llworld.cpp')
-rw-r--r-- | indra/newview/llworld.cpp | 1141 |
1 files changed, 1141 insertions, 0 deletions
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp new file mode 100644 index 0000000000..813eb0c7ea --- /dev/null +++ b/indra/newview/llworld.cpp @@ -0,0 +1,1141 @@ +/** + * @file llworld.cpp + * @brief Initial test structure to organize viewer regions + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llworld.h" + +#include "indra_constants.h" + +#include "llagent.h" +#include "llviewercontrol.h" +#include "lldrawpool.h" +#include "llglheaders.h" +#include "llregionhandle.h" +#include "llsurface.h" +#include "llviewercamera.h" +#include "llviewerimage.h" +#include "llviewerimagelist.h" +#include "llviewernetwork.h" +#include "llviewerobjectlist.h" +#include "llviewerparceloverlay.h" +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llvlcomposition.h" +#include "llvoavatar.h" +#include "llvowater.h" +#include "message.h" +#include "pipeline.h" +#include "viewer.h" // for do_disconnect() + +// +// Globals +// +LLWorld* gWorldp = NULL; +U32 gAgentPauseSerialNum = 0; + +// +// Constants +// +const S32 MAX_NUMBER_OF_CLOUDS = 750; +const F32 MIN_IDLE_UPDATE_TIME = 0.025f; +const S32 WORLD_PATCH_SIZE = 16; + +extern LLColor4U MAX_WATER_COLOR; + +// +// Functions +// + +// allocate the stack +LLWorld::LLWorld(const U32 grids_per_region, const F32 meters_per_grid) +: mWidth(grids_per_region), + mScale(meters_per_grid), + mWidthInMeters( grids_per_region * meters_per_grid ) +{ + mSpaceTimeUSec = 0; + mLastPacketsIn = 0; + mLastPacketsOut = 0; + mLastPacketsLost = 0; + mLandFarClip = DEFAULT_FAR_PLANE; + mIdleUpdateTime = MIN_IDLE_UPDATE_TIME; + + if (gNoRender) + { + return; + } + + for (S32 i = 0; i < 8; i++) + { + mEdgeWaterObjects[i] = NULL; + } + + LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4); + U8 *default_texture = raw->getData(); + *(default_texture++) = MAX_WATER_COLOR.mV[0]; + *(default_texture++) = MAX_WATER_COLOR.mV[1]; + *(default_texture++) = MAX_WATER_COLOR.mV[2]; + *(default_texture++) = MAX_WATER_COLOR.mV[3]; + + mDefaultWaterTexturep = new LLViewerImage(raw, FALSE); + mDefaultWaterTexturep->bind(); + mDefaultWaterTexturep->setClamp(TRUE, TRUE); + +} + + +LLWorld::~LLWorld() +{ + gObjectList.killAllObjects(); + + mRegionList.deleteAllData(); +} + + +LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) +{ + LLMemType mt(LLMemType::MTYPE_REGIONS); + + LLViewerRegion *regionp = getRegionFromHandle(region_handle); + if (regionp) + { + LLHost old_host = regionp->getHost(); + // region already exists! + if (host == old_host && regionp->mAlive) + { + // This is a duplicate for the same host and it's alive, don't bother. + return regionp; + } + + if (host != old_host) + { + llwarns << "LLWorld::addRegion exists, but old host " << old_host + << " does not match new host " << host << llendl; + } + if (!regionp->mAlive) + { + llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl; + } + + // 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); + } + + 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; + + LLVector3d origin_global; + + origin_global = from_region_handle(region_handle); + + regionp = new LLViewerRegion(region_handle, + host, + mWidth, + WORLD_PATCH_SIZE, + getRegionWidthInMeters() ); + if (!regionp) + { + llerrs << "Unable to create new region!" << llendl; + } + + regionp->mCloudLayer.create(regionp); + regionp->mCloudLayer.setWidth((F32)mWidth); + regionp->mCloudLayer.setWindPointer(®ionp->mWind); + + mRegionList.addData(regionp); + mActiveRegionList.addData(regionp); + mCulledRegionList.addData(regionp); + + + // Find all the adjacent regions, and attach them. + // Generate handles for all of the adjacent regions, and attach them in the correct way. + // connect the edges + F32 adj_x = 0.f; + F32 adj_y = 0.f; + F32 region_x = 0.f; + F32 region_y = 0.f; + U64 adj_handle = 0; + + F32 width = getRegionWidthInMeters(); + + LLViewerRegion *neighborp; + from_region_handle(region_handle, ®ion_x, ®ion_y); + + // Iterate through all directions, and connect neighbors if there. + S32 dir; + for (dir = 0; dir < 8; dir++) + { + adj_x = region_x + width * gDirAxes[dir][0]; + adj_y = region_y + width * gDirAxes[dir][1]; + to_region_handle(adj_x, adj_y, &adj_handle); + + neighborp = getRegionFromHandle(adj_handle); + if (neighborp) + { + //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl; + regionp->connectNeighbor(neighborp, dir); + } + } + + updateWaterObjects(); + + return regionp; +} + + +void LLWorld::removeRegion(const LLHost &host) +{ + F32 x, y; + + LLViewerRegion *regionp = getRegion(host); + if (!regionp) + { + llwarns << "Trying to remove region that doesn't exist!" << llendl; + return; + } + + if (regionp == gAgent.getRegion()) + { + LLViewerRegion *reg; + for (reg = mRegionList.getFirstData(); reg; reg = mRegionList.getNextData()) + { + llwarns << "RegionDump: " << reg->getName() + << " " << reg->getHost() + << " " << reg->getOriginGlobal() + << llendl; + } + + llwarns << "Agent position global " << gAgent.getPositionGlobal() + << " agent " << gAgent.getPositionAgent() + << llendl; + + llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl; + + llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl; + + llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl; + do_disconnect("You have been disconnected from the region you were in."); + return; + } + + from_region_handle(regionp->getHandle(), &x, &y); + llinfos << "Removing region " << x << ":" << y << llendl; + + // This code can probably be blitzed now... + if (!mRegionList.removeData(regionp)) + { + for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) + { + llwarns << "RegionDump: " << regionp->getName() + << " " << regionp->getHost() + << " " << regionp->getOriginGlobal() + << llendl; + } + + llerrs << "Region list is broken" << llendl; + } + + if (!mActiveRegionList.removeData(regionp)) + { + llwarns << "LLWorld.mActiveRegionList is broken." << llendl; + } + if (!mCulledRegionList.removeData(regionp)) + { + if (!mVisibleRegionList.removeData(regionp)) + { + llwarns << "LLWorld.mCulled/mVisibleRegionList are broken" << llendl;; + } + } + delete regionp; + + updateWaterObjects(); +} + + +LLViewerRegion *LLWorld::getRegion(const LLHost &host) +{ + LLViewerRegion *regionp; + for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) + { + if (regionp->getHost() == host) + { + return regionp; + } + } + return NULL; +} + +LLViewerRegion *LLWorld::getRegionFromPosAgent(const LLVector3 &pos) +{ + return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos)); +} + +LLViewerRegion *LLWorld::getRegionFromPosGlobal(const LLVector3d &pos) +{ + LLViewerRegion *regionp; + for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) + { + if (regionp->pointInRegionGlobal(pos)) + { + return regionp; + } + } + return NULL; +} + + +LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) +{ + if (positionRegionValidGlobal(end_pos)) + { + return end_pos; + } + + LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); + if (!regionp) + { + return start_pos; + } + + LLVector3d delta_pos = end_pos - start_pos; + LLVector3d delta_pos_abs; + delta_pos_abs.setVec(delta_pos); + delta_pos_abs.abs(); + + LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); + F64 clip_factor = 1.0; + F32 region_width = regionp->getWidth(); + if (region_coord.mV[VX] < 0.f) + { + if (region_coord.mV[VY] < region_coord.mV[VX]) + { + // clip along y - + clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); + } + else + { + // clip along x - + clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); + } + } + else if (region_coord.mV[VX] > region_width) + { + if (region_coord.mV[VY] > region_coord.mV[VX]) + { + // clip along y + + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; + } + else + { + //clip along x + + clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; + } + } + else if (region_coord.mV[VY] < 0.f) + { + // clip along y - + clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); + } + else if (region_coord.mV[VY] > region_width) + { + // clip along y + + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; + } + + // clamp to < 256 to stay in sim + LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); + final_region_pos.clamp(0.0, 255.999); + return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); +} + +LLViewerRegion *LLWorld::getRegionFromHandle(const U64 &handle) +{ + LLViewerRegion *regionp; + for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) + { + if (regionp->getHandle() == handle) + { + return regionp; + } + } + return NULL; +} + + +void LLWorld::updateAgentOffset(const LLVector3d &offset_global) +{ +#if 0 + LLViewerRegion *regionp; + for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) + { + regionp->setAgentOffset(offset_global); + } +#endif +} + + +BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global) +{ + LLViewerRegion *regionp; + for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) + { + if (regionp->pointInRegionGlobal(pos_global)) + { + return TRUE; + } + } + return FALSE; +} + + +// Allow objects to go up to their radius underground. +F32 LLWorld::getMinAllowedZ(LLViewerObject* object) +{ + F32 land_height = resolveLandHeightGlobal(object->getPositionGlobal()); + F32 radius = 0.5f * object->getScale().magVec(); + return land_height - radius; +} + + +LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global) +{ + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + + if (regionp) + { + pos_region = regionp->getPosRegionFromGlobal(pos_global); + return regionp; + } + + return NULL; +} + + +LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent) +{ + LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + + if (regionp) + { + pos_region = regionp->getPosRegionFromGlobal(pos_global); + return regionp; + } + + return NULL; +} + + +F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent) +{ + LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); + return resolveLandHeightGlobal(pos_global); +} + + +F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global) +{ + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + if (regionp) + { + return regionp->getLand().resolveHeightGlobal(pos_global); + } + return 0.0f; +} + + +// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a) +// point where the the line intersects an object or the land surface. Stores the results +// in "intersection" and "intersection_normal" and returns a scalar value that represents +// the normalized distance along the line from "point_a" to "intersection". +// +// Currently assumes point_a and point_b only differ in z-direction, +// but it may eventually become more general. +F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b, + LLVector3d &intersection, LLVector3 &intersection_normal, + LLViewerObject **viewerObjectPtr) +{ + // initialize return value to null + if (viewerObjectPtr) + { + *viewerObjectPtr = NULL; + } + + LLViewerRegion *regionp = getRegionFromPosGlobal(point_a); + if (!regionp) + { + // We're outside the world + intersection = 0.5f * (point_a + point_b); + intersection_normal.setVec(0.0f, 0.0f, 1.0f); + return 0.5f; + } + + // calculate the length of the segment + F32 segment_length = (F32)((point_a - point_b).magVec()); + if (0.0f == segment_length) + { + intersection = point_a; + intersection_normal.setVec(0.0f, 0.0f, 1.0f); + return segment_length; + } + + // get land height + // Note: we assume that the line is parallel to z-axis here + LLVector3d land_intersection = point_a; + F32 normalized_land_distance; + + land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a); + normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length; + + if (avatarp && !avatarp->mFootPlane.isExactlyClear()) + { + LLVector3 foot_plane_normal(avatarp->mFootPlane.mV); + LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a); + // added 0.05 meters to compensate for error in foot plane reported by Havok + F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f; + norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f); + if (norm_dist_from_plane < normalized_land_distance) + { + normalized_land_distance = norm_dist_from_plane; + intersection = point_a; + intersection.mdV[VZ] -= norm_dist_from_plane * segment_length; + intersection_normal = foot_plane_normal; + } + } + else + { + intersection = land_intersection; + intersection_normal = resolveLandNormalGlobal(land_intersection); + } + + return normalized_land_distance; +} + + +LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global) +{ + // returns a pointer to the patch at this location + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + if (!regionp) + { + return NULL; + } + + return regionp->getLand().resolvePatchGlobal(pos_global); +} + + +LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global) +{ + LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); + if (!regionp) + { + return LLVector3::z_axis; + } + + return regionp->getLand().resolveNormalGlobal(pos_global); +} + + +void LLWorld::updateVisibilities() +{ + F32 cur_far_clip = gCamera->getFar(); + + gCamera->setFar(mLandFarClip); + + LLViewerRegion *regionp; + + F32 diagonal_squared = F_SQRT2 * F_SQRT2 * mWidth * mWidth; + // Go through the culled list and check for visible regions + for (regionp = mCulledRegionList.getFirstData(); + regionp; + regionp = mCulledRegionList.getNextData()) + { + F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); + F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); + if (!regionp->getLand().hasZData() + || gCamera->sphereInFrustum(regionp->getCenterAgent(), radius)) + { + mCulledRegionList.removeCurrentData(); + mVisibleRegionList.addDataAtEnd(regionp); + } + } + + F32 last_dist_squared = 0.0f; + F32 dist_squared; + + // Update all of the visible regions and make single bubble-sort pass + for (regionp = mVisibleRegionList.getFirstData(); + regionp; + regionp = mVisibleRegionList.getNextData()) + { + if (!regionp->getLand().hasZData()) + { + continue; + } + + F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); + F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); + if (gCamera->sphereInFrustum(regionp->getCenterAgent(), radius)) + { + if (!gNoRender) + { + regionp->getLand().updatePatchVisibilities(gAgent); + } + + // sort by distance... closer regions to the front + // Note: regions use absolute frame so we use the agent's center + dist_squared = (F32)(gAgent.getCameraPositionGlobal() - regionp->getCenterGlobal()).magVecSquared(); + if (dist_squared < last_dist_squared) + { + mVisibleRegionList.swapCurrentWithPrevious(); + } + else + { + last_dist_squared = dist_squared; + } + } + else + { + mVisibleRegionList.removeCurrentData(); + mCulledRegionList.addData(regionp); + } + } + + gCamera->setFar(cur_far_clip); +} + + +void LLWorld::updateRegions() +{ + LLViewerRegion *regionp; + LLTimer update_timer; + + // Perform idle time updates for the regions (and associated surfaces) + for (regionp = mRegionList.getFirstData(); + regionp; + regionp = mRegionList.getNextData()) + { + update_timer.reset(); + if (!regionp->idleUpdate(update_timer, mIdleUpdateTime)) + { + // Didn't finish all the updates. Slightly increase the idle update time. + mIdleUpdateTime *= 1.05f; + } + else + { + mIdleUpdateTime *= 0.9f; + if (mIdleUpdateTime < MIN_IDLE_UPDATE_TIME) + { + mIdleUpdateTime = MIN_IDLE_UPDATE_TIME; + } + } + } +} + +void LLWorld::updateParticles() +{ + mPartSim.updateSimulation(); +} + +void LLWorld::updateClouds(const F32 dt) +{ + if (gSavedSettings.getBOOL("FreezeTime")) + { + // don't move clouds in snapshot mode + return; + } + LLViewerRegion *regionp; + if (mActiveRegionList.getLength()) + { + // Update all the cloud puff positions, and timer based stuff + // such as death decay + for (regionp = mActiveRegionList.getFirstData(); + regionp; + regionp = mActiveRegionList.getNextData()) + { + regionp->mCloudLayer.updatePuffs(dt); + } + + // Reshuffle who owns which puffs + for (regionp = mActiveRegionList.getFirstData(); + regionp; + regionp = mActiveRegionList.getNextData()) + { + regionp->mCloudLayer.updatePuffOwnership(); + } + + // Add new puffs + for (regionp = mActiveRegionList.getFirstData(); + regionp; + regionp = mActiveRegionList.getNextData()) + { + regionp->mCloudLayer.updatePuffCount(); + } + } +} + +LLCloudGroup *LLWorld::findCloudGroup(const LLCloudPuff &puff) +{ + LLViewerRegion *regionp; + if (mActiveRegionList.getLength()) + { + // Update all the cloud puff positions, and timer based stuff + // such as death decay + for (regionp = mActiveRegionList.getFirstData(); + regionp; + regionp = mActiveRegionList.getNextData()) + { + LLCloudGroup *groupp = regionp->mCloudLayer.findCloudGroup(puff); + if (groupp) + { + return groupp; + } + } + } + return NULL; +} + + +void LLWorld::renderPropertyLines() +{ + S32 region_count = 0; + S32 vertex_count = 0; + + LLViewerRegion* region; + for (region = mVisibleRegionList.getFirstData(); region; region = mVisibleRegionList.getNextData() ) + { + region_count++; + vertex_count += region->renderPropertyLines(); + } +} + + +void LLWorld::updateNetStats() +{ + F32 bits = 0.f; + U32 packets = 0; + LLViewerRegion *regionp; + + for (regionp = mActiveRegionList.getFirstData(); regionp; regionp = mActiveRegionList.getNextData()) + { + regionp->updateNetStats(); + bits += regionp->mBitStat.getCurrent(); + packets += llfloor( regionp->mPacketsStat.getCurrent() ); + } + + 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(); + gViewerStats->mActualInKBitStat.addValue(actual_in_bits/1024.f); + gViewerStats->mActualOutKBitStat.addValue(actual_out_bits/1024.f); + gViewerStats->mKBitStat.addValue(bits/1024.f); + gViewerStats->mPacketsInStat.addValue(packets_in); + gViewerStats->mPacketsOutStat.addValue(packets_out); + gViewerStats->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets); + if (packets_in) + { + gViewerStats->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in)); + } + else + { + gViewerStats->mPacketsLostPercentStat.addValue(0.f); + } + + mLastPacketsIn = gMessageSystem->mPacketsIn; + mLastPacketsOut = gMessageSystem->mPacketsOut; + mLastPacketsLost = gMessageSystem->mDroppedPackets; +} + + +void LLWorld::printPacketsLost() +{ + LLViewerRegion *regionp; + + llinfos << "Simulators:" << llendl; + llinfos << "----------" << llendl; + + LLCircuitData *cdp = NULL; + for (regionp = mActiveRegionList.getFirstData(); + regionp; + regionp = mActiveRegionList.getNextData()) + { + cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost()); + if (cdp) + { + LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal(); + + llinfos << regionp->getHost() << ", range: " << range.magVec() << + " packets lost: " << + cdp->getPacketsLost() << llendl; + } + } + + llinfos << "UserServer:" << llendl; + llinfos << "-----------" << llendl; + + cdp = gMessageSystem->mCircuitInfo.findCircuit(gUserServer); + if (cdp) + { + llinfos << gUserServer << " packets lost: " << cdp->getPacketsLost() << llendl; + } +} + +void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data) +{ + LLViewerRegion* region = NULL; + region = gWorldp->getRegion(msg->getSender()); + if( region ) region->updateCoarseLocations(msg); +} + +F32 LLWorld::getLandFarClip() const +{ + return mLandFarClip; +} + +void LLWorld::setLandFarClip(const F32 far_clip) +{ + mLandFarClip = far_clip; +} + + +void LLWorld::updateWaterObjects() +{ + //llinfos << "Start water update" << llendl; + if (!gAgent.getRegion()) + { + return; + } + S32 min_x, min_y, max_x, max_y; + U32 region_x, region_y; + + S32 rwidth = llfloor(getRegionWidthInMeters()); + + // First, determine the min and max "box" of water objects + LLViewerRegion *regionp; + regionp = mRegionList.getFirstData(); + + if (!regionp) + { + llwarns << "No regions!" << llendl; + return; + } + + from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); + min_x = max_x = region_x; + min_y = max_y = region_y; + + LLVOWater *waterp; + + for (; regionp; regionp = mRegionList.getNextData()) + { + from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); + min_x = llmin(min_x, (S32)region_x); + min_y = llmin(min_y, (S32)region_y); + max_x = llmax(max_x, (S32)region_x); + max_y = llmax(max_y, (S32)region_y); + waterp = regionp->getLand().getWaterObj(); + if (waterp) + { + gObjectList.updateActive(waterp); + } + } + + for (waterp = mHoleWaterObjects.getFirstData(); waterp; waterp = mHoleWaterObjects.getNextData()) + { + gObjectList.killObject(waterp); + } + mHoleWaterObjects.removeAllNodes(); + + // We only want to fill in holes for stuff that's near us, say, within 512m + regionp = gAgent.getRegion(); + from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); + + min_x = llmax((S32)region_x - 512, min_x); + min_y = llmax((S32)region_y - 512, min_y); + max_x = llmin((S32)region_x + 512, max_x); + max_y = llmin((S32)region_y + 512, max_y); + + // Now, get a list of the holes + S32 x, y; + for (x = min_x; x <= max_x; x += rwidth) + { + for (y = min_y; y <= max_y; y += rwidth) + { + U64 region_handle = to_region_handle(x, y); + if (!getRegionFromHandle(region_handle)) + { + waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); + waterp->setUseTexture(FALSE); + gPipeline.addObject(waterp); + waterp->setPositionGlobal(LLVector3d(x + rwidth/2, + y + rwidth/2, + DEFAULT_WATER_HEIGHT)); + waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 0.f)); + mHoleWaterObjects.addData(waterp); + } + } + } + + // 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) }; + + + S32 dir; + for (dir = 0; dir < 8; dir++) + { + 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; + } + + if (dim[0] == 0 || dim[1] == 0) + { + continue; + } + + // Resize and reshape the water objects + const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]); + const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]); + + + 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_WATER, + gAgent.getRegion()); + waterp = mEdgeWaterObjects[dir]; + waterp->setUseTexture(FALSE); + gPipeline.addObject(waterp); + } + + waterp->setRegion(gAgent.getRegion()); + LLVector3d water_pos(water_center_x, water_center_y, + DEFAULT_WATER_HEIGHT); + waterp->setPositionGlobal(water_pos); + waterp->setScale(LLVector3((F32)dim[0], (F32)dim[1], 0.f)); + gObjectList.updateActive(waterp); + /*if (!gNoRender) + { + gPipeline.markMoved(waterp->mDrawable); + }*/ + } + + + //llinfos << "End water update" << llendl; +} + +LLViewerImage *LLWorld::getDefaultWaterTexture() +{ + return mDefaultWaterTexturep; +} + +void LLWorld::setSpaceTimeUSec(const U64 space_time_usec) +{ + mSpaceTimeUSec = space_time_usec; +} + +U64 LLWorld::getSpaceTimeUSec() const +{ + return mSpaceTimeUSec; +} + +void LLWorld::requestCacheMisses() +{ + for(LLViewerRegion* regionp = mRegionList.getFirstData(); + regionp; + regionp = mRegionList.getNextData()) + { + regionp->requestCacheMisses(); + } +} + +LLString LLWorld::getInfoString() +{ + LLString info_string("World Info:\n"); + for (LLViewerRegion* regionp = mRegionList.getFirstData(); + regionp; + regionp = mRegionList.getNextData()) + { + info_string += regionp->getInfoString(); + } + return info_string; +} + +void LLWorld::disconnectRegions() +{ + LLMessageSystem* msg = gMessageSystem; + for(LLViewerRegion* regionp = mRegionList.getFirstData(); + regionp; + regionp = mRegionList.getNextData()) + { + if (regionp == gAgent.getRegion()) + { + // Skip the main agent + continue; + } + + llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl; + msg->newMessageFast(_PREHASH_AgentQuitCopy); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_FuseBlock); + msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode); + msg->sendMessage(regionp->getHost()); + } +} + + +void process_enable_simulator(LLMessageSystem *msg, void **user_data) +{ + // enable the appropriate circuit for this simulator and + // add its values into the gSimulator structure + U64 handle; + U32 ip_u32; + U16 port; + + msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle); + msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32); + msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port); + + // which simulator should we modify? + LLHost sim(ip_u32, port); + + // Viewer trusts the simulator. + msg->enableCircuit(sim, TRUE); + gWorldp->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; + msg->newMessageFast(_PREHASH_UseCircuitCode); + msg->nextBlockFast(_PREHASH_CircuitCode); + msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); + msg->sendReliable(sim); +} + + +// disable the circuit to this simulator +// Called in response to "DisableSimulator" message. +void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data) +{ + LLHost host = mesgsys->getSender(); + + //llinfos << "Disabling simulator with message from " << host << llendl; + gWorldp->removeRegion(host); + + mesgsys->disableCircuit(host); +} + + +void process_region_handshake(LLMessageSystem* msg, void** user_data) +{ + LLHost host = msg->getSender(); + LLViewerRegion* regionp = gWorldp->getRegion(host); + if (!regionp) + { + llwarns << "Got region handshake for unknown region " + << host << llendl; + return; + } + + regionp->unpackRegionHandshake(); +} + + +void send_agent_pause() +{ + // world not initialized yet + if (!gWorldp) return; + + gMessageSystem->newMessageFast(_PREHASH_AgentPause); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + + gAgentPauseSerialNum++; + gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); + + LLViewerRegion *regionp; + for (regionp = gWorldp->mActiveRegionList.getFirstData(); + regionp; + regionp = gWorldp->mActiveRegionList.getNextData()) + { + gMessageSystem->sendReliable(regionp->getHost()); + } + + gMessageSystem->sendReliable(gUserServer); + + gObjectList.mWasPaused = TRUE; +} + + +void send_agent_resume() +{ + // world not initialized yet + if (!gWorldp) return; + + gMessageSystem->newMessageFast(_PREHASH_AgentResume); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + + gAgentPauseSerialNum++; + gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); + + + LLViewerRegion *regionp; + for (regionp = gWorldp->mActiveRegionList.getFirstData(); + regionp; + regionp = gWorldp->mActiveRegionList.getNextData()) + { + gMessageSystem->sendReliable(regionp->getHost()); + } + + gMessageSystem->sendReliable(gUserServer); + + // Reset the FPS counter to avoid an invalid fps + gViewerStats->mFPSStat.start(); +} + + |