From c3f30fef96674e9f43a277399c987a85cec9a7d3 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 24 Nov 2012 19:57:11 -0800 Subject: BulletSim: add parameter for terrain collision margin. Add locking around unlikely but possible race conditions on terrain list. --- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 2 +- .../Physics/BulletSPlugin/BSTerrainManager.cs | 93 ++++++++++------------ .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 4 - 3 files changed, 45 insertions(+), 54 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs index 3ca756c..1450f66 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -93,7 +93,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys { m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, m_mapInfo.minCoords, m_mapInfo.maxCoords, - m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN); + m_mapInfo.heightMap, PhysicsScene.Params.terrainCollisionMargin); // Create the terrain shape from the mapInfo m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 23fcfd3..cd623f1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -80,8 +80,6 @@ public sealed class BSTerrainManager // amount to make sure that a bounding box is built for the terrain. public const float HEIGHT_EQUAL_FUDGE = 0.2f; - public const float TERRAIN_COLLISION_MARGIN = 0.0f; - // Until the whole simulator is changed to pass us the region size, we rely on constants. public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); @@ -129,7 +127,8 @@ public sealed class BSTerrainManager { // The ground plane is here to catch things that are trying to drop to negative infinity BulletShape groundPlaneShape = new BulletShape( - BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), + BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, + PhysicsScene.Params.terrainCollisionMargin), BSPhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, @@ -165,17 +164,22 @@ public sealed class BSTerrainManager // Release all the terrain we have allocated public void ReleaseTerrain() { - foreach (KeyValuePair kvp in m_terrains) + lock (m_terrains) { - kvp.Value.Dispose(); + foreach (KeyValuePair kvp in m_terrains) + { + kvp.Value.Dispose(); + } + m_terrains.Clear(); } - m_terrains.Clear(); } // The simulator wants to set a new heightmap for the terrain. public void SetTerrain(float[] heightMap) { float[] localHeightMap = heightMap; - PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() + // If there are multiple requests for changes to the same terrain between ticks, + // only do that last one. + PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() { if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) { @@ -211,6 +215,7 @@ public sealed class BSTerrainManager // terrain shape is created and added to the body. // This call is most often used to update the heightMap and parameters of the terrain. // (The above does suggest that some simplification/refactoring is in order.) + // Called during taint-time. private void UpdateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) { @@ -220,7 +225,7 @@ public sealed class BSTerrainManager // Find high and low points of passed heightmap. // The min and max passed in is usually the area objects can be in (maximum // object height, for instance). The terrain wants the bounding box for the - // terrain so we replace passed min and max Z with the actual terrain min/max Z. + // terrain so replace passed min and max Z with the actual terrain min/max Z. float minZ = float.MaxValue; float maxZ = float.MinValue; foreach (float height in heightMap) @@ -238,15 +243,15 @@ public sealed class BSTerrainManager Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); - BSTerrainPhys terrainPhys; - if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) + lock (m_terrains) { - // There is already a terrain in this spot. Free the old and build the new. - DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", - BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); - - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:UpdateExisting", delegate() + BSTerrainPhys terrainPhys; + if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) { + // There is already a terrain in this spot. Free the old and build the new. + DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", + BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); + // Remove old terrain from the collection m_terrains.Remove(terrainRegionBase); // Release any physical memory it may be using. @@ -271,35 +276,24 @@ public sealed class BSTerrainManager // I hate doing this, but just bail return; } - }); - } - else - { - // We don't know about this terrain so either we are creating a new terrain or - // our mega-prim child is giving us a new terrain to add to the phys world - - // if this is a child terrain, calculate a unique terrain id - uint newTerrainID = id; - if (newTerrainID >= BSScene.CHILDTERRAIN_ID) - newTerrainID = ++m_terrainCount; - - float[] heightMapX = heightMap; - Vector3 minCoordsX = minCoords; - Vector3 maxCoordsX = maxCoords; + } + else + { + // We don't know about this terrain so either we are creating a new terrain or + // our mega-prim child is giving us a new terrain to add to the phys world - DetailLog("{0},UpdateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", - BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); + // if this is a child terrain, calculate a unique terrain id + uint newTerrainID = id; + if (newTerrainID >= BSScene.CHILDTERRAIN_ID) + newTerrainID = ++m_terrainCount; - // Code that must happen at taint-time - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:NewTerrain", delegate() - { - DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", - BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); + DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", + BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; - }); + } } } @@ -349,6 +343,7 @@ public sealed class BSTerrainManager // with the same parameters as last time. if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) return lastHeight; + m_terrainModified = false; lastHeightTX = tX; lastHeightTY = tY; @@ -358,19 +353,19 @@ public sealed class BSTerrainManager int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); - BSTerrainPhys physTerrain; - if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) + lock (m_terrains) { - ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ); - DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,loc={1},base={2},height={3}", - BSScene.DetailLogZero, loc, terrainBaseXYZ, ret); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, PhysicsScene.RegionName, tX, tY); + BSTerrainPhys physTerrain; + if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) + { + ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ); + } + else + { + PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", + LogHeader, PhysicsScene.RegionName, tX, tY); + } } - m_terrainModified = false; lastHeight = ret; return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index dca7150..d7afdeb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -217,8 +217,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys } } verticesCount = verticesCount / 3; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}", - BSScene.DetailLogZero, verticesCount); for (int yy = 0; yy < sizeY; yy++) { @@ -235,8 +233,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys indicesCount += 6; } } - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG - LogHeader, indicesCount); // DEBUG ret = true; } catch (Exception e) -- cgit v1.1