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

Generated on Thu Jul 1 06:09:47 2010 for Second Life Viewer by  doxygen 1.4.7