diff options
author | Robert Adams | 2013-03-09 14:15:14 -0800 |
---|---|---|
committer | Robert Adams | 2013-03-09 14:15:14 -0800 |
commit | 1120bcf123b5aa159e966a80254794f6af66f2a3 (patch) | |
tree | d2add6a1b8a5b5b24dac2820bf55af2c1b94d3fc /OpenSim/Region/Physics | |
parent | * Apparently, sometimes texture entries come in from the wire with no default... (diff) | |
download | opensim-SC-1120bcf123b5aa159e966a80254794f6af66f2a3.zip opensim-SC-1120bcf123b5aa159e966a80254794f6af66f2a3.tar.gz opensim-SC-1120bcf123b5aa159e966a80254794f6af66f2a3.tar.bz2 opensim-SC-1120bcf123b5aa159e966a80254794f6af66f2a3.tar.xz |
BulletSim: remove the ability for avatars to fly off the edge of
regions when there are no region neighbors.
Add some terrain location processing routines to support above.
Diffstat (limited to '')
4 files changed, 117 insertions, 23 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f442ca2..e208d3a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -205,7 +205,7 @@ public sealed class BSCharacter : BSPhysObject | |||
205 | // errors can creap in and the avatar will slowly float off in some direction. | 205 | // errors can creap in and the avatar will slowly float off in some direction. |
206 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error | 206 | // So, the problem is that, when an avatar is standing, we cannot tell creaping error |
207 | // from real pushing. | 207 | // from real pushing. |
208 | // The code below keeps setting the velocity to zero hoping the world will keep pushing. | 208 | // The code below uses whether the collider is static or moving to decide whether to zero motion. |
209 | 209 | ||
210 | _velocityMotor.Step(timeStep); | 210 | _velocityMotor.Step(timeStep); |
211 | 211 | ||
@@ -244,6 +244,7 @@ public sealed class BSCharacter : BSPhysObject | |||
244 | } | 244 | } |
245 | else | 245 | else |
246 | { | 246 | { |
247 | // Supposed to be moving. | ||
247 | OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue; | 248 | OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue; |
248 | 249 | ||
249 | if (Friction != BSParam.AvatarFriction) | 250 | if (Friction != BSParam.AvatarFriction) |
@@ -276,8 +277,8 @@ public sealed class BSCharacter : BSPhysObject | |||
276 | }); | 277 | }); |
277 | } | 278 | } |
278 | 279 | ||
279 | // Decide of the character is colliding with a low object and compute a force to pop the | 280 | // Decide if the character is colliding with a low object and compute a force to pop the |
280 | // avatar up so it has a chance of walking up and over the low object. | 281 | // avatar up so it can walk up and over the low objects. |
281 | private OMV.Vector3 WalkUpStairs() | 282 | private OMV.Vector3 WalkUpStairs() |
282 | { | 283 | { |
283 | OMV.Vector3 ret = OMV.Vector3.Zero; | 284 | OMV.Vector3 ret = OMV.Vector3.Zero; |
@@ -476,17 +477,19 @@ public sealed class BSCharacter : BSPhysObject | |||
476 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) | 477 | if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) |
477 | { | 478 | { |
478 | // The character is out of the known/simulated area. | 479 | // The character is out of the known/simulated area. |
479 | // Upper levels of code will handle the transition to other areas so, for | 480 | // Force the avatar position to be within known. ScenePresence will use the position |
480 | // the time, we just ignore the position. | 481 | // plus the velocity to decide if the avatar is moving out of the region. |
481 | return ret; | 482 | RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); |
483 | DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); | ||
484 | return true; | ||
482 | } | 485 | } |
483 | 486 | ||
484 | // If below the ground, move the avatar up | 487 | // If below the ground, move the avatar up |
485 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | 488 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); |
486 | if (Position.Z < terrainHeight) | 489 | if (Position.Z < terrainHeight) |
487 | { | 490 | { |
488 | DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); | 491 | DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); |
489 | _position.Z = terrainHeight + 2.0f; | 492 | _position.Z = terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters; |
490 | ret = true; | 493 | ret = true; |
491 | } | 494 | } |
492 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) | 495 | if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) |
@@ -806,14 +809,7 @@ public sealed class BSCharacter : BSPhysObject | |||
806 | private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { | 809 | private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { |
807 | if (force.IsFinite()) | 810 | if (force.IsFinite()) |
808 | { | 811 | { |
809 | float magnitude = force.Length(); | 812 | OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); |
810 | if (magnitude > BSParam.MaxAddForceMagnitude) | ||
811 | { | ||
812 | // Force has a limit | ||
813 | force = force / magnitude * BSParam.MaxAddForceMagnitude; | ||
814 | } | ||
815 | |||
816 | OMV.Vector3 addForce = force; | ||
817 | // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); | 813 | // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); |
818 | 814 | ||
819 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() | 815 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() |
@@ -902,6 +898,7 @@ public sealed class BSCharacter : BSPhysObject | |||
902 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. | 898 | // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. |
903 | if (PositionSanityCheck(true)) | 899 | if (PositionSanityCheck(true)) |
904 | { | 900 | { |
901 | DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); | ||
905 | entprop.Position = _position; | 902 | entprop.Position = _position; |
906 | } | 903 | } |
907 | 904 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index fa58109..2af8468 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | |||
@@ -107,6 +107,7 @@ public static class BSParam | |||
107 | public static float AvatarCapsuleDepth { get; private set; } | 107 | public static float AvatarCapsuleDepth { get; private set; } |
108 | public static float AvatarCapsuleHeight { get; private set; } | 108 | public static float AvatarCapsuleHeight { get; private set; } |
109 | public static float AvatarContactProcessingThreshold { get; private set; } | 109 | public static float AvatarContactProcessingThreshold { get; private set; } |
110 | public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } | ||
110 | public static float AvatarStepHeight { get; private set; } | 111 | public static float AvatarStepHeight { get; private set; } |
111 | public static float AvatarStepApproachFactor { get; private set; } | 112 | public static float AvatarStepApproachFactor { get; private set; } |
112 | public static float AvatarStepForceFactor { get; private set; } | 113 | public static float AvatarStepForceFactor { get; private set; } |
@@ -497,6 +498,10 @@ public static class BSParam | |||
497 | 0.1f, | 498 | 0.1f, |
498 | (s) => { return AvatarContactProcessingThreshold; }, | 499 | (s) => { return AvatarContactProcessingThreshold; }, |
499 | (s,v) => { AvatarContactProcessingThreshold = v; } ), | 500 | (s,v) => { AvatarContactProcessingThreshold = v; } ), |
501 | new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", | ||
502 | 1.0f, | ||
503 | (s) => { return AvatarBelowGroundUpCorrectionMeters; }, | ||
504 | (s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ), | ||
500 | new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", | 505 | new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", |
501 | 0.3f, | 506 | 0.3f, |
502 | (s) => { return AvatarStepHeight; }, | 507 | (s) => { return AvatarStepHeight; }, |
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. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index d7e800d..57a5ff2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs | |||
@@ -215,7 +215,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
215 | 215 | ||
216 | float magX = (float)sizeX / extentX; | 216 | float magX = (float)sizeX / extentX; |
217 | float magY = (float)sizeY / extentY; | 217 | float magY = (float)sizeY / extentY; |
218 | physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", | 218 | if (physicsScene != null) |
219 | physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", | ||
219 | BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); | 220 | BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); |
220 | float minHeight = float.MaxValue; | 221 | float minHeight = float.MaxValue; |
221 | // Note that sizeX+1 vertices are created since there is land between this and the next region. | 222 | // Note that sizeX+1 vertices are created since there is land between this and the next region. |
@@ -257,7 +258,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys | |||
257 | } | 258 | } |
258 | catch (Exception e) | 259 | catch (Exception e) |
259 | { | 260 | { |
260 | physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", | 261 | if (physicsScene != null) |
262 | physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", | ||
261 | LogHeader, physicsScene.RegionName, extentBase, e); | 263 | LogHeader, physicsScene.RegionName, extentBase, e); |
262 | } | 264 | } |
263 | 265 | ||