llworld.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llworld.h"
00035 
00036 #include "indra_constants.h"
00037 #include "llstl.h"
00038 
00039 #include "llagent.h"
00040 #include "llviewercontrol.h"
00041 #include "lldrawpool.h"
00042 #include "llglheaders.h"
00043 #include "llhttpnode.h"
00044 #include "llregionhandle.h"
00045 #include "llsurface.h"
00046 #include "llviewercamera.h"
00047 #include "llviewerimage.h"
00048 #include "llviewerimagelist.h"
00049 #include "llviewernetwork.h"
00050 #include "llviewerobjectlist.h"
00051 #include "llviewerparceloverlay.h"
00052 #include "llviewerregion.h"
00053 #include "llviewerstats.h"
00054 #include "llvlcomposition.h"
00055 #include "llvoavatar.h"
00056 #include "llvowater.h"
00057 #include "message.h"
00058 #include "pipeline.h"
00059 #include "llappviewer.h"                // for do_disconnect()
00060 
00061 //
00062 // Globals
00063 //
00064 U32                     gAgentPauseSerialNum = 0;
00065 
00066 //
00067 // Constants
00068 //
00069 const S32 MAX_NUMBER_OF_CLOUDS  = 750;
00070 const S32 WORLD_PATCH_SIZE = 16;
00071 
00072 extern LLColor4U MAX_WATER_COLOR;
00073 
00074 const U32 LLWorld::mWidth = 256;
00075 
00076 // meters/point, therefore mWidth * mScale = meters per edge
00077 const F32 LLWorld::mScale = 1.f;
00078 
00079 const F32 LLWorld::mWidthInMeters = mWidth * mScale;
00080 
00081 //
00082 // Functions
00083 //
00084 
00085 // allocate the stack
00086 LLWorld::LLWorld() :
00087         mLandFarClip(DEFAULT_FAR_PLANE),
00088         mLastPacketsIn(0),
00089         mLastPacketsOut(0),
00090         mLastPacketsLost(0),
00091         mMinRegionX(0),
00092         mMaxRegionX(0),
00093         mMinRegionY(0),
00094         mMaxRegionY(0),
00095         mSpaceTimeUSec(0)
00096 {
00097         for (S32 i = 0; i < 8; i++)
00098         {
00099                 mEdgeWaterObjects[i] = NULL;
00100         }
00101 
00102         if (gNoRender)
00103         {
00104                 return;
00105         }
00106 
00107         LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4);
00108         U8 *default_texture = raw->getData();
00109         *(default_texture++) = MAX_WATER_COLOR.mV[0];
00110         *(default_texture++) = MAX_WATER_COLOR.mV[1];
00111         *(default_texture++) = MAX_WATER_COLOR.mV[2];
00112         *(default_texture++) = MAX_WATER_COLOR.mV[3];
00113         
00114         mDefaultWaterTexturep = new LLViewerImage(raw, FALSE);
00115         mDefaultWaterTexturep->bind();
00116         mDefaultWaterTexturep->setClamp(TRUE, TRUE);
00117 
00118 }
00119 
00120 
00121 void LLWorld::destroyClass()
00122 {
00123         gObjectList.destroy();
00124         for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
00125         {
00126                 LLViewerRegion* region_to_delete = *region_it++;
00127                 removeRegion(region_to_delete->getHost());
00128         }
00129         LLViewerPartSim::getInstance()->destroyClass();
00130 }
00131 
00132 
00133 LLViewerRegion* LLWorld::addRegion(const U64 &region_handle, const LLHost &host)
00134 {
00135         LLMemType mt(LLMemType::MTYPE_REGIONS);
00136         
00137         LLViewerRegion *regionp = getRegionFromHandle(region_handle);
00138         if (regionp)
00139         {
00140                 LLHost old_host = regionp->getHost();
00141                 // region already exists!
00142                 if (host == old_host && regionp->mAlive)
00143                 {
00144                         // This is a duplicate for the same host and it's alive, don't bother.
00145                         return regionp;
00146                 }
00147 
00148                 if (host != old_host)
00149                 {
00150                         llwarns << "LLWorld::addRegion exists, but old host " << old_host
00151                                         << " does not match new host " << host << llendl;
00152                 }
00153                 if (!regionp->mAlive)
00154                 {
00155                         llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl;
00156                 }
00157 
00158                 // Kill the old host, and then we can continue on and add the new host.  We have to kill even if the host
00159                 // matches, because all the agent state for the new camera is completely different.
00160                 removeRegion(old_host);
00161         }
00162 
00163         U32 iindex = 0;
00164         U32 jindex = 0;
00165         from_region_handle(region_handle, &iindex, &jindex);
00166         S32 x = (S32)(iindex/mWidth);
00167         S32 y = (S32)(jindex/mWidth);
00168         llinfos << "Adding new region (" << x << ":" << y << ")" << llendl;
00169         llinfos << "Host: " << host << llendl;
00170 
00171         LLVector3d origin_global;
00172 
00173         origin_global = from_region_handle(region_handle);
00174 
00175         regionp = new LLViewerRegion(region_handle,
00176                                                                     host,
00177                                                                         mWidth,
00178                                                                         WORLD_PATCH_SIZE,
00179                                                                         getRegionWidthInMeters() );
00180         if (!regionp)
00181         {
00182                 llerrs << "Unable to create new region!" << llendl;
00183         }
00184 
00185         regionp->mCloudLayer.create(regionp);
00186         regionp->mCloudLayer.setWidth((F32)mWidth);
00187         regionp->mCloudLayer.setWindPointer(&regionp->mWind);
00188 
00189         mRegionList.push_back(regionp);
00190         mActiveRegionList.push_back(regionp);
00191         mCulledRegionList.push_back(regionp);
00192 
00193 
00194         // Find all the adjacent regions, and attach them.
00195         // Generate handles for all of the adjacent regions, and attach them in the correct way.
00196         // connect the edges
00197         F32 adj_x = 0.f;
00198         F32 adj_y = 0.f;
00199         F32 region_x = 0.f;
00200         F32 region_y = 0.f;
00201         U64 adj_handle = 0;
00202 
00203         F32 width = getRegionWidthInMeters();
00204 
00205         LLViewerRegion *neighborp;
00206         from_region_handle(region_handle, &region_x, &region_y);
00207 
00208         // Iterate through all directions, and connect neighbors if there.
00209         S32 dir;
00210         for (dir = 0; dir < 8; dir++)
00211         {
00212                 adj_x = region_x + width * gDirAxes[dir][0];
00213                 adj_y = region_y + width * gDirAxes[dir][1];
00214                 to_region_handle(adj_x, adj_y, &adj_handle);
00215 
00216                 neighborp = getRegionFromHandle(adj_handle);
00217                 if (neighborp)
00218                 {
00219                         //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl;
00220                         regionp->connectNeighbor(neighborp, dir);
00221                 }
00222         }
00223 
00224         updateWaterObjects();
00225 
00226         return regionp;
00227 }
00228 
00229 
00230 void LLWorld::removeRegion(const LLHost &host)
00231 {
00232         F32 x, y;
00233 
00234         LLViewerRegion *regionp = getRegion(host);
00235         if (!regionp)
00236         {
00237                 llwarns << "Trying to remove region that doesn't exist!" << llendl;
00238                 return;
00239         }
00240         
00241         if (regionp == gAgent.getRegion())
00242         {
00243                 for (region_list_t::iterator iter = mRegionList.begin();
00244                          iter != mRegionList.end(); ++iter)
00245                 {
00246                         LLViewerRegion* reg = *iter;
00247                         llwarns << "RegionDump: " << reg->getName()
00248                                 << " " << reg->getHost()
00249                                 << " " << reg->getOriginGlobal()
00250                                 << llendl;
00251                 }
00252 
00253                 llwarns << "Agent position global " << gAgent.getPositionGlobal() 
00254                         << " agent " << gAgent.getPositionAgent()
00255                         << llendl;
00256 
00257                 llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl;
00258 
00259                 llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl;
00260 
00261                 llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl;
00262                 LLAppViewer::instance()->forceDisconnect("You have been disconnected from the region you were in.");
00263                 return;
00264         }
00265 
00266         from_region_handle(regionp->getHandle(), &x, &y);
00267         llinfos << "Removing region " << x << ":" << y << llendl;
00268 
00269         mRegionList.remove(regionp);
00270         mActiveRegionList.remove(regionp);
00271         mCulledRegionList.remove(regionp);
00272         mVisibleRegionList.remove(regionp);
00273         
00274         delete regionp;
00275 
00276         updateWaterObjects();
00277 }
00278 
00279 
00280 LLViewerRegion* LLWorld::getRegion(const LLHost &host)
00281 {
00282         for (region_list_t::iterator iter = mRegionList.begin();
00283                  iter != mRegionList.end(); ++iter)
00284         {
00285                 LLViewerRegion* regionp = *iter;
00286                 if (regionp->getHost() == host)
00287                 {
00288                         return regionp;
00289                 }
00290         }
00291         return NULL;
00292 }
00293 
00294 LLViewerRegion* LLWorld::getRegionFromPosAgent(const LLVector3 &pos)
00295 {
00296         return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos));
00297 }
00298 
00299 LLViewerRegion* LLWorld::getRegionFromPosGlobal(const LLVector3d &pos)
00300 {
00301         for (region_list_t::iterator iter = mRegionList.begin();
00302                  iter != mRegionList.end(); ++iter)
00303         {
00304                 LLViewerRegion* regionp = *iter;
00305                 if (regionp->pointInRegionGlobal(pos))
00306                 {
00307                         return regionp;
00308                 }
00309         }
00310         return NULL;
00311 }
00312 
00313 
00314 LLVector3d      LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos)
00315 {
00316         if (positionRegionValidGlobal(end_pos))
00317         {
00318                 return end_pos;
00319         }
00320 
00321         LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos);
00322         if (!regionp) 
00323         {
00324                 return start_pos;
00325         }
00326 
00327         LLVector3d delta_pos = end_pos - start_pos;
00328         LLVector3d delta_pos_abs;
00329         delta_pos_abs.setVec(delta_pos);
00330         delta_pos_abs.abs();
00331 
00332         LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos);
00333         F64 clip_factor = 1.0;
00334         F32 region_width = regionp->getWidth();
00335         if (region_coord.mV[VX] < 0.f)
00336         {
00337                 if (region_coord.mV[VY] < region_coord.mV[VX])
00338                 {
00339                         // clip along y -
00340                         clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
00341                 }
00342                 else
00343                 {
00344                         // clip along x -
00345                         clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]);
00346                 }
00347         }
00348         else if (region_coord.mV[VX] > region_width)
00349         {
00350                 if (region_coord.mV[VY] > region_coord.mV[VX])
00351                 {
00352                         // clip along y +
00353                         clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
00354                 }
00355                 else
00356                 {
00357                         //clip along x +
00358                         clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX];
00359                 }
00360         }
00361         else if (region_coord.mV[VY] < 0.f)
00362         {
00363                 // clip along y -
00364                 clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
00365         }
00366         else if (region_coord.mV[VY] > region_width)
00367         { 
00368                 // clip along y +
00369                 clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
00370         }
00371 
00372         // clamp to < 256 to stay in sim
00373         LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor);
00374         final_region_pos.clamp(0.0, 255.999);
00375         return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos));
00376 }
00377 
00378 LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle)
00379 {
00380         for (region_list_t::iterator iter = mRegionList.begin();
00381                  iter != mRegionList.end(); ++iter)
00382         {
00383                 LLViewerRegion* regionp = *iter;
00384                 if (regionp->getHandle() == handle)
00385                 {
00386                         return regionp;
00387                 }
00388         }
00389         return NULL;
00390 }
00391 
00392 
00393 void LLWorld::updateAgentOffset(const LLVector3d &offset_global)
00394 {
00395 #if 0
00396         for (region_list_t::iterator iter = mRegionList.begin();
00397                  iter != mRegionList.end(); ++iter)
00398         {
00399                 LLViewerRegion* regionp = *iter;
00400                 regionp->setAgentOffset(offset_global);
00401         }
00402 #endif
00403 }
00404 
00405 
00406 BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global)
00407 {
00408         for (region_list_t::iterator iter = mRegionList.begin();
00409                  iter != mRegionList.end(); ++iter)
00410         {
00411                 LLViewerRegion* regionp = *iter;
00412                 if (regionp->pointInRegionGlobal(pos_global))
00413                 {
00414                         return TRUE;
00415                 }
00416         }
00417         return FALSE;
00418 }
00419 
00420 
00421 // Allow objects to go up to their radius underground.
00422 F32 LLWorld::getMinAllowedZ(LLViewerObject* object)
00423 {
00424         F32 land_height = resolveLandHeightGlobal(object->getPositionGlobal());
00425         F32 radius = 0.5f * object->getScale().magVec();
00426         return land_height - radius;
00427 }
00428 
00429 
00430 LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global)
00431 {
00432         LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
00433 
00434         if (regionp)
00435         {
00436                 pos_region = regionp->getPosRegionFromGlobal(pos_global);
00437                 return regionp;
00438         }
00439 
00440         return NULL;
00441 }
00442 
00443 
00444 LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent)
00445 {
00446         LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
00447         LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
00448 
00449         if (regionp)
00450         {
00451                 pos_region = regionp->getPosRegionFromGlobal(pos_global);
00452                 return regionp;
00453         }
00454 
00455         return NULL;
00456 }
00457 
00458 
00459 F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent)
00460 {
00461         LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
00462         return resolveLandHeightGlobal(pos_global);
00463 }
00464 
00465 
00466 F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global)
00467 {
00468         LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
00469         if (regionp)
00470         {
00471                 return regionp->getLand().resolveHeightGlobal(pos_global);
00472         }
00473         return 0.0f;
00474 }
00475 
00476 
00477 // Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a) 
00478 // point where the the line intersects an object or the land surface.  Stores the results
00479 // in "intersection" and "intersection_normal" and returns a scalar value that represents
00480 // the normalized distance along the line from "point_a" to "intersection".
00481 //
00482 // Currently assumes point_a and point_b only differ in z-direction, 
00483 // but it may eventually become more general.
00484 F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b, 
00485                                                            LLVector3d &intersection, LLVector3 &intersection_normal,
00486                                                            LLViewerObject **viewerObjectPtr)
00487 {
00488         // initialize return value to null
00489         if (viewerObjectPtr)
00490         {
00491                 *viewerObjectPtr = NULL;
00492         }
00493 
00494         LLViewerRegion *regionp = getRegionFromPosGlobal(point_a);
00495         if (!regionp)
00496         {
00497                 // We're outside the world 
00498                 intersection = 0.5f * (point_a + point_b);
00499                 intersection_normal.setVec(0.0f, 0.0f, 1.0f);
00500                 return 0.5f;
00501         }
00502         
00503         // calculate the length of the segment
00504         F32 segment_length = (F32)((point_a - point_b).magVec());
00505         if (0.0f == segment_length)
00506         {
00507                 intersection = point_a;
00508                 intersection_normal.setVec(0.0f, 0.0f, 1.0f);
00509                 return segment_length;
00510         }
00511 
00512         // get land height      
00513         // Note: we assume that the line is parallel to z-axis here
00514         LLVector3d land_intersection = point_a;
00515         F32 normalized_land_distance;
00516 
00517         land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a);
00518         normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length;
00519         intersection = land_intersection;
00520         intersection_normal = resolveLandNormalGlobal(land_intersection);
00521 
00522         if (avatarp && !avatarp->mFootPlane.isExactlyClear())
00523         {
00524                 LLVector3 foot_plane_normal(avatarp->mFootPlane.mV);
00525                 LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a);
00526                 // added 0.05 meters to compensate for error in foot plane reported by Havok
00527                 F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f;
00528                 norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f);
00529                 if (norm_dist_from_plane < normalized_land_distance)
00530                 {
00531                         // collided with object before land
00532                         normalized_land_distance = norm_dist_from_plane;
00533                         intersection = point_a;
00534                         intersection.mdV[VZ] -= norm_dist_from_plane * segment_length;
00535                         intersection_normal = foot_plane_normal;
00536                 }
00537                 else
00538                 {
00539                         intersection = land_intersection;
00540                         intersection_normal = resolveLandNormalGlobal(land_intersection);
00541                 }
00542         }
00543 
00544         return normalized_land_distance;
00545 }
00546 
00547 
00548 LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global)
00549 {
00550         //  returns a pointer to the patch at this location
00551         LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
00552         if (!regionp)
00553         {
00554                 return NULL;
00555         }
00556 
00557         return regionp->getLand().resolvePatchGlobal(pos_global);
00558 }
00559 
00560 
00561 LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global)
00562 {
00563         LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
00564         if (!regionp)
00565         {
00566                 return LLVector3::z_axis;
00567         }
00568 
00569         return regionp->getLand().resolveNormalGlobal(pos_global);
00570 }
00571 
00572 
00573 void LLWorld::updateVisibilities()
00574 {
00575         F32 cur_far_clip = LLViewerCamera::getInstance()->getFar();
00576 
00577         LLViewerCamera::getInstance()->setFar(mLandFarClip);
00578 
00579         F32 diagonal_squared = F_SQRT2 * F_SQRT2 * mWidth * mWidth;
00580         // Go through the culled list and check for visible regions
00581         for (region_list_t::iterator iter = mCulledRegionList.begin();
00582                  iter != mCulledRegionList.end(); )
00583         {
00584                 region_list_t::iterator curiter = iter++;
00585                 LLViewerRegion* regionp = *curiter;
00586                 F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ();
00587                 F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared);
00588                 if (!regionp->getLand().hasZData()
00589                         || LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius))
00590                 {
00591                         mCulledRegionList.erase(curiter);
00592                         mVisibleRegionList.push_back(regionp);
00593                 }
00594         }
00595         
00596         // Update all of the visible regions 
00597         for (region_list_t::iterator iter = mVisibleRegionList.begin();
00598                  iter != mVisibleRegionList.end(); )
00599         {
00600                 region_list_t::iterator curiter = iter++;
00601                 LLViewerRegion* regionp = *curiter;
00602                 if (!regionp->getLand().hasZData())
00603                 {
00604                         continue;
00605                 }
00606 
00607                 F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ();
00608                 F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared);
00609                 if (LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius))
00610                 {
00611                         regionp->calculateCameraDistance();
00612                         if (!gNoRender)
00613                         {
00614                                 regionp->getLand().updatePatchVisibilities(gAgent);
00615                         }
00616                 }
00617                 else
00618                 {
00619                         mVisibleRegionList.erase(curiter);
00620                         mCulledRegionList.push_back(regionp);
00621                 }
00622         }
00623 
00624         // Sort visible regions
00625         mVisibleRegionList.sort(LLViewerRegion::CompareDistance());
00626         
00627         LLViewerCamera::getInstance()->setFar(cur_far_clip);
00628 }
00629 
00630 void LLWorld::updateRegions(F32 max_update_time)
00631 {
00632         LLTimer update_timer;
00633         BOOL did_one = FALSE;
00634         
00635         // Perform idle time updates for the regions (and associated surfaces)
00636         for (region_list_t::iterator iter = mRegionList.begin();
00637                  iter != mRegionList.end(); ++iter)
00638         {
00639                 LLViewerRegion* regionp = *iter;
00640                 F32 max_time = max_update_time - update_timer.getElapsedTimeF32();
00641                 if (did_one && max_time <= 0.f)
00642                         break;
00643                 max_time = llmin(max_time, max_update_time*.1f);
00644                 did_one |= regionp->idleUpdate(max_update_time);
00645         }
00646 }
00647 
00648 void LLWorld::updateParticles()
00649 {
00650         LLViewerPartSim::getInstance()->updateSimulation();
00651 }
00652 
00653 void LLWorld::updateClouds(const F32 dt)
00654 {
00655         if (gSavedSettings.getBOOL("FreezeTime") ||
00656                 !gSavedSettings.getBOOL("SkyUseClassicClouds"))
00657         {
00658                 // don't move clouds in snapshot mode
00659                 return;
00660         }
00661         if (mActiveRegionList.size())
00662         {
00663                 // Update all the cloud puff positions, and timer based stuff
00664                 // such as death decay
00665                 for (region_list_t::iterator iter = mActiveRegionList.begin();
00666                          iter != mActiveRegionList.end(); ++iter)
00667                 {
00668                         LLViewerRegion* regionp = *iter;
00669                         regionp->mCloudLayer.updatePuffs(dt);
00670                 }
00671 
00672                 // Reshuffle who owns which puffs
00673                 for (region_list_t::iterator iter = mActiveRegionList.begin();
00674                          iter != mActiveRegionList.end(); ++iter)
00675                 {
00676                         LLViewerRegion* regionp = *iter;
00677                         regionp->mCloudLayer.updatePuffOwnership();
00678                 }
00679 
00680                 // Add new puffs
00681                 for (region_list_t::iterator iter = mActiveRegionList.begin();
00682                          iter != mActiveRegionList.end(); ++iter)
00683                 {
00684                         LLViewerRegion* regionp = *iter;
00685                         regionp->mCloudLayer.updatePuffCount();
00686                 }
00687         }
00688 }
00689 
00690 LLCloudGroup* LLWorld::findCloudGroup(const LLCloudPuff &puff)
00691 {
00692         if (mActiveRegionList.size())
00693         {
00694                 // Update all the cloud puff positions, and timer based stuff
00695                 // such as death decay
00696                 for (region_list_t::iterator iter = mActiveRegionList.begin();
00697                          iter != mActiveRegionList.end(); ++iter)
00698                 {
00699                         LLViewerRegion* regionp = *iter;
00700                         LLCloudGroup *groupp = regionp->mCloudLayer.findCloudGroup(puff);
00701                         if (groupp)
00702                         {
00703                                 return groupp;
00704                         }
00705                 }
00706         }
00707         return NULL;
00708 }
00709 
00710 
00711 void LLWorld::renderPropertyLines()
00712 {
00713         S32 region_count = 0;
00714         S32 vertex_count = 0;
00715 
00716         for (region_list_t::iterator iter = mVisibleRegionList.begin();
00717                  iter != mVisibleRegionList.end(); ++iter)
00718         {
00719                 LLViewerRegion* regionp = *iter;
00720                 region_count++;
00721                 vertex_count += regionp->renderPropertyLines();
00722         }
00723 }
00724 
00725 
00726 void LLWorld::updateNetStats()
00727 {
00728         F32 bits = 0.f;
00729         U32 packets = 0;
00730 
00731         for (region_list_t::iterator iter = mActiveRegionList.begin();
00732                  iter != mActiveRegionList.end(); ++iter)
00733         {
00734                 LLViewerRegion* regionp = *iter;
00735                 regionp->updateNetStats();
00736                 bits += regionp->mBitStat.getCurrent();
00737                 packets += llfloor( regionp->mPacketsStat.getCurrent() );
00738         }
00739 
00740         S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn;
00741         S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut;
00742         S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost;
00743 
00744         S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits();
00745         S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits();
00746         LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f);
00747         LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f);
00748         LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f);
00749         LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in);
00750         LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out);
00751         LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets);
00752         if (packets_in)
00753         {
00754                 LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in));
00755         }
00756         else
00757         {
00758                 LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f);
00759         }
00760 
00761         mLastPacketsIn = gMessageSystem->mPacketsIn;
00762         mLastPacketsOut = gMessageSystem->mPacketsOut;
00763         mLastPacketsLost = gMessageSystem->mDroppedPackets;
00764 }
00765 
00766 
00767 void LLWorld::printPacketsLost()
00768 {
00769         llinfos << "Simulators:" << llendl;
00770         llinfos << "----------" << llendl;
00771 
00772         LLCircuitData *cdp = NULL;
00773         for (region_list_t::iterator iter = mActiveRegionList.begin();
00774                  iter != mActiveRegionList.end(); ++iter)
00775         {
00776                 LLViewerRegion* regionp = *iter;
00777                 cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost());
00778                 if (cdp)
00779                 {
00780                         LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal();
00781                                 
00782                         llinfos << regionp->getHost() << ", range: " << range.magVec()
00783                                         << " packets lost: " << cdp->getPacketsLost() << llendl;
00784                 }
00785         }
00786 }
00787 
00788 void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data)
00789 {
00790         LLViewerRegion* region = LLWorld::getInstance()->getRegion(msg->getSender());
00791         if( region )
00792         {
00793                 region->updateCoarseLocations(msg);
00794         }
00795 }
00796 
00797 F32 LLWorld::getLandFarClip() const
00798 {
00799         return mLandFarClip;
00800 }
00801 
00802 void LLWorld::setLandFarClip(const F32 far_clip)
00803 {
00804         mLandFarClip = far_clip;
00805 }
00806 
00807 
00808 void LLWorld::updateWaterObjects()
00809 {
00810         if (!gAgent.getRegion())
00811         {
00812                 return;
00813         }
00814         if (mRegionList.empty())
00815         {
00816                 llwarns << "No regions!" << llendl;
00817                 return;
00818         }
00819 
00820         // First, determine the min and max "box" of water objects
00821         S32 min_x = 0;
00822         S32 min_y = 0;
00823         S32 max_x = 0;
00824         S32 max_y = 0;
00825         U32 region_x, region_y;
00826 
00827         S32 rwidth = 256;
00828 
00829         // We only want to fill in water for stuff that's near us, say, within 256 or 512m
00830         S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256;
00831 
00832         LLViewerRegion* regionp = gAgent.getRegion();
00833         from_region_handle(regionp->getHandle(), &region_x, &region_y);
00834 
00835         min_x = (S32)region_x - range;
00836         min_y = (S32)region_y - range;
00837         max_x = (S32)region_x + range;
00838         max_y = (S32)region_y + range;
00839 
00840         F32 height = 0.f;
00841         
00842         for (region_list_t::iterator iter = mRegionList.begin();
00843                  iter != mRegionList.end(); ++iter)
00844         {
00845                 LLViewerRegion* regionp = *iter;
00846                 LLVOWater* waterp = regionp->getLand().getWaterObj();
00847                 height += regionp->getWaterHeight();
00848                 if (waterp)
00849                 {
00850                         gObjectList.updateActive(waterp);
00851                 }
00852         }
00853 
00854         for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin();
00855                  iter != mHoleWaterObjects.end(); ++ iter)
00856         {
00857                 LLVOWater* waterp = *iter;
00858                 gObjectList.killObject(waterp);
00859         }
00860         mHoleWaterObjects.clear();
00861 
00862         // Now, get a list of the holes
00863         S32 x, y;
00864         for (x = min_x; x <= max_x; x += rwidth)
00865         {
00866                 for (y = min_y; y <= max_y; y += rwidth)
00867                 {
00868                         U64 region_handle = to_region_handle(x, y);
00869                         if (!getRegionFromHandle(region_handle))
00870                         {
00871                                 LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
00872                                 waterp->setUseTexture(FALSE);
00873                                 waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
00874                                                                                                          y + rwidth/2,
00875                                                                                                          256.f+DEFAULT_WATER_HEIGHT));
00876                                 waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
00877                                 gPipeline.addObject(waterp);
00878                                 mHoleWaterObjects.push_back(waterp);
00879                         }
00880                 }
00881         }
00882 
00883         // Update edge water objects
00884         S32 wx, wy;
00885         S32 center_x, center_y;
00886         wx = (max_x - min_x) + rwidth;
00887         wy = (max_y - min_y) + rwidth;
00888         center_x = min_x + (wx >> 1);
00889         center_y = min_y + (wy >> 1);
00890 
00891         S32 add_boundary[4] = {
00892                 512 - (max_x - region_x),
00893                 512 - (max_y - region_y),
00894                 512 - (region_x - min_x),
00895                 512 - (region_y - min_y) };
00896                 
00897         S32 dir;
00898         for (dir = 0; dir < 8; dir++)
00899         {
00900                 S32 dim[2] = { 0 };
00901                 switch (gDirAxes[dir][0])
00902                 {
00903                 case -1: dim[0] = add_boundary[2]; break;
00904                 case  0: dim[0] = wx; break;
00905                 default: dim[0] = add_boundary[0]; break;
00906                 }
00907                 switch (gDirAxes[dir][1])
00908                 {
00909                 case -1: dim[1] = add_boundary[3]; break;
00910                 case  0: dim[1] = wy; break;
00911                 default: dim[1] = add_boundary[1]; break;
00912                 }
00913 
00914                 // Resize and reshape the water objects
00915                 const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
00916                 const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
00917                 
00918                 LLVOWater* waterp = mEdgeWaterObjects[dir];
00919                 if (!waterp || waterp->isDead())
00920                 {
00921                         // The edge water objects can be dead because they're attached to the region that the
00922                         // agent was in when they were originally created.
00923                         mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER,
00924                                                                                                                                                                  gAgent.getRegion());
00925                         waterp = mEdgeWaterObjects[dir];
00926                         waterp->setUseTexture(FALSE);
00927                         waterp->setIsEdgePatch(TRUE);
00928                         gPipeline.addObject(waterp);
00929                 }
00930 
00931                 waterp->setRegion(gAgent.getRegion());
00932                 LLVector3d water_pos(water_center_x, water_center_y, 
00933                         DEFAULT_WATER_HEIGHT+256.f);
00934                 LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
00935 
00936                 //stretch out to horizon
00937                 water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]);
00938                 water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]);
00939 
00940                 water_pos.mdV[0] += 1024.f * gDirAxes[dir][0];
00941                 water_pos.mdV[1] += 1024.f * gDirAxes[dir][1];
00942 
00943                 waterp->setPositionGlobal(water_pos);
00944                 waterp->setScale(water_scale);
00945 
00946                 gObjectList.updateActive(waterp);
00947         }
00948 }
00949 
00950 void LLWorld::shiftRegions(const LLVector3& offset)
00951 {
00952         for (region_list_t::iterator i = getRegionList().begin(); i != getRegionList().end(); ++i)
00953         {
00954                 LLViewerRegion* region = *i;
00955                 region->updateRenderMatrix();
00956         }
00957 
00958         LLViewerPartSim::getInstance()->shift(offset);
00959 }
00960 
00961 LLViewerImage* LLWorld::getDefaultWaterTexture()
00962 {
00963         return mDefaultWaterTexturep;
00964 }
00965 
00966 void LLWorld::setSpaceTimeUSec(const U64 space_time_usec)
00967 {
00968         mSpaceTimeUSec = space_time_usec;
00969 }
00970 
00971 U64 LLWorld::getSpaceTimeUSec() const
00972 {
00973         return mSpaceTimeUSec;
00974 }
00975 
00976 void LLWorld::requestCacheMisses()
00977 {
00978         for (region_list_t::iterator iter = mRegionList.begin();
00979                  iter != mRegionList.end(); ++iter)
00980         {
00981                 LLViewerRegion* regionp = *iter;
00982                 regionp->requestCacheMisses();
00983         }
00984 }
00985 
00986 void LLWorld::getInfo(LLSD& info)
00987 {
00988         LLSD region_info;
00989         for (region_list_t::iterator iter = mRegionList.begin();
00990                  iter != mRegionList.end(); ++iter)
00991         {       
00992                 LLViewerRegion* regionp = *iter;
00993                 regionp->getInfo(region_info);
00994                 info["World"].append(region_info);
00995         }
00996 }
00997 
00998 void LLWorld::disconnectRegions()
00999 {
01000         LLMessageSystem* msg = gMessageSystem;
01001         for (region_list_t::iterator iter = mRegionList.begin();
01002                  iter != mRegionList.end(); ++iter)
01003         {
01004                 LLViewerRegion* regionp = *iter;
01005                 if (regionp == gAgent.getRegion())
01006                 {
01007                         // Skip the main agent
01008                         continue;
01009                 }
01010 
01011                 llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl;
01012                 msg->newMessageFast(_PREHASH_AgentQuitCopy);
01013                 msg->nextBlockFast(_PREHASH_AgentData);
01014                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01015                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01016                 msg->nextBlockFast(_PREHASH_FuseBlock);
01017                 msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode);
01018                 msg->sendMessage(regionp->getHost());
01019         }
01020 }
01021 
01022 
01023 void process_enable_simulator(LLMessageSystem *msg, void **user_data)
01024 {
01025         // enable the appropriate circuit for this simulator and 
01026         // add its values into the gSimulator structure
01027         U64             handle;
01028         U32             ip_u32;
01029         U16             port;
01030 
01031         msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle);
01032         msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32);
01033         msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port);
01034 
01035         // which simulator should we modify?
01036         LLHost sim(ip_u32, port);
01037 
01038         // Viewer trusts the simulator.
01039         msg->enableCircuit(sim, TRUE);
01040         LLWorld::getInstance()->addRegion(handle, sim);
01041 
01042         // give the simulator a message it can use to get ip and port
01043         llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl;
01044         msg->newMessageFast(_PREHASH_UseCircuitCode);
01045         msg->nextBlockFast(_PREHASH_CircuitCode);
01046         msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode());
01047         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01048         msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
01049         msg->sendReliable(sim);
01050 }
01051 
01052 class LLEstablishAgentCommunication : public LLHTTPNode
01053 {
01054         LOG_CLASS(LLEstablishAgentCommunication);
01055 public:
01056         virtual void describe(Description& desc) const
01057         {
01058                 desc.shortInfo("seed capability info for a region");
01059                 desc.postAPI();
01060                 desc.input(
01061                         "{ seed-capability: ..., sim-ip: ..., sim-port }");
01062                 desc.source(__FILE__, __LINE__);
01063         }
01064 
01065         virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
01066         {
01067                 if (!input["body"].has("agent-id") ||
01068                         !input["body"].has("sim-ip-and-port") ||
01069                         !input["body"].has("seed-capability"))
01070                 {
01071                         llwarns << "invalid parameters" << llendl;
01072             return;
01073                 }
01074 
01075                 LLHost sim(input["body"]["sim-ip-and-port"].asString());
01076         
01077                 LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim);
01078                 if (!regionp)
01079                 {
01080                         llwarns << "Got EstablishAgentCommunication for unknown region "
01081                                         << sim << llendl;
01082                         return;
01083                 }
01084                 regionp->setSeedCapability(input["body"]["seed-capability"]);
01085         }
01086 };
01087 
01088 // disable the circuit to this simulator
01089 // Called in response to "DisableSimulator" message.
01090 void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
01091 {       
01092         LLHost host = mesgsys->getSender();
01093 
01094         //llinfos << "Disabling simulator with message from " << host << llendl;
01095         LLWorld::getInstance()->removeRegion(host);
01096 
01097         mesgsys->disableCircuit(host);
01098 }
01099 
01100 
01101 void process_region_handshake(LLMessageSystem* msg, void** user_data)
01102 {
01103         LLHost host = msg->getSender();
01104         LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host);
01105         if (!regionp)
01106         {
01107                 llwarns << "Got region handshake for unknown region "
01108                         << host << llendl;
01109                 return;
01110         }
01111 
01112         regionp->unpackRegionHandshake();
01113 }
01114 
01115 
01116 void send_agent_pause()
01117 {
01118         // *NOTE:Mani Pausing the mainloop timeout. Otherwise a long modal event may cause
01119         // the thread monitor to timeout.
01120         LLAppViewer::instance()->stopMainloopTimeout();
01121         
01122         // Note: used to check for LLWorld initialization before it became a singleton.
01123         // Rather than just remove this check I'm changing it to assure that the message 
01124         // system has been initialized. -MG
01125         if (!gMessageSystem)
01126         {
01127                 return;
01128         }
01129         
01130         gMessageSystem->newMessageFast(_PREHASH_AgentPause);
01131         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
01132         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
01133         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
01134 
01135         gAgentPauseSerialNum++;
01136         gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
01137 
01138         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->mActiveRegionList.begin();
01139                  iter != LLWorld::getInstance()->mActiveRegionList.end(); ++iter)
01140         {
01141                 LLViewerRegion* regionp = *iter;
01142                 gMessageSystem->sendReliable(regionp->getHost());
01143         }
01144 
01145         gObjectList.mWasPaused = TRUE;
01146 }
01147 
01148 
01149 void send_agent_resume()
01150 {
01151         // Note: used to check for LLWorld initialization before it became a singleton.
01152         // Rather than just remove this check I'm changing it to assure that the message 
01153         // system has been initialized. -MG
01154         if (!gMessageSystem)
01155         {
01156                 return;
01157         }
01158 
01159         gMessageSystem->newMessageFast(_PREHASH_AgentResume);
01160         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
01161         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
01162         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
01163 
01164         gAgentPauseSerialNum++;
01165         gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
01166         
01167 
01168         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->mActiveRegionList.begin();
01169                  iter != LLWorld::getInstance()->mActiveRegionList.end(); ++iter)
01170         {
01171                 LLViewerRegion* regionp = *iter;
01172                 gMessageSystem->sendReliable(regionp->getHost());
01173         }
01174 
01175         // Reset the FPS counter to avoid an invalid fps
01176         LLViewerStats::getInstance()->mFPSStat.start();
01177 
01178         LLAppViewer::instance()->startMainloopTimeout();
01179 }
01180 
01181 
01182 LLHTTPRegistration<LLEstablishAgentCommunication>
01183         gHTTPRegistrationEstablishAgentCommunication(
01184                                                         "/message/EstablishAgentCommunication");

Generated on Fri May 16 08:34:26 2008 for SecondLife by  doxygen 1.5.5