aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs100
1 files changed, 95 insertions, 5 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 2e9db39..e8040d8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -337,6 +337,54 @@ public sealed class BSTerrainManager : IDisposable
337 return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); 337 return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ);
338 } 338 }
339 339
340 // Return a new position that is over known terrain if the position is outside our terrain.
341 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos)
342 {
343 Vector3 ret = pPos;
344
345 // Can't do this function if we don't know about any terrain.
346 if (m_terrains.Count == 0)
347 return ret;
348
349 int loopPrevention = 5;
350 Vector3 terrainBaseXYZ;
351 BSTerrainPhys physTerrain;
352 while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ))
353 {
354 // The passed position is not within a known terrain area.
355
356 // First, base addresses are never negative so correct for that possible problem.
357 if (ret.X < 0f || ret.Y < 0f)
358 {
359 if (ret.X < 0f)
360 ret.X = 0f;
361 if (ret.Y < 0f)
362 ret.Y = 0f;
363 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}",
364 BSScene.DetailLogZero, pPos, ret);
365 }
366 else
367 {
368 // Must be off the top of a region. Find an adjacent region to move into.
369 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
370
371 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + DefaultRegionSize.X);
372 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + DefaultRegionSize.Y);
373 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
374 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
375 }
376 if (loopPrevention-- < 0f)
377 {
378 // The 'while' is a little dangerous so this prevents looping forever if the
379 // mapping of the terrains ever gets messed up (like nothing at <0,0>) or
380 // the list of terrains is in transition.
381 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,suppressingFindAdjacentRegionLoop", BSScene.DetailLogZero);
382 break;
383 }
384 }
385 return ret;
386 }
387
340 // Given an X and Y, find the height of the terrain. 388 // Given an X and Y, find the height of the terrain.
341 // Since we could be handling multiple terrains for a mega-region, 389 // Since we could be handling multiple terrains for a mega-region,
342 // the base of the region is calcuated assuming all regions are 390 // the base of the region is calcuated assuming all regions are
@@ -400,18 +448,60 @@ public sealed class BSTerrainManager : IDisposable
400 // the descriptor class and the 'base' fo the addresses therein. 448 // the descriptor class and the 'base' fo the addresses therein.
401 private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) 449 private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase)
402 { 450 {
403 int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; 451 bool ret = false;
404 int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; 452
405 Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); 453 Vector3 terrainBaseXYZ = Vector3.Zero;
454 if (pos.X < 0f || pos.Y < 0f)
455 {
456 // We don't handle negative addresses so just make up a base that will not be found.
457 terrainBaseXYZ = new Vector3(-DefaultRegionSize.X, -DefaultRegionSize.Y, 0f);
458 }
459 else
460 {
461 int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
462 int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
463 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
464 }
406 465
407 BSTerrainPhys physTerrain = null; 466 BSTerrainPhys physTerrain = null;
408 lock (m_terrains) 467 lock (m_terrains)
409 { 468 {
410 m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); 469 ret = m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
411 } 470 }
412 outTerrainBase = terrainBaseXYZ; 471 outTerrainBase = terrainBaseXYZ;
413 outPhysTerrain = physTerrain; 472 outPhysTerrain = physTerrain;
414 return (physTerrain != null); 473 return ret;
474 }
475
476 // Given a terrain base, return a terrain base for a terrain that is closer to <0,0> than
477 // this one. Usually used to return an out of bounds object to a known place.
478 private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase)
479 {
480 Vector3 ret = pTerrainBase;
481 ret.Z = 0f;
482 lock (m_terrains)
483 {
484 // Once down to the <0,0> region, we have to be done.
485 while (ret.X > 0f && ret.Y > 0f)
486 {
487 if (ret.X > 0f)
488 {
489 ret.X = Math.Max(0f, ret.X - DefaultRegionSize.X);
490 DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingX,terrainBase={1}", BSScene.DetailLogZero, ret);
491 if (m_terrains.ContainsKey(ret))
492 break;
493 }
494 if (ret.Y > 0f)
495 {
496 ret.Y = Math.Max(0f, ret.Y - DefaultRegionSize.Y);
497 DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingY,terrainBase={1}", BSScene.DetailLogZero, ret);
498 if (m_terrains.ContainsKey(ret))
499 break;
500 }
501 }
502 }
503
504 return ret;
415 } 505 }
416 506
417 // Although no one seems to check this, I do support combining. 507 // Although no one seems to check this, I do support combining.