diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | 111 |
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 | } |