aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llworld.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llworld.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llworld.cpp')
-rw-r--r--linden/indra/newview/llworld.cpp1160
1 files changed, 1160 insertions, 0 deletions
diff --git a/linden/indra/newview/llworld.cpp b/linden/indra/newview/llworld.cpp
new file mode 100644
index 0000000..18d4e48
--- /dev/null
+++ b/linden/indra/newview/llworld.cpp
@@ -0,0 +1,1160 @@
1/**
2 * @file llworld.cpp
3 * @brief Initial test structure to organize viewer regions
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llworld.h"
31
32#include "indra_constants.h"
33
34#include "llagent.h"
35#include "llviewercontrol.h"
36#include "lldrawpool.h"
37#include "llglheaders.h"
38#include "llregionhandle.h"
39#include "llsurface.h"
40#include "llviewercamera.h"
41#include "llviewerimage.h"
42#include "llviewerimagelist.h"
43#include "llviewernetwork.h"
44#include "llviewerobjectlist.h"
45#include "llviewerparceloverlay.h"
46#include "llviewerregion.h"
47#include "llviewerstats.h"
48#include "llvlcomposition.h"
49#include "llvoavatar.h"
50#include "llvowater.h"
51#include "message.h"
52#include "pipeline.h"
53#include "viewer.h" // for do_disconnect()
54
55//
56// Globals
57//
58LLWorld* gWorldp = NULL;
59U32 gAgentPauseSerialNum = 0;
60
61//
62// Constants
63//
64const S32 MAX_NUMBER_OF_CLOUDS = 750;
65const F32 MIN_IDLE_UPDATE_TIME = 0.025f;
66const S32 WORLD_PATCH_SIZE = 16;
67
68extern LLColor4U MAX_WATER_COLOR;
69
70//
71// Functions
72//
73
74// allocate the stack
75LLWorld::LLWorld(const U32 grids_per_region, const F32 meters_per_grid)
76: mWidth(grids_per_region),
77 mScale(meters_per_grid),
78 mWidthInMeters( grids_per_region * meters_per_grid )
79{
80 mSpaceTimeUSec = 0;
81 mLastPacketsIn = 0;
82 mLastPacketsOut = 0;
83 mLastPacketsLost = 0;
84 mLandFarClip = DEFAULT_FAR_PLANE;
85 mIdleUpdateTime = MIN_IDLE_UPDATE_TIME;
86
87 if (gNoRender)
88 {
89 return;
90 }
91
92 for (S32 i = 0; i < 8; i++)
93 {
94 mEdgeWaterObjects[i] = NULL;
95 }
96
97 LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4);
98 U8 *default_texture = raw->getData();
99 *(default_texture++) = MAX_WATER_COLOR.mV[0];
100 *(default_texture++) = MAX_WATER_COLOR.mV[1];
101 *(default_texture++) = MAX_WATER_COLOR.mV[2];
102 *(default_texture++) = MAX_WATER_COLOR.mV[3];
103
104 mDefaultWaterTexturep = new LLViewerImage(raw, FALSE);
105 mDefaultWaterTexturep->bind();
106 mDefaultWaterTexturep->setClamp(TRUE, TRUE);
107
108}
109
110
111LLWorld::~LLWorld()
112{
113 gObjectList.killAllObjects();
114
115 mRegionList.deleteAllData();
116}
117
118
119LLViewerRegion* LLWorld::addRegion(const U64 &region_handle, const LLHost &host)
120{
121 LLMemType mt(LLMemType::MTYPE_REGIONS);
122
123 LLViewerRegion *regionp = getRegionFromHandle(region_handle);
124 if (regionp)
125 {
126 LLHost old_host = regionp->getHost();
127 // region already exists!
128 if (host == old_host && regionp->mAlive)
129 {
130 // This is a duplicate for the same host and it's alive, don't bother.
131 return regionp;
132 }
133
134 if (host != old_host)
135 {
136 llwarns << "LLWorld::addRegion exists, but old host " << old_host
137 << " does not match new host " << host << llendl;
138 }
139 if (!regionp->mAlive)
140 {
141 llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl;
142 }
143
144 // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host
145 // matches, because all the agent state for the new camera is completely different.
146 removeRegion(old_host);
147 }
148
149 U32 iindex = 0;
150 U32 jindex = 0;
151 from_region_handle(region_handle, &iindex, &jindex);
152 S32 x = (S32)(iindex/mWidth);
153 S32 y = (S32)(jindex/mWidth);
154 llinfos << "Adding new region (" << x << ":" << y << ")" << llendl;
155 llinfos << "Host: " << host << llendl;
156
157 LLVector3d origin_global;
158
159 origin_global = from_region_handle(region_handle);
160
161 regionp = new LLViewerRegion(region_handle,
162 host,
163 mWidth,
164 WORLD_PATCH_SIZE,
165 getRegionWidthInMeters() );
166 if (!regionp)
167 {
168 llerrs << "Unable to create new region!" << llendl;
169 }
170
171 regionp->mCloudLayer.create(regionp);
172 regionp->mCloudLayer.setWidth((F32)mWidth);
173 regionp->mCloudLayer.setWindPointer(&regionp->mWind);
174
175 mRegionList.addData(regionp);
176 mActiveRegionList.addData(regionp);
177 mCulledRegionList.addData(regionp);
178
179
180 // Find all the adjacent regions, and attach them.
181 // Generate handles for all of the adjacent regions, and attach them in the correct way.
182 // connect the edges
183 F32 adj_x = 0.f;
184 F32 adj_y = 0.f;
185 F32 region_x = 0.f;
186 F32 region_y = 0.f;
187 U64 adj_handle = 0;
188
189 F32 width = getRegionWidthInMeters();
190
191 LLViewerRegion *neighborp;
192 from_region_handle(region_handle, &region_x, &region_y);
193
194 // Iterate through all directions, and connect neighbors if there.
195 S32 dir;
196 for (dir = 0; dir < 8; dir++)
197 {
198 adj_x = region_x + width * gDirAxes[dir][0];
199 adj_y = region_y + width * gDirAxes[dir][1];
200 to_region_handle(adj_x, adj_y, &adj_handle);
201
202 neighborp = getRegionFromHandle(adj_handle);
203 if (neighborp)
204 {
205 //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl;
206 regionp->connectNeighbor(neighborp, dir);
207 }
208 }
209
210 updateWaterObjects();
211
212 return regionp;
213}
214
215
216void LLWorld::removeRegion(const LLHost &host)
217{
218 F32 x, y;
219
220 LLViewerRegion *regionp = getRegion(host);
221 if (!regionp)
222 {
223 llwarns << "Trying to remove region that doesn't exist!" << llendl;
224 return;
225 }
226
227 if (regionp == gAgent.getRegion())
228 {
229 LLViewerRegion *reg;
230 for (reg = mRegionList.getFirstData(); reg; reg = mRegionList.getNextData())
231 {
232 llwarns << "RegionDump: " << reg->getName()
233 << " " << reg->getHost()
234 << " " << reg->getOriginGlobal()
235 << llendl;
236 }
237
238 llwarns << "Agent position global " << gAgent.getPositionGlobal()
239 << " agent " << gAgent.getPositionAgent()
240 << llendl;
241
242 llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl;
243
244 llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl;
245
246 llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl;
247 do_disconnect("You have been disconnected from the region you were in.");
248 return;
249 }
250
251 from_region_handle(regionp->getHandle(), &x, &y);
252 llinfos << "Removing region " << x << ":" << y << llendl;
253
254 // This code can probably be blitzed now...
255 if (!mRegionList.removeData(regionp))
256 {
257 for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData())
258 {
259 llwarns << "RegionDump: " << regionp->getName()
260 << " " << regionp->getHost()
261 << " " << regionp->getOriginGlobal()
262 << llendl;
263 }
264
265 llerrs << "Region list is broken" << llendl;
266 }
267
268 if (!mActiveRegionList.removeData(regionp))
269 {
270 llwarns << "LLWorld.mActiveRegionList is broken." << llendl;
271 }
272 if (!mCulledRegionList.removeData(regionp))
273 {
274 if (!mVisibleRegionList.removeData(regionp))
275 {
276 llwarns << "LLWorld.mCulled/mVisibleRegionList are broken" << llendl;;
277 }
278 }
279 delete regionp;
280
281 updateWaterObjects();
282}
283
284
285LLViewerRegion *LLWorld::getRegion(const LLHost &host)
286{
287 LLViewerRegion *regionp;
288 for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData())
289 {
290 if (regionp->getHost() == host)
291 {
292 return regionp;
293 }
294 }
295 return NULL;
296}
297
298LLViewerRegion *LLWorld::getRegionFromPosAgent(const LLVector3 &pos)
299{
300 return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos));
301}
302
303LLViewerRegion *LLWorld::getRegionFromPosGlobal(const LLVector3d &pos)
304{
305 LLViewerRegion *regionp;
306 for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData())
307 {
308 if (regionp->pointInRegionGlobal(pos))
309 {
310 return regionp;
311 }
312 }
313 return NULL;
314}
315
316
317LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos)
318{
319 if (positionRegionValidGlobal(end_pos))
320 {
321 return end_pos;
322 }
323
324 LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos);
325 if (!regionp)
326 {
327 return start_pos;
328 }
329
330 LLVector3d delta_pos = end_pos - start_pos;
331 LLVector3d delta_pos_abs;
332 delta_pos_abs.setVec(delta_pos);
333 delta_pos_abs.abs();
334
335 LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos);
336 F64 clip_factor = 1.0;
337 F32 region_width = regionp->getWidth();
338 if (region_coord.mV[VX] < 0.f)
339 {
340 if (region_coord.mV[VY] < region_coord.mV[VX])
341 {
342 // clip along y -
343 clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
344 }
345 else
346 {
347 // clip along x -
348 clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]);
349 }
350 }
351 else if (region_coord.mV[VX] > region_width)
352 {
353 if (region_coord.mV[VY] > region_coord.mV[VX])
354 {
355 // clip along y +
356 clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
357 }
358 else
359 {
360 //clip along x +
361 clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX];
362 }
363 }
364 else if (region_coord.mV[VY] < 0.f)
365 {
366 // clip along y -
367 clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
368 }
369 else if (region_coord.mV[VY] > region_width)
370 {
371 // clip along y +
372 clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
373 }
374
375 // clamp to < 256 to stay in sim
376 LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor);
377 final_region_pos.clamp(0.0, 255.999);
378 return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos));
379}
380
381LLViewerRegion *LLWorld::getRegionFromHandle(const U64 &handle)
382{
383 LLViewerRegion *regionp;
384 for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData())
385 {
386 if (regionp->getHandle() == handle)
387 {
388 return regionp;
389 }
390 }
391 return NULL;
392}
393
394
395void LLWorld::updateAgentOffset(const LLVector3d &offset_global)
396{
397#if 0
398 LLViewerRegion *regionp;
399 for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData())
400 {
401 regionp->setAgentOffset(offset_global);
402 }
403#endif
404}
405
406
407BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global)
408{
409 LLViewerRegion *regionp;
410 for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData())
411 {
412 if (regionp->pointInRegionGlobal(pos_global))
413 {
414 return TRUE;
415 }
416 }
417 return FALSE;
418}
419
420
421// Allow objects to go up to their radius underground.
422F32 LLWorld::getMinAllowedZ(LLViewerObject* object)
423{
424 F32 land_height = resolveLandHeightGlobal(object->getPositionGlobal());
425 F32 radius = 0.5f * object->getScale().magVec();
426 return land_height - radius;
427}
428
429
430LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global)
431{
432 LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
433
434 if (regionp)
435 {
436 pos_region = regionp->getPosRegionFromGlobal(pos_global);
437 return regionp;
438 }
439
440 return NULL;
441}
442
443
444LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent)
445{
446 LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
447 LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
448
449 if (regionp)
450 {
451 pos_region = regionp->getPosRegionFromGlobal(pos_global);
452 return regionp;
453 }
454
455 return NULL;
456}
457
458
459F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent)
460{
461 LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
462 return resolveLandHeightGlobal(pos_global);
463}
464
465
466F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global)
467{
468 LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
469 if (regionp)
470 {
471 return regionp->getLand().resolveHeightGlobal(pos_global);
472 }
473 return 0.0f;
474}
475
476
477// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a)
478// point where the the line intersects an object or the land surface. Stores the results
479// in "intersection" and "intersection_normal" and returns a scalar value that represents
480// the normalized distance along the line from "point_a" to "intersection".
481//
482// Currently assumes point_a and point_b only differ in z-direction,
483// but it may eventually become more general.
484F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b,
485 LLVector3d &intersection, LLVector3 &intersection_normal,
486 LLViewerObject **viewerObjectPtr)
487{
488 // initialize return value to null
489 if (viewerObjectPtr)
490 {
491 *viewerObjectPtr = NULL;
492 }
493
494 LLViewerRegion *regionp = getRegionFromPosGlobal(point_a);
495 if (!regionp)
496 {
497 // We're outside the world
498 intersection = 0.5f * (point_a + point_b);
499 intersection_normal.setVec(0.0f, 0.0f, 1.0f);
500 return 0.5f;
501 }
502
503 // calculate the length of the segment
504 F32 segment_length = (F32)((point_a - point_b).magVec());
505 if (0.0f == segment_length)
506 {
507 intersection = point_a;
508 intersection_normal.setVec(0.0f, 0.0f, 1.0f);
509 return segment_length;
510 }
511
512 // get land height
513 // Note: we assume that the line is parallel to z-axis here
514 LLVector3d land_intersection = point_a;
515 F32 normalized_land_distance;
516
517 land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a);
518 normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length;
519
520 if (avatarp && !avatarp->mFootPlane.isExactlyClear())
521 {
522 LLVector3 foot_plane_normal(avatarp->mFootPlane.mV);
523 LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a);
524 // added 0.05 meters to compensate for error in foot plane reported by Havok
525 F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f;
526 norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f);
527 if (norm_dist_from_plane < normalized_land_distance)
528 {
529 normalized_land_distance = norm_dist_from_plane;
530 intersection = point_a;
531 intersection.mdV[VZ] -= norm_dist_from_plane * segment_length;
532 intersection_normal = foot_plane_normal;
533 }
534 }
535 else
536 {
537 intersection = land_intersection;
538 intersection_normal = resolveLandNormalGlobal(land_intersection);
539 }
540
541 return normalized_land_distance;
542}
543
544
545LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global)
546{
547 // returns a pointer to the patch at this location
548 LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
549 if (!regionp)
550 {
551 return NULL;
552 }
553
554 return regionp->getLand().resolvePatchGlobal(pos_global);
555}
556
557
558LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global)
559{
560 LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
561 if (!regionp)
562 {
563 return LLVector3::z_axis;
564 }
565
566 return regionp->getLand().resolveNormalGlobal(pos_global);
567}
568
569
570void LLWorld::updateVisibilities()
571{
572 F32 cur_far_clip = gCamera->getFar();
573
574 gCamera->setFar(mLandFarClip);
575
576 LLViewerRegion *regionp;
577
578 F32 diagonal_squared = F_SQRT2 * F_SQRT2 * mWidth * mWidth;
579 // Go through the culled list and check for visible regions
580 for (regionp = mCulledRegionList.getFirstData();
581 regionp;
582 regionp = mCulledRegionList.getNextData())
583 {
584 F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ();
585 F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared);
586 if (!regionp->getLand().hasZData()
587 || gCamera->sphereInFrustum(regionp->getCenterAgent(), radius))
588 {
589 mCulledRegionList.removeCurrentData();
590 mVisibleRegionList.addDataAtEnd(regionp);
591 }
592 }
593
594 F32 last_dist_squared = 0.0f;
595 F32 dist_squared;
596
597 // Update all of the visible regions and make single bubble-sort pass
598 for (regionp = mVisibleRegionList.getFirstData();
599 regionp;
600 regionp = mVisibleRegionList.getNextData())
601 {
602 if (!regionp->getLand().hasZData())
603 {
604 continue;
605 }
606
607 F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ();
608 F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared);
609 if (gCamera->sphereInFrustum(regionp->getCenterAgent(), radius))
610 {
611 if (!gNoRender)
612 {
613 regionp->getLand().updatePatchVisibilities(gAgent);
614 }
615
616 // sort by distance... closer regions to the front
617 // Note: regions use absolute frame so we use the agent's center
618 dist_squared = (F32)(gAgent.getCameraPositionGlobal() - regionp->getCenterGlobal()).magVecSquared();
619 if (dist_squared < last_dist_squared)
620 {
621 mVisibleRegionList.swapCurrentWithPrevious();
622 }
623 else
624 {
625 last_dist_squared = dist_squared;
626 }
627 }
628 else
629 {
630 mVisibleRegionList.removeCurrentData();
631 mCulledRegionList.addData(regionp);
632 }
633 }
634
635 gCamera->setFar(cur_far_clip);
636}
637
638
639void LLWorld::updateRegions()
640{
641 LLViewerRegion *regionp;
642 LLTimer update_timer;
643
644 // Perform idle time updates for the regions (and associated surfaces)
645 for (regionp = mRegionList.getFirstData();
646 regionp;
647 regionp = mRegionList.getNextData())
648 {
649 update_timer.reset();
650 if (!regionp->idleUpdate(update_timer, mIdleUpdateTime))
651 {
652 // Didn't finish all the updates. Slightly increase the idle update time.
653 mIdleUpdateTime *= 1.05f;
654 }
655 else
656 {
657 mIdleUpdateTime *= 0.9f;
658 if (mIdleUpdateTime < MIN_IDLE_UPDATE_TIME)
659 {
660 mIdleUpdateTime = MIN_IDLE_UPDATE_TIME;
661 }
662 }
663 }
664}
665
666void LLWorld::updateParticles()
667{
668 mPartSim.updateSimulation();
669}
670
671void LLWorld::updateClouds(const F32 dt)
672{
673 if (gSavedSettings.getBOOL("FreezeTime"))
674 {
675 // don't move clouds in snapshot mode
676 return;
677 }
678 LLViewerRegion *regionp;
679 if (mActiveRegionList.getLength())
680 {
681 // Update all the cloud puff positions, and timer based stuff
682 // such as death decay
683 for (regionp = mActiveRegionList.getFirstData();
684 regionp;
685 regionp = mActiveRegionList.getNextData())
686 {
687 regionp->mCloudLayer.updatePuffs(dt);
688 }
689
690 // Reshuffle who owns which puffs
691 for (regionp = mActiveRegionList.getFirstData();
692 regionp;
693 regionp = mActiveRegionList.getNextData())
694 {
695 regionp->mCloudLayer.updatePuffOwnership();
696 }
697
698 // Add new puffs
699 for (regionp = mActiveRegionList.getFirstData();
700 regionp;
701 regionp = mActiveRegionList.getNextData())
702 {
703 regionp->mCloudLayer.updatePuffCount();
704 }
705 }
706}
707
708LLCloudGroup *LLWorld::findCloudGroup(const LLCloudPuff &puff)
709{
710 LLViewerRegion *regionp;
711 if (mActiveRegionList.getLength())
712 {
713 // Update all the cloud puff positions, and timer based stuff
714 // such as death decay
715 for (regionp = mActiveRegionList.getFirstData();
716 regionp;
717 regionp = mActiveRegionList.getNextData())
718 {
719 LLCloudGroup *groupp = regionp->mCloudLayer.findCloudGroup(puff);
720 if (groupp)
721 {
722 return groupp;
723 }
724 }
725 }
726 return NULL;
727}
728
729
730void LLWorld::renderPropertyLines()
731{
732 S32 region_count = 0;
733 S32 vertex_count = 0;
734
735 LLViewerRegion* region;
736 for (region = mVisibleRegionList.getFirstData(); region; region = mVisibleRegionList.getNextData() )
737 {
738 region_count++;
739 vertex_count += region->renderPropertyLines();
740 }
741}
742
743
744void LLWorld::updateNetStats()
745{
746 F32 bits = 0.f;
747 U32 packets = 0;
748 LLViewerRegion *regionp;
749
750 for (regionp = mActiveRegionList.getFirstData(); regionp; regionp = mActiveRegionList.getNextData())
751 {
752 regionp->updateNetStats();
753 bits += regionp->mBitStat.getCurrent();
754 packets += llfloor( regionp->mPacketsStat.getCurrent() );
755 }
756
757 S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn;
758 S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut;
759 S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost;
760
761 S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits();
762 S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits();
763 gViewerStats->mActualInKBitStat.addValue(actual_in_bits/1024.f);
764 gViewerStats->mActualOutKBitStat.addValue(actual_out_bits/1024.f);
765 gViewerStats->mKBitStat.addValue(bits/1024.f);
766 gViewerStats->mPacketsInStat.addValue(packets_in);
767 gViewerStats->mPacketsOutStat.addValue(packets_out);
768 gViewerStats->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets);
769 if (packets_in)
770 {
771 gViewerStats->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in));
772 }
773 else
774 {
775 gViewerStats->mPacketsLostPercentStat.addValue(0.f);
776 }
777
778 mLastPacketsIn = gMessageSystem->mPacketsIn;
779 mLastPacketsOut = gMessageSystem->mPacketsOut;
780 mLastPacketsLost = gMessageSystem->mDroppedPackets;
781}
782
783
784void LLWorld::printPacketsLost()
785{
786 LLViewerRegion *regionp;
787
788 llinfos << "Simulators:" << llendl;
789 llinfos << "----------" << llendl;
790
791 LLCircuitData *cdp = NULL;
792 for (regionp = mActiveRegionList.getFirstData();
793 regionp;
794 regionp = mActiveRegionList.getNextData())
795 {
796 cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost());
797 if (cdp)
798 {
799 LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal();
800
801 llinfos << regionp->getHost() << ", range: " << range.magVec() <<
802 " packets lost: " <<
803 cdp->getPacketsLost() << llendl;
804 }
805 }
806
807 llinfos << "UserServer:" << llendl;
808 llinfos << "-----------" << llendl;
809
810 cdp = gMessageSystem->mCircuitInfo.findCircuit(gUserServer);
811 if (cdp)
812 {
813 llinfos << gUserServer << " packets lost: " << cdp->getPacketsLost() << llendl;
814 }
815}
816
817void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data)
818{
819 LLViewerRegion* region = NULL;
820 region = gWorldp->getRegion(msg->getSender());
821 if( region ) region->updateCoarseLocations(msg);
822}
823
824F32 LLWorld::getLandFarClip() const
825{
826 return mLandFarClip;
827}
828
829void LLWorld::setLandFarClip(const F32 far_clip)
830{
831 mLandFarClip = far_clip;
832}
833
834
835void LLWorld::updateWaterObjects()
836{
837 //llinfos << "Start water update" << llendl;
838 if (!gAgent.getRegion())
839 {
840 return;
841 }
842 S32 min_x, min_y, max_x, max_y;
843 U32 region_x, region_y;
844
845 S32 rwidth = llfloor(getRegionWidthInMeters());
846
847 // First, determine the min and max "box" of water objects
848 LLViewerRegion *regionp;
849 regionp = mRegionList.getFirstData();
850
851 if (!regionp)
852 {
853 llwarns << "No regions!" << llendl;
854 return;
855 }
856
857 from_region_handle(regionp->getHandle(), &region_x, &region_y);
858 min_x = max_x = region_x;
859 min_y = max_y = region_y;
860
861 LLVOWater *waterp;
862
863 for (; regionp; regionp = mRegionList.getNextData())
864 {
865 from_region_handle(regionp->getHandle(), &region_x, &region_y);
866 min_x = llmin(min_x, (S32)region_x);
867 min_y = llmin(min_y, (S32)region_y);
868 max_x = llmax(max_x, (S32)region_x);
869 max_y = llmax(max_y, (S32)region_y);
870 waterp = regionp->getLand().getWaterObj();
871 if (waterp)
872 {
873 gObjectList.updateActive(waterp);
874 }
875 }
876
877 for (waterp = mHoleWaterObjects.getFirstData(); waterp; waterp = mHoleWaterObjects.getNextData())
878 {
879 gObjectList.killObject(waterp);
880 }
881 mHoleWaterObjects.removeAllNodes();
882
883 // We only want to fill in holes for stuff that's near us, say, within 512m
884 regionp = gAgent.getRegion();
885 from_region_handle(regionp->getHandle(), &region_x, &region_y);
886
887 min_x = llmax((S32)region_x - 512, min_x);
888 min_y = llmax((S32)region_y - 512, min_y);
889 max_x = llmin((S32)region_x + 512, max_x);
890 max_y = llmin((S32)region_y + 512, max_y);
891
892 // Now, get a list of the holes
893 S32 x, y;
894 for (x = min_x; x <= max_x; x += rwidth)
895 {
896 for (y = min_y; y <= max_y; y += rwidth)
897 {
898 U64 region_handle = to_region_handle(x, y);
899 if (!getRegionFromHandle(region_handle))
900 {
901 waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
902 waterp->setUseTexture(FALSE);
903 gPipeline.addObject(waterp);
904 waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
905 y + rwidth/2,
906 DEFAULT_WATER_HEIGHT));
907 waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 0.f));
908 mHoleWaterObjects.addData(waterp);
909 }
910 }
911 }
912
913 // Update edge water objects
914 S32 wx, wy;
915 S32 center_x, center_y;
916 wx = (max_x - min_x) + rwidth;
917 wy = (max_y - min_y) + rwidth;
918 center_x = min_x + (wx >> 1);
919 center_y = min_y + (wy >> 1);
920
921
922
923 S32 add_boundary[4] = {
924 512 - (max_x - region_x),
925 512 - (max_y - region_y),
926 512 - (region_x - min_x),
927 512 - (region_y - min_y) };
928
929
930 S32 dir;
931 for (dir = 0; dir < 8; dir++)
932 {
933 S32 dim[2] = { 0 };
934 switch (gDirAxes[dir][0])
935 {
936 case -1: dim[0] = add_boundary[2]; break;
937 case 0: dim[0] = wx; break;
938 default: dim[0] = add_boundary[0]; break;
939 }
940 switch (gDirAxes[dir][1])
941 {
942 case -1: dim[1] = add_boundary[3]; break;
943 case 0: dim[1] = wy; break;
944 default: dim[1] = add_boundary[1]; break;
945 }
946
947 if (dim[0] == 0 || dim[1] == 0)
948 {
949 continue;
950 }
951
952 // Resize and reshape the water objects
953 const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
954 const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
955
956
957 waterp = mEdgeWaterObjects[dir];
958 if (!waterp || waterp->isDead())
959 {
960 // The edge water objects can be dead because they're attached to the region that the
961 // agent was in when they were originally created.
962 mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER,
963 gAgent.getRegion());
964 waterp = mEdgeWaterObjects[dir];
965 waterp->setUseTexture(FALSE);
966 gPipeline.addObject(waterp);
967 }
968
969 waterp->setRegion(gAgent.getRegion());
970 LLVector3d water_pos(water_center_x, water_center_y,
971 DEFAULT_WATER_HEIGHT);
972 waterp->setPositionGlobal(water_pos);
973 waterp->setScale(LLVector3((F32)dim[0], (F32)dim[1], 0.f));
974 gObjectList.updateActive(waterp);
975 /*if (!gNoRender)
976 {
977 gPipeline.markMoved(waterp->mDrawable);
978 }*/
979 }
980
981
982 //llinfos << "End water update" << llendl;
983}
984
985LLViewerImage *LLWorld::getDefaultWaterTexture()
986{
987 return mDefaultWaterTexturep;
988}
989
990void LLWorld::setSpaceTimeUSec(const U64 space_time_usec)
991{
992 mSpaceTimeUSec = space_time_usec;
993}
994
995U64 LLWorld::getSpaceTimeUSec() const
996{
997 return mSpaceTimeUSec;
998}
999
1000void LLWorld::requestCacheMisses()
1001{
1002 for(LLViewerRegion* regionp = mRegionList.getFirstData();
1003 regionp;
1004 regionp = mRegionList.getNextData())
1005 {
1006 regionp->requestCacheMisses();
1007 }
1008}
1009
1010LLString LLWorld::getInfoString()
1011{
1012 LLString info_string("World Info:\n");
1013 for (LLViewerRegion* regionp = mRegionList.getFirstData();
1014 regionp;
1015 regionp = mRegionList.getNextData())
1016 {
1017 info_string += regionp->getInfoString();
1018 }
1019 return info_string;
1020}
1021
1022void LLWorld::disconnectRegions()
1023{
1024 LLMessageSystem* msg = gMessageSystem;
1025 for(LLViewerRegion* regionp = mRegionList.getFirstData();
1026 regionp;
1027 regionp = mRegionList.getNextData())
1028 {
1029 if (regionp == gAgent.getRegion())
1030 {
1031 // Skip the main agent
1032 continue;
1033 }
1034
1035 llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl;
1036 msg->newMessageFast(_PREHASH_AgentQuitCopy);
1037 msg->nextBlockFast(_PREHASH_AgentData);
1038 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
1039 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1040 msg->nextBlockFast(_PREHASH_FuseBlock);
1041 msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode);
1042 msg->sendMessage(regionp->getHost());
1043 }
1044}
1045
1046
1047void process_enable_simulator(LLMessageSystem *msg, void **user_data)
1048{
1049 // enable the appropriate circuit for this simulator and
1050 // add its values into the gSimulator structure
1051 U64 handle;
1052 U32 ip_u32;
1053 U16 port;
1054
1055 msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle);
1056 msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32);
1057 msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port);
1058
1059 // which simulator should we modify?
1060 LLHost sim(ip_u32, port);
1061
1062 // Viewer trusts the simulator.
1063 msg->enableCircuit(sim, TRUE);
1064 gWorldp->addRegion(handle, sim);
1065
1066 // give the simulator a message it can use to get ip and port
1067 llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl;
1068 msg->newMessageFast(_PREHASH_UseCircuitCode);
1069 msg->nextBlockFast(_PREHASH_CircuitCode);
1070 msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode());
1071 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1072 msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
1073 msg->sendReliable(sim);
1074}
1075
1076
1077// disable the circuit to this simulator
1078// Called in response to "DisableSimulator" message.
1079void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
1080{
1081 LLHost host = mesgsys->getSender();
1082
1083 //llinfos << "Disabling simulator with message from " << host << llendl;
1084 gWorldp->removeRegion(host);
1085
1086 mesgsys->disableCircuit(host);
1087}
1088
1089
1090void process_region_handshake(LLMessageSystem* msg, void** user_data)
1091{
1092 LLHost host = msg->getSender();
1093 LLViewerRegion* regionp = gWorldp->getRegion(host);
1094 if (!regionp)
1095 {
1096 llwarns << "Got region handshake for unknown region "
1097 << host << llendl;
1098 return;
1099 }
1100
1101 regionp->unpackRegionHandshake();
1102}
1103
1104
1105void send_agent_pause()
1106{
1107 // world not initialized yet
1108 if (!gWorldp) return;
1109
1110 gMessageSystem->newMessageFast(_PREHASH_AgentPause);
1111 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
1112 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
1113 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
1114
1115 gAgentPauseSerialNum++;
1116 gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
1117
1118 LLViewerRegion *regionp;
1119 for (regionp = gWorldp->mActiveRegionList.getFirstData();
1120 regionp;
1121 regionp = gWorldp->mActiveRegionList.getNextData())
1122 {
1123 gMessageSystem->sendReliable(regionp->getHost());
1124 }
1125
1126 gMessageSystem->sendReliable(gUserServer);
1127
1128 gObjectList.mWasPaused = TRUE;
1129}
1130
1131
1132void send_agent_resume()
1133{
1134 // world not initialized yet
1135 if (!gWorldp) return;
1136
1137 gMessageSystem->newMessageFast(_PREHASH_AgentResume);
1138 gMessageSystem->nextBlockFast(_PREHASH_AgentData);
1139 gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
1140 gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
1141
1142 gAgentPauseSerialNum++;
1143 gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
1144
1145
1146 LLViewerRegion *regionp;
1147 for (regionp = gWorldp->mActiveRegionList.getFirstData();
1148 regionp;
1149 regionp = gWorldp->mActiveRegionList.getNextData())
1150 {
1151 gMessageSystem->sendReliable(regionp->getHost());
1152 }
1153
1154 gMessageSystem->sendReliable(gUserServer);
1155
1156 // Reset the FPS counter to avoid an invalid fps
1157 gViewerStats->mFPSStat.start();
1158}
1159
1160