aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs111
1 files changed, 63 insertions, 48 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index b2fb835..441d2d3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -50,14 +50,14 @@ public abstract class BSTerrainPhys : IDisposable
50 Mesh = 1 50 Mesh = 1
51 } 51 }
52 52
53 public BSScene PhysicsScene { get; private set; } 53 protected BSScene m_physicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this. 54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; } 55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; } 56 public uint ID { get; private set; }
57 57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) 58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 { 59 {
60 PhysicsScene = physicsScene; 60 m_physicsScene = physicsScene;
61 TerrainBase = regionBase; 61 TerrainBase = regionBase;
62 ID = id; 62 ID = id;
63 } 63 }
@@ -86,7 +86,7 @@ public sealed class BSTerrainManager : IDisposable
86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
87 87
88 // The scene that I am part of 88 // The scene that I am part of
89 private BSScene PhysicsScene { get; set; } 89 private BSScene m_physicsScene { get; set; }
90 90
91 // The ground plane created to keep thing from falling to infinity. 91 // The ground plane created to keep thing from falling to infinity.
92 private BulletBody m_groundPlane; 92 private BulletBody m_groundPlane;
@@ -113,7 +113,7 @@ public sealed class BSTerrainManager : IDisposable
113 113
114 public BSTerrainManager(BSScene physicsScene) 114 public BSTerrainManager(BSScene physicsScene)
115 { 115 {
116 PhysicsScene = physicsScene; 116 m_physicsScene = physicsScene;
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); 117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118 118
119 // Assume one region of default size 119 // Assume one region of default size
@@ -132,21 +132,22 @@ public sealed class BSTerrainManager : IDisposable
132 // safe to call Bullet in real time. We hope no one is moving prims around yet. 132 // safe to call Bullet in real time. We hope no one is moving prims around yet.
133 public void CreateInitialGroundPlaneAndTerrain() 133 public void CreateInitialGroundPlaneAndTerrain()
134 { 134 {
135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
136 // The ground plane is here to catch things that are trying to drop to negative infinity 136 // The ground plane is here to catch things that are trying to drop to negative infinity
137 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); 137 BulletShape groundPlaneShape = m_physicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
138 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, 138 m_groundPlane = m_physicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity); 139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);
140 140
141 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane);
142 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane);
143 // Ground plane does not move
144 PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
145 // Everything collides with the ground plane. 141 // Everything collides with the ground plane.
146 m_groundPlane.collisionType = CollisionType.Groundplane; 142 m_groundPlane.collisionType = CollisionType.Groundplane;
147 m_groundPlane.ApplyCollisionMask(PhysicsScene);
148 143
149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 144 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_groundPlane);
145 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_groundPlane);
146
147 // Ground plane does not move
148 m_physicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
149
150 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(m_physicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
150 lock (m_terrains) 151 lock (m_terrains)
151 { 152 {
152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. 153 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
@@ -157,12 +158,12 @@ public sealed class BSTerrainManager : IDisposable
157 // Release all the terrain structures we might have allocated 158 // Release all the terrain structures we might have allocated
158 public void ReleaseGroundPlaneAndTerrain() 159 public void ReleaseGroundPlaneAndTerrain()
159 { 160 {
160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 161 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
161 if (m_groundPlane.HasPhysicalBody) 162 if (m_groundPlane.HasPhysicalBody)
162 { 163 {
163 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) 164 if (m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_groundPlane))
164 { 165 {
165 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane); 166 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_groundPlane);
166 } 167 }
167 m_groundPlane.Clear(); 168 m_groundPlane.Clear();
168 } 169 }
@@ -188,7 +189,7 @@ public sealed class BSTerrainManager : IDisposable
188 float[] localHeightMap = heightMap; 189 float[] localHeightMap = heightMap;
189 // If there are multiple requests for changes to the same terrain between ticks, 190 // If there are multiple requests for changes to the same terrain between ticks,
190 // only do that last one. 191 // only do that last one.
191 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() 192 m_physicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
192 { 193 {
193 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 194 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
194 { 195 {
@@ -199,15 +200,8 @@ public sealed class BSTerrainManager : IDisposable
199 if (MegaRegionParentPhysicsScene is BSScene) 200 if (MegaRegionParentPhysicsScene is BSScene)
200 { 201 {
201 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax); 202 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax);
202 // This looks really odd but this region is passing its terrain to its mega-region root region 203 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.AddMegaRegionChildTerrain(
203 // and the creation of the terrain must happen on the root region's taint thread and not 204 BSScene.CHILDTERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize);
204 // my taint thread.
205 ((BSScene)MegaRegionParentPhysicsScene).PostTaintObject("TerrainManager.SetTerrain.Mega-" + m_worldOffset.ToString(), 0, delegate()
206 {
207 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
208 BSScene.CHILDTERRAIN_ID, localHeightMap,
209 m_worldOffset, m_worldOffset + DefaultRegionSize, true /* inTaintTime */);
210 });
211 } 205 }
212 } 206 }
213 else 207 else
@@ -215,12 +209,23 @@ public sealed class BSTerrainManager : IDisposable
215 // If not doing the mega-prim thing, just change the terrain 209 // If not doing the mega-prim thing, just change the terrain
216 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); 210 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
217 211
218 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, 212 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize);
219 m_worldOffset, m_worldOffset + DefaultRegionSize, true /* inTaintTime */);
220 } 213 }
221 }); 214 });
222 } 215 }
223 216
217 // Another region is calling this region and passing a terrain.
218 // A region that is not the mega-region root will pass its terrain to the root region so the root region
219 // physics engine will have all the terrains.
220 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
221 {
222 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
223 m_physicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
224 {
225 UpdateTerrain(id, heightMap, minCoords, maxCoords);
226 });
227 }
228
224 // If called for terrain has has not been previously allocated, a new terrain will be built 229 // If called for terrain has has not been previously allocated, a new terrain will be built
225 // based on the passed information. The 'id' should be either the terrain id or 230 // based on the passed information. The 'id' should be either the terrain id or
226 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. 231 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
@@ -230,11 +235,10 @@ public sealed class BSTerrainManager : IDisposable
230 // This call is most often used to update the heightMap and parameters of the terrain. 235 // This call is most often used to update the heightMap and parameters of the terrain.
231 // (The above does suggest that some simplification/refactoring is in order.) 236 // (The above does suggest that some simplification/refactoring is in order.)
232 // Called during taint-time. 237 // Called during taint-time.
233 private void UpdateTerrain(uint id, float[] heightMap, 238 private void UpdateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
234 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
235 { 239 {
236 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1},minC={2},maxC={3},inTaintTime={4}", 240 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1},minC={2},maxC={3}",
237 BSScene.DetailLogZero, id, minCoords, maxCoords, inTaintTime); 241 BSScene.DetailLogZero, id, minCoords, maxCoords);
238 242
239 // Find high and low points of passed heightmap. 243 // Find high and low points of passed heightmap.
240 // The min and max passed in is usually the area objects can be in (maximum 244 // The min and max passed in is usually the area objects can be in (maximum
@@ -303,7 +307,7 @@ public sealed class BSTerrainManager : IDisposable
303 newTerrainID = ++m_terrainCount; 307 newTerrainID = ++m_terrainCount;
304 308
305 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", 309 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
306 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); 310 BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords);
307 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); 311 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
308 m_terrains.Add(terrainRegionBase, newTerrainPhys); 312 m_terrains.Add(terrainRegionBase, newTerrainPhys);
309 313
@@ -315,26 +319,26 @@ public sealed class BSTerrainManager : IDisposable
315 // TODO: redo terrain implementation selection to allow other base types than heightMap. 319 // TODO: redo terrain implementation selection to allow other base types than heightMap.
316 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 320 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
317 { 321 {
318 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", 322 m_physicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
319 LogHeader, PhysicsScene.RegionName, terrainRegionBase, 323 LogHeader, m_physicsScene.RegionName, terrainRegionBase,
320 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); 324 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
321 BSTerrainPhys newTerrainPhys = null; 325 BSTerrainPhys newTerrainPhys = null;
322 switch ((int)BSParam.TerrainImplementation) 326 switch ((int)BSParam.TerrainImplementation)
323 { 327 {
324 case (int)BSTerrainPhys.TerrainImplementation.Heightmap: 328 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
325 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, 329 newTerrainPhys = new BSTerrainHeightmap(m_physicsScene, terrainRegionBase, id,
326 heightMap, minCoords, maxCoords); 330 heightMap, minCoords, maxCoords);
327 break; 331 break;
328 case (int)BSTerrainPhys.TerrainImplementation.Mesh: 332 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
329 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, 333 newTerrainPhys = new BSTerrainMesh(m_physicsScene, terrainRegionBase, id,
330 heightMap, minCoords, maxCoords); 334 heightMap, minCoords, maxCoords);
331 break; 335 break;
332 default: 336 default:
333 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", 337 m_physicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
334 LogHeader, 338 LogHeader,
335 (int)BSParam.TerrainImplementation, 339 (int)BSParam.TerrainImplementation,
336 BSParam.TerrainImplementation, 340 BSParam.TerrainImplementation,
337 PhysicsScene.RegionName, terrainRegionBase); 341 m_physicsScene.RegionName, terrainRegionBase);
338 break; 342 break;
339 } 343 }
340 return newTerrainPhys; 344 return newTerrainPhys;
@@ -351,6 +355,8 @@ public sealed class BSTerrainManager : IDisposable
351 // Return a new position that is over known terrain if the position is outside our terrain. 355 // Return a new position that is over known terrain if the position is outside our terrain.
352 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) 356 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos)
353 { 357 {
358 float edgeEpsilon = 0.1f;
359
354 Vector3 ret = pPos; 360 Vector3 ret = pPos;
355 361
356 // First, base addresses are never negative so correct for that possible problem. 362 // First, base addresses are never negative so correct for that possible problem.
@@ -375,10 +381,19 @@ public sealed class BSTerrainManager : IDisposable
375 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region. 381 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region.
376 382
377 // Must be off the top of a region. Find an adjacent region to move into. 383 // Must be off the top of a region. Find an adjacent region to move into.
384 // The returned terrain is always 'lower'. That is, closer to <0,0>.
378 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); 385 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
379 386
380 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + (ret.X % DefaultRegionSize.X)); 387 if (adjacentTerrainBase.X < terrainBaseXYZ.X)
381 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y)); 388 {
389 // moving down into a new region in the X dimension. New position will be the max in the new base.
390 ret.X = adjacentTerrainBase.X + DefaultRegionSize.X - edgeEpsilon;
391 }
392 if (adjacentTerrainBase.Y < terrainBaseXYZ.Y)
393 {
394 // moving down into a new region in the X dimension. New position will be the max in the new base.
395 ret.Y = adjacentTerrainBase.Y + DefaultRegionSize.Y - edgeEpsilon;
396 }
382 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", 397 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
383 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); 398 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
384 399
@@ -426,8 +441,8 @@ public sealed class BSTerrainManager : IDisposable
426 } 441 }
427 else 442 else
428 { 443 {
429 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", 444 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
430 LogHeader, PhysicsScene.RegionName, tX, tY); 445 LogHeader, m_physicsScene.RegionName, tX, tY);
431 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", 446 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
432 BSScene.DetailLogZero, pos, terrainBaseXYZ); 447 BSScene.DetailLogZero, pos, terrainBaseXYZ);
433 } 448 }
@@ -448,8 +463,8 @@ public sealed class BSTerrainManager : IDisposable
448 } 463 }
449 else 464 else
450 { 465 {
451 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", 466 m_physicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}",
452 LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); 467 LogHeader, m_physicsScene.RegionName, pos, terrainBaseXYZ, ret);
453 } 468 }
454 return ret; 469 return ret;
455 } 470 }
@@ -561,7 +576,7 @@ public sealed class BSTerrainManager : IDisposable
561 576
562 private void DetailLog(string msg, params Object[] args) 577 private void DetailLog(string msg, params Object[] args)
563 { 578 {
564 PhysicsScene.PhysicsLogging.Write(msg, args); 579 m_physicsScene.PhysicsLogging.Write(msg, args);
565 } 580 }
566} 581}
567} 582}