diff options
author | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
commit | 134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch) | |
tree | 216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/PhysicsModules/BulletS/BSTerrainManager.cs | |
parent | More changing to production grid. Double oops. (diff) | |
download | opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2 opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz |
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/PhysicsModules/BulletS/BSTerrainManager.cs (renamed from OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs) | 244 |
1 files changed, 185 insertions, 59 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/PhysicsModules/BulletS/BSTerrainManager.cs index 2e9db39..d11baa6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSTerrainManager.cs | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
@@ -30,15 +30,14 @@ using System.Text; | |||
30 | 30 | ||
31 | using OpenSim.Framework; | 31 | using OpenSim.Framework; |
32 | using OpenSim.Region.Framework; | 32 | using OpenSim.Region.Framework; |
33 | using OpenSim.Region.CoreModules; | 33 | using OpenSim.Region.PhysicsModules.SharedBase; |
34 | using OpenSim.Region.Physics.Manager; | ||
35 | 34 | ||
36 | using Nini.Config; | 35 | using Nini.Config; |
37 | using log4net; | 36 | using log4net; |
38 | 37 | ||
39 | using OpenMetaverse; | 38 | using OpenMetaverse; |
40 | 39 | ||
41 | namespace OpenSim.Region.Physics.BulletSPlugin | 40 | namespace OpenSim.Region.PhysicsModule.BulletS |
42 | { | 41 | { |
43 | 42 | ||
44 | // The physical implementation of the terrain is wrapped in this class. | 43 | // The physical implementation of the terrain is wrapped in this class. |
@@ -50,14 +49,14 @@ public abstract class BSTerrainPhys : IDisposable | |||
50 | Mesh = 1 | 49 | Mesh = 1 |
51 | } | 50 | } |
52 | 51 | ||
53 | public BSScene PhysicsScene { get; private set; } | 52 | protected BSScene m_physicsScene { get; private set; } |
54 | // Base of the region in world coordinates. Coordinates inside the region are relative to this. | 53 | // Base of the region in world coordinates. Coordinates inside the region are relative to this. |
55 | public Vector3 TerrainBase { get; private set; } | 54 | public Vector3 TerrainBase { get; private set; } |
56 | public uint ID { get; private set; } | 55 | public uint ID { get; private set; } |
57 | 56 | ||
58 | public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) | 57 | public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) |
59 | { | 58 | { |
60 | PhysicsScene = physicsScene; | 59 | m_physicsScene = physicsScene; |
61 | TerrainBase = regionBase; | 60 | TerrainBase = regionBase; |
62 | ID = id; | 61 | ID = id; |
63 | } | 62 | } |
@@ -86,7 +85,7 @@ public sealed class BSTerrainManager : IDisposable | |||
86 | public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); | 85 | public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); |
87 | 86 | ||
88 | // The scene that I am part of | 87 | // The scene that I am part of |
89 | private BSScene PhysicsScene { get; set; } | 88 | private BSScene m_physicsScene { get; set; } |
90 | 89 | ||
91 | // The ground plane created to keep thing from falling to infinity. | 90 | // The ground plane created to keep thing from falling to infinity. |
92 | private BulletBody m_groundPlane; | 91 | private BulletBody m_groundPlane; |
@@ -111,9 +110,11 @@ public sealed class BSTerrainManager : IDisposable | |||
111 | private Vector3 m_worldMax; | 110 | private Vector3 m_worldMax; |
112 | private PhysicsScene MegaRegionParentPhysicsScene { get; set; } | 111 | private PhysicsScene MegaRegionParentPhysicsScene { get; set; } |
113 | 112 | ||
114 | public BSTerrainManager(BSScene physicsScene) | 113 | public BSTerrainManager(BSScene physicsScene, Vector3 regionSize) |
115 | { | 114 | { |
116 | PhysicsScene = physicsScene; | 115 | m_physicsScene = physicsScene; |
116 | DefaultRegionSize = regionSize; | ||
117 | |||
117 | m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); | 118 | m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); |
118 | 119 | ||
119 | // Assume one region of default size | 120 | // Assume one region of default size |
@@ -132,32 +133,39 @@ public sealed class BSTerrainManager : IDisposable | |||
132 | // safe to call Bullet in real time. We hope no one is moving prims around yet. | 133 | // safe to call Bullet in real time. We hope no one is moving prims around yet. |
133 | public void CreateInitialGroundPlaneAndTerrain() | 134 | public void CreateInitialGroundPlaneAndTerrain() |
134 | { | 135 | { |
136 | DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName); | ||
135 | // The ground plane is here to catch things that are trying to drop to negative infinity | 137 | // The ground plane is here to catch things that are trying to drop to negative infinity |
136 | BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); | 138 | BulletShape groundPlaneShape = m_physicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); |
137 | m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, | 139 | Vector3 groundPlaneAltitude = new Vector3(0f, 0f, BSParam.TerrainGroundPlane); |
138 | BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity); | 140 | m_groundPlane = m_physicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, |
141 | BSScene.GROUNDPLANE_ID, groundPlaneAltitude, Quaternion.Identity); | ||
139 | 142 | ||
140 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane); | ||
141 | PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane); | ||
142 | // Ground plane does not move | ||
143 | PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION); | ||
144 | // Everything collides with the ground plane. | 143 | // Everything collides with the ground plane. |
145 | m_groundPlane.collisionType = CollisionType.Groundplane; | 144 | m_groundPlane.collisionType = CollisionType.Groundplane; |
146 | m_groundPlane.ApplyCollisionMask(PhysicsScene); | ||
147 | 145 | ||
148 | // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. | 146 | m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_groundPlane); |
149 | BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); | 147 | m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_groundPlane); |
150 | m_terrains.Add(Vector3.Zero, initialTerrain); | 148 | |
149 | // Ground plane does not move | ||
150 | m_physicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION); | ||
151 | |||
152 | BSTerrainPhys initialTerrain = new BSTerrainHeightmap(m_physicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); | ||
153 | lock (m_terrains) | ||
154 | { | ||
155 | // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. | ||
156 | m_terrains.Add(Vector3.Zero, initialTerrain); | ||
157 | } | ||
151 | } | 158 | } |
152 | 159 | ||
153 | // Release all the terrain structures we might have allocated | 160 | // Release all the terrain structures we might have allocated |
154 | public void ReleaseGroundPlaneAndTerrain() | 161 | public void ReleaseGroundPlaneAndTerrain() |
155 | { | 162 | { |
163 | DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName); | ||
156 | if (m_groundPlane.HasPhysicalBody) | 164 | if (m_groundPlane.HasPhysicalBody) |
157 | { | 165 | { |
158 | if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) | 166 | if (m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_groundPlane)) |
159 | { | 167 | { |
160 | PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane); | 168 | m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_groundPlane); |
161 | } | 169 | } |
162 | m_groundPlane.Clear(); | 170 | m_groundPlane.Clear(); |
163 | } | 171 | } |
@@ -183,7 +191,7 @@ public sealed class BSTerrainManager : IDisposable | |||
183 | float[] localHeightMap = heightMap; | 191 | float[] localHeightMap = heightMap; |
184 | // If there are multiple requests for changes to the same terrain between ticks, | 192 | // If there are multiple requests for changes to the same terrain between ticks, |
185 | // only do that last one. | 193 | // only do that last one. |
186 | PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() | 194 | m_physicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() |
187 | { | 195 | { |
188 | if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) | 196 | if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) |
189 | { | 197 | { |
@@ -193,11 +201,9 @@ public sealed class BSTerrainManager : IDisposable | |||
193 | // the terrain is added to our parent | 201 | // the terrain is added to our parent |
194 | if (MegaRegionParentPhysicsScene is BSScene) | 202 | if (MegaRegionParentPhysicsScene is BSScene) |
195 | { | 203 | { |
196 | DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", | 204 | DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax); |
197 | BSScene.DetailLogZero, m_worldOffset, m_worldMax); | 205 | ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.AddMegaRegionChildTerrain( |
198 | ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain( | 206 | BSScene.CHILDTERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize); |
199 | BSScene.CHILDTERRAIN_ID, localHeightMap, | ||
200 | m_worldOffset, m_worldOffset + DefaultRegionSize, true); | ||
201 | } | 207 | } |
202 | } | 208 | } |
203 | else | 209 | else |
@@ -205,27 +211,34 @@ public sealed class BSTerrainManager : IDisposable | |||
205 | // If not doing the mega-prim thing, just change the terrain | 211 | // If not doing the mega-prim thing, just change the terrain |
206 | DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); | 212 | DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); |
207 | 213 | ||
208 | UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, | 214 | UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize); |
209 | m_worldOffset, m_worldOffset + DefaultRegionSize, true); | ||
210 | } | 215 | } |
211 | }); | 216 | }); |
212 | } | 217 | } |
213 | 218 | ||
214 | // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain | 219 | // Another region is calling this region and passing a terrain. |
220 | // A region that is not the mega-region root will pass its terrain to the root region so the root region | ||
221 | // physics engine will have all the terrains. | ||
222 | private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) | ||
223 | { | ||
224 | // Since we are called by another region's thread, the action must be rescheduled onto our processing thread. | ||
225 | m_physicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate() | ||
226 | { | ||
227 | UpdateTerrain(id, heightMap, minCoords, maxCoords); | ||
228 | }); | ||
229 | } | ||
230 | |||
231 | // If called for terrain has has not been previously allocated, a new terrain will be built | ||
215 | // based on the passed information. The 'id' should be either the terrain id or | 232 | // based on the passed information. The 'id' should be either the terrain id or |
216 | // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. | 233 | // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. |
217 | // The latter feature is for creating child terrains for mega-regions. | 234 | // The latter feature is for creating child terrains for mega-regions. |
218 | // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new | 235 | // If there is an existing terrain body, a new |
219 | // terrain shape is created and added to the body. | 236 | // terrain shape is created and added to the body. |
220 | // This call is most often used to update the heightMap and parameters of the terrain. | 237 | // This call is most often used to update the heightMap and parameters of the terrain. |
221 | // (The above does suggest that some simplification/refactoring is in order.) | 238 | // (The above does suggest that some simplification/refactoring is in order.) |
222 | // Called during taint-time. | 239 | // Called during taint-time. |
223 | private void UpdateTerrain(uint id, float[] heightMap, | 240 | private void UpdateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) |
224 | Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) | ||
225 | { | 241 | { |
226 | DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}", | ||
227 | BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); | ||
228 | |||
229 | // Find high and low points of passed heightmap. | 242 | // Find high and low points of passed heightmap. |
230 | // The min and max passed in is usually the area objects can be in (maximum | 243 | // The min and max passed in is usually the area objects can be in (maximum |
231 | // object height, for instance). The terrain wants the bounding box for the | 244 | // object height, for instance). The terrain wants the bounding box for the |
@@ -245,6 +258,9 @@ public sealed class BSTerrainManager : IDisposable | |||
245 | minCoords.Z = minZ; | 258 | minCoords.Z = minZ; |
246 | maxCoords.Z = maxZ; | 259 | maxCoords.Z = maxZ; |
247 | 260 | ||
261 | DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1},minC={2},maxC={3}", | ||
262 | BSScene.DetailLogZero, id, minCoords, maxCoords); | ||
263 | |||
248 | Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); | 264 | Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); |
249 | 265 | ||
250 | lock (m_terrains) | 266 | lock (m_terrains) |
@@ -253,8 +269,8 @@ public sealed class BSTerrainManager : IDisposable | |||
253 | if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) | 269 | if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) |
254 | { | 270 | { |
255 | // There is already a terrain in this spot. Free the old and build the new. | 271 | // There is already a terrain in this spot. Free the old and build the new. |
256 | DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", | 272 | DetailLog("{0},BSTerrainManager.UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", |
257 | BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); | 273 | BSScene.DetailLogZero, id, terrainRegionBase, minCoords, maxCoords); |
258 | 274 | ||
259 | // Remove old terrain from the collection | 275 | // Remove old terrain from the collection |
260 | m_terrains.Remove(terrainRegionBase); | 276 | m_terrains.Remove(terrainRegionBase); |
@@ -263,6 +279,7 @@ public sealed class BSTerrainManager : IDisposable | |||
263 | 279 | ||
264 | if (MegaRegionParentPhysicsScene == null) | 280 | if (MegaRegionParentPhysicsScene == null) |
265 | { | 281 | { |
282 | // This terrain is not part of the mega-region scheme. Create vanilla terrain. | ||
266 | BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); | 283 | BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); |
267 | m_terrains.Add(terrainRegionBase, newTerrainPhys); | 284 | m_terrains.Add(terrainRegionBase, newTerrainPhys); |
268 | 285 | ||
@@ -291,8 +308,8 @@ public sealed class BSTerrainManager : IDisposable | |||
291 | if (newTerrainID >= BSScene.CHILDTERRAIN_ID) | 308 | if (newTerrainID >= BSScene.CHILDTERRAIN_ID) |
292 | newTerrainID = ++m_terrainCount; | 309 | newTerrainID = ++m_terrainCount; |
293 | 310 | ||
294 | DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", | 311 | DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", |
295 | BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); | 312 | BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords); |
296 | BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); | 313 | BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); |
297 | m_terrains.Add(terrainRegionBase, newTerrainPhys); | 314 | m_terrains.Add(terrainRegionBase, newTerrainPhys); |
298 | 315 | ||
@@ -304,26 +321,26 @@ public sealed class BSTerrainManager : IDisposable | |||
304 | // TODO: redo terrain implementation selection to allow other base types than heightMap. | 321 | // TODO: redo terrain implementation selection to allow other base types than heightMap. |
305 | private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) | 322 | private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) |
306 | { | 323 | { |
307 | PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", | 324 | m_physicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", |
308 | LogHeader, PhysicsScene.RegionName, terrainRegionBase, | 325 | LogHeader, m_physicsScene.RegionName, terrainRegionBase, |
309 | (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); | 326 | (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); |
310 | BSTerrainPhys newTerrainPhys = null; | 327 | BSTerrainPhys newTerrainPhys = null; |
311 | switch ((int)BSParam.TerrainImplementation) | 328 | switch ((int)BSParam.TerrainImplementation) |
312 | { | 329 | { |
313 | case (int)BSTerrainPhys.TerrainImplementation.Heightmap: | 330 | case (int)BSTerrainPhys.TerrainImplementation.Heightmap: |
314 | newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, | 331 | newTerrainPhys = new BSTerrainHeightmap(m_physicsScene, terrainRegionBase, id, |
315 | heightMap, minCoords, maxCoords); | 332 | heightMap, minCoords, maxCoords); |
316 | break; | 333 | break; |
317 | case (int)BSTerrainPhys.TerrainImplementation.Mesh: | 334 | case (int)BSTerrainPhys.TerrainImplementation.Mesh: |
318 | newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, | 335 | newTerrainPhys = new BSTerrainMesh(m_physicsScene, terrainRegionBase, id, |
319 | heightMap, minCoords, maxCoords); | 336 | heightMap, minCoords, maxCoords); |
320 | break; | 337 | break; |
321 | default: | 338 | default: |
322 | PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", | 339 | m_physicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", |
323 | LogHeader, | 340 | LogHeader, |
324 | (int)BSParam.TerrainImplementation, | 341 | (int)BSParam.TerrainImplementation, |
325 | BSParam.TerrainImplementation, | 342 | BSParam.TerrainImplementation, |
326 | PhysicsScene.RegionName, terrainRegionBase); | 343 | m_physicsScene.RegionName, terrainRegionBase); |
327 | break; | 344 | break; |
328 | } | 345 | } |
329 | return newTerrainPhys; | 346 | return newTerrainPhys; |
@@ -337,6 +354,64 @@ public sealed class BSTerrainManager : IDisposable | |||
337 | return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); | 354 | return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ); |
338 | } | 355 | } |
339 | 356 | ||
357 | // Return a new position that is over known terrain if the position is outside our terrain. | ||
358 | public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) | ||
359 | { | ||
360 | float edgeEpsilon = 0.1f; | ||
361 | |||
362 | Vector3 ret = pPos; | ||
363 | |||
364 | // First, base addresses are never negative so correct for that possible problem. | ||
365 | if (ret.X < 0f || ret.Y < 0f) | ||
366 | { | ||
367 | ret.X = Util.Clamp<float>(ret.X, 0f, 1000000f); | ||
368 | ret.Y = Util.Clamp<float>(ret.Y, 0f, 1000000f); | ||
369 | DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,zeroingNegXorY,oldPos={1},newPos={2}", | ||
370 | BSScene.DetailLogZero, pPos, ret); | ||
371 | } | ||
372 | |||
373 | // Can't do this function if we don't know about any terrain. | ||
374 | if (m_terrains.Count == 0) | ||
375 | return ret; | ||
376 | |||
377 | int loopPrevention = 10; | ||
378 | Vector3 terrainBaseXYZ; | ||
379 | BSTerrainPhys physTerrain; | ||
380 | while (!GetTerrainPhysicalAtXYZ(ret, out physTerrain, out terrainBaseXYZ)) | ||
381 | { | ||
382 | // The passed position is not within a known terrain area. | ||
383 | // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region. | ||
384 | |||
385 | // Must be off the top of a region. Find an adjacent region to move into. | ||
386 | // The returned terrain is always 'lower'. That is, closer to <0,0>. | ||
387 | Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); | ||
388 | |||
389 | if (adjacentTerrainBase.X < terrainBaseXYZ.X) | ||
390 | { | ||
391 | // moving down into a new region in the X dimension. New position will be the max in the new base. | ||
392 | ret.X = adjacentTerrainBase.X + DefaultRegionSize.X - edgeEpsilon; | ||
393 | } | ||
394 | if (adjacentTerrainBase.Y < terrainBaseXYZ.Y) | ||
395 | { | ||
396 | // moving down into a new region in the X dimension. New position will be the max in the new base. | ||
397 | ret.Y = adjacentTerrainBase.Y + DefaultRegionSize.Y - edgeEpsilon; | ||
398 | } | ||
399 | DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", | ||
400 | BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); | ||
401 | |||
402 | if (loopPrevention-- < 0f) | ||
403 | { | ||
404 | // The 'while' is a little dangerous so this prevents looping forever if the | ||
405 | // mapping of the terrains ever gets messed up (like nothing at <0,0>) or | ||
406 | // the list of terrains is in transition. | ||
407 | DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,suppressingFindAdjacentRegionLoop", BSScene.DetailLogZero); | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | |||
412 | return ret; | ||
413 | } | ||
414 | |||
340 | // Given an X and Y, find the height of the terrain. | 415 | // Given an X and Y, find the height of the terrain. |
341 | // Since we could be handling multiple terrains for a mega-region, | 416 | // Since we could be handling multiple terrains for a mega-region, |
342 | // the base of the region is calcuated assuming all regions are | 417 | // the base of the region is calcuated assuming all regions are |
@@ -368,8 +443,8 @@ public sealed class BSTerrainManager : IDisposable | |||
368 | } | 443 | } |
369 | else | 444 | else |
370 | { | 445 | { |
371 | PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", | 446 | m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", |
372 | LogHeader, PhysicsScene.RegionName, tX, tY); | 447 | LogHeader, m_physicsScene.RegionName, tX, tY); |
373 | DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", | 448 | DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", |
374 | BSScene.DetailLogZero, pos, terrainBaseXYZ); | 449 | BSScene.DetailLogZero, pos, terrainBaseXYZ); |
375 | } | 450 | } |
@@ -390,8 +465,8 @@ public sealed class BSTerrainManager : IDisposable | |||
390 | } | 465 | } |
391 | else | 466 | else |
392 | { | 467 | { |
393 | PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", | 468 | m_physicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", |
394 | LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); | 469 | LogHeader, m_physicsScene.RegionName, pos, terrainBaseXYZ, ret); |
395 | } | 470 | } |
396 | return ret; | 471 | return ret; |
397 | } | 472 | } |
@@ -400,18 +475,69 @@ public sealed class BSTerrainManager : IDisposable | |||
400 | // the descriptor class and the 'base' fo the addresses therein. | 475 | // the descriptor class and the 'base' fo the addresses therein. |
401 | private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) | 476 | private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase) |
402 | { | 477 | { |
403 | int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; | 478 | bool ret = false; |
404 | int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; | 479 | |
405 | Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); | 480 | Vector3 terrainBaseXYZ = Vector3.Zero; |
481 | if (pos.X < 0f || pos.Y < 0f) | ||
482 | { | ||
483 | // We don't handle negative addresses so just make up a base that will not be found. | ||
484 | terrainBaseXYZ = new Vector3(-DefaultRegionSize.X, -DefaultRegionSize.Y, 0f); | ||
485 | } | ||
486 | else | ||
487 | { | ||
488 | int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; | ||
489 | int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; | ||
490 | terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); | ||
491 | } | ||
406 | 492 | ||
407 | BSTerrainPhys physTerrain = null; | 493 | BSTerrainPhys physTerrain = null; |
408 | lock (m_terrains) | 494 | lock (m_terrains) |
409 | { | 495 | { |
410 | m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); | 496 | ret = m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain); |
411 | } | 497 | } |
412 | outTerrainBase = terrainBaseXYZ; | 498 | outTerrainBase = terrainBaseXYZ; |
413 | outPhysTerrain = physTerrain; | 499 | outPhysTerrain = physTerrain; |
414 | return (physTerrain != null); | 500 | return ret; |
501 | } | ||
502 | |||
503 | // Given a terrain base, return a terrain base for a terrain that is closer to <0,0> than | ||
504 | // this one. Usually used to return an out of bounds object to a known place. | ||
505 | private Vector3 FindAdjacentTerrainBase(Vector3 pTerrainBase) | ||
506 | { | ||
507 | Vector3 ret = pTerrainBase; | ||
508 | |||
509 | // Can't do this function if we don't know about any terrain. | ||
510 | if (m_terrains.Count == 0) | ||
511 | return ret; | ||
512 | |||
513 | // Just some sanity | ||
514 | ret.X = Util.Clamp<float>(ret.X, 0f, 1000000f); | ||
515 | ret.Y = Util.Clamp<float>(ret.Y, 0f, 1000000f); | ||
516 | ret.Z = 0f; | ||
517 | |||
518 | lock (m_terrains) | ||
519 | { | ||
520 | // Once down to the <0,0> region, we have to be done. | ||
521 | while (ret.X > 0f || ret.Y > 0f) | ||
522 | { | ||
523 | if (ret.X > 0f) | ||
524 | { | ||
525 | ret.X = Math.Max(0f, ret.X - DefaultRegionSize.X); | ||
526 | DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingX,terrainBase={1}", BSScene.DetailLogZero, ret); | ||
527 | if (m_terrains.ContainsKey(ret)) | ||
528 | break; | ||
529 | } | ||
530 | if (ret.Y > 0f) | ||
531 | { | ||
532 | ret.Y = Math.Max(0f, ret.Y - DefaultRegionSize.Y); | ||
533 | DetailLog("{0},BSTerrainManager.FindAdjacentTerrainBase,reducingY,terrainBase={1}", BSScene.DetailLogZero, ret); | ||
534 | if (m_terrains.ContainsKey(ret)) | ||
535 | break; | ||
536 | } | ||
537 | } | ||
538 | } | ||
539 | |||
540 | return ret; | ||
415 | } | 541 | } |
416 | 542 | ||
417 | // Although no one seems to check this, I do support combining. | 543 | // Although no one seems to check this, I do support combining. |
@@ -452,7 +578,7 @@ public sealed class BSTerrainManager : IDisposable | |||
452 | 578 | ||
453 | private void DetailLog(string msg, params Object[] args) | 579 | private void DetailLog(string msg, params Object[] args) |
454 | { | 580 | { |
455 | PhysicsScene.PhysicsLogging.Write(msg, args); | 581 | m_physicsScene.PhysicsLogging.Write(msg, args); |
456 | } | 582 | } |
457 | } | 583 | } |
458 | } | 584 | } |