From 5097437e1174d19d3dcb68e936581e60e4ef49cc Mon Sep 17 00:00:00 2001 From: teravus Date: Fri, 8 Mar 2013 19:32:47 -0500 Subject: [PATCH 1/3] * Apparently, sometimes texture entries come in from the wire with no default texture defined.. so apply better fallback protection against that. The net result is clients will have their selected textures set when they would have previously had an ignored exception. --- .../Region/Framework/Scenes/SceneObjectPart.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cce8b21b6e..3e9a6fa217 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4503,8 +4503,25 @@ namespace OpenSim.Region.Framework.Scenes Changed changeFlags = 0; + Primitive.TextureEntryFace fallbackNewFace = newTex.DefaultTexture; + Primitive.TextureEntryFace fallbackOldFace = oldTex.DefaultTexture; + + // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all + // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point. + if (fallbackNewFace == null) + { + fallbackNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); + newTex.DefaultTexture = fallbackNewFace; + } + if (fallbackOldFace == null) + { + fallbackOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); + oldTex.DefaultTexture = fallbackOldFace; + } + for (int i = 0 ; i < GetNumberOfSides(); i++) { + Primitive.TextureEntryFace newFace = newTex.DefaultTexture; Primitive.TextureEntryFace oldFace = oldTex.DefaultTexture; From 1120bcf123b5aa159e966a80254794f6af66f2a3 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 9 Mar 2013 14:15:14 -0800 Subject: [PATCH 2/3] 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. --- .../Physics/BulletSPlugin/BSCharacter.cs | 29 +++-- .../Region/Physics/BulletSPlugin/BSParam.cs | 5 + .../Physics/BulletSPlugin/BSTerrainManager.cs | 100 +++++++++++++++++- .../Physics/BulletSPlugin/BSTerrainMesh.cs | 6 +- 4 files changed, 117 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f442ca22df..e208d3a9e0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -205,7 +205,7 @@ public sealed class BSCharacter : BSPhysObject // errors can creap in and the avatar will slowly float off in some direction. // So, the problem is that, when an avatar is standing, we cannot tell creaping error // from real pushing. - // The code below keeps setting the velocity to zero hoping the world will keep pushing. + // The code below uses whether the collider is static or moving to decide whether to zero motion. _velocityMotor.Step(timeStep); @@ -244,6 +244,7 @@ public sealed class BSCharacter : BSPhysObject } else { + // Supposed to be moving. OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue; if (Friction != BSParam.AvatarFriction) @@ -276,8 +277,8 @@ public sealed class BSCharacter : BSPhysObject }); } - // Decide of the character is colliding with a low object and compute a force to pop the - // avatar up so it has a chance of walking up and over the low object. + // Decide if the character is colliding with a low object and compute a force to pop the + // avatar up so it can walk up and over the low objects. private OMV.Vector3 WalkUpStairs() { OMV.Vector3 ret = OMV.Vector3.Zero; @@ -476,17 +477,19 @@ public sealed class BSCharacter : BSPhysObject if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) { // The character is out of the known/simulated area. - // Upper levels of code will handle the transition to other areas so, for - // the time, we just ignore the position. - return ret; + // Force the avatar position to be within known. ScenePresence will use the position + // plus the velocity to decide if the avatar is moving out of the region. + RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); + DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); + return true; } // If below the ground, move the avatar up float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); if (Position.Z < terrainHeight) { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - _position.Z = terrainHeight + 2.0f; + DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); + _position.Z = terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters; ret = true; } if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) @@ -806,14 +809,7 @@ public sealed class BSCharacter : BSPhysObject private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { if (force.IsFinite()) { - float magnitude = force.Length(); - if (magnitude > BSParam.MaxAddForceMagnitude) - { - // Force has a limit - force = force / magnitude * BSParam.MaxAddForceMagnitude; - } - - OMV.Vector3 addForce = force; + OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() @@ -902,6 +898,7 @@ public sealed class BSCharacter : BSPhysObject // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. if (PositionSanityCheck(true)) { + DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); entprop.Position = _position; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index fa581090c6..2af84684fc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs @@ -107,6 +107,7 @@ public static class BSParam public static float AvatarCapsuleDepth { get; private set; } public static float AvatarCapsuleHeight { get; private set; } public static float AvatarContactProcessingThreshold { get; private set; } + public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } public static float AvatarStepHeight { get; private set; } public static float AvatarStepApproachFactor { get; private set; } public static float AvatarStepForceFactor { get; private set; } @@ -497,6 +498,10 @@ public static class BSParam 0.1f, (s) => { return AvatarContactProcessingThreshold; }, (s,v) => { AvatarContactProcessingThreshold = v; } ), + new ParameterDefn("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", + 1.0f, + (s) => { return AvatarBelowGroundUpCorrectionMeters; }, + (s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ), new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction", 0.3f, (s) => { return AvatarStepHeight; }, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 2e9db39f73..e8040d856b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -337,6 +337,54 @@ public sealed class BSTerrainManager : IDisposable return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); } + // Return a new position that is over known terrain if the position is outside our terrain. + public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) + { + Vector3 ret = pPos; + + // Can't do this function if we don't know about any terrain. + if (m_terrains.Count == 0) + return ret; + + int loopPrevention = 5; + Vector3 terrainBaseXYZ; + BSTerrainPhys physTerrain; + while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ)) + { + // The passed position is not within a known terrain area. + + // First, base addresses are never negative so correct for that possible problem. + if (ret.X < 0f || ret.Y < 0f) + { + if (ret.X < 0f) + ret.X = 0f; + if (ret.Y < 0f) + ret.Y = 0f; + DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}", + BSScene.DetailLogZero, pPos, ret); + } + else + { + // Must be off the top of a region. Find an adjacent region to move into. + Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); + + ret.X = Math.Min(ret.X, adjacentTerrainBase.X + DefaultRegionSize.X); + ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + DefaultRegionSize.Y); + DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", + BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); + } + if (loopPrevention-- < 0f) + { + // The 'while' is a little dangerous so this prevents looping forever if the + // mapping of the terrains ever gets messed up (like nothing at <0,0>) or + // the list of terrains is in transition. + DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,suppressingFindAdjacentRegionLoop", BSScene.DetailLogZero); + break; + } + } + return ret; + } + // Given an X and Y, find the height of the terrain. // Since we could be handling multiple terrains for a mega-region, // the base of the region is calcuated assuming all regions are @@ -400,18 +448,60 @@ public sealed class BSTerrainManager : IDisposable // the descriptor class and the 'base' fo the addresses therein. private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) { - int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; - int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); + bool ret = false; + + Vector3 terrainBaseXYZ = Vector3.Zero; + if (pos.X < 0f || pos.Y < 0f) + { + // We don't handle negative addresses so just make up a base that will not be found. + terrainBaseXYZ = new Vector3(-DefaultRegionSize.X, -DefaultRegionSize.Y, 0f); + } + else + { + int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; + int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; + terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); + } BSTerrainPhys physTerrain = null; lock (m_terrains) { - m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); + ret = m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); } outTerrainBase = terrainBaseXYZ; outPhysTerrain = physTerrain; - return (physTerrain != null); + return ret; + } + + // Given a terrain base, return a terrain base for a terrain that is closer to <0,0> than + // this one. Usually used to return an out of bounds object to a known place. + private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase) + { + Vector3 ret = pTerrainBase; + ret.Z = 0f; + lock (m_terrains) + { + // Once down to the <0,0> region, we have to be done. + while (ret.X > 0f && ret.Y > 0f) + { + if (ret.X > 0f) + { + ret.X = Math.Max(0f, ret.X - DefaultRegionSize.X); + DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingX,terrainBase={1}", BSScene.DetailLogZero, ret); + if (m_terrains.ContainsKey(ret)) + break; + } + if (ret.Y > 0f) + { + ret.Y = Math.Max(0f, ret.Y - DefaultRegionSize.Y); + DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingY,terrainBase={1}", BSScene.DetailLogZero, ret); + if (m_terrains.ContainsKey(ret)) + break; + } + } + } + + return ret; } // 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 d7e800d933..57a5ff2a6f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -215,7 +215,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys float magX = (float)sizeX / extentX; float magY = (float)sizeY / extentY; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", + if (physicsScene != null) + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); float minHeight = float.MaxValue; // 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 } catch (Exception e) { - physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", + if (physicsScene != null) + physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", LogHeader, physicsScene.RegionName, extentBase, e); } From 13f3bcae9454041e056df5e37d621ffda2c7a002 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 10 Mar 2013 22:24:34 -0700 Subject: [PATCH 3/3] Update comment about setting physics=BulletSimN as the C# Bullet version has been wrapped into one BulletSim and the physics engine selection is now done as specified in OpenSimDefaults.ini. --- bin/OpenSim.ini.example | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index eab1fce06a..e078e86807 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -210,13 +210,12 @@ ;; Choose one of the physics engines below ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} OpenDynamicsEngine ;; OpenDynamicsEngine is by some distance the most developed physics engine - ;; BulletSim is incomplete and experimental but in active development. BulletSimN is a purely C# version of BulletSim. + ;; BulletSim is experimental and in active development. ;; basicphysics effectively does not model physics at all, making all ;; objects phantom. ;; Default is OpenDynamicsEngine ; physics = OpenDynamicsEngine ; physics = BulletSim - ; physics = BulletSimN ; physics = basicphysics ; physics = POS