diff options
author | Justin Clark-Casey (justincc) | 2012-07-20 23:20:40 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-07-20 23:20:40 +0100 |
commit | ef14232e64c659cb3f0f1bb690e6ce4ac0f3e075 (patch) | |
tree | 23037bef0445a91cb764468c8e44eb121198095b /OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |
parent | Move RegionConfig.ini.example into bin/Regions/Regions.ini.example - all othe... (diff) | |
parent | BulletSim: more detail logging for vehicle and general physics debugging. (diff) | |
download | opensim-SC_OLD-ef14232e64c659cb3f0f1bb690e6ce4ac0f3e075.zip opensim-SC_OLD-ef14232e64c659cb3f0f1bb690e6ce4ac0f3e075.tar.gz opensim-SC_OLD-ef14232e64c659cb3f0f1bb690e6ce4ac0f3e075.tar.bz2 opensim-SC_OLD-ef14232e64c659cb3f0f1bb690e6ce4ac0f3e075.tar.xz |
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 136 |
1 files changed, 105 insertions, 31 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 417cb5f..9d41ce8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -29,12 +29,13 @@ using System.Collections.Generic; | |||
29 | using System.Runtime.InteropServices; | 29 | using System.Runtime.InteropServices; |
30 | using System.Text; | 30 | using System.Text; |
31 | using System.Threading; | 31 | using System.Threading; |
32 | using Nini.Config; | ||
33 | using log4net; | ||
34 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Region.Framework; | ||
35 | using OpenSim.Region.Physics.Manager; | 34 | using OpenSim.Region.Physics.Manager; |
35 | using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging; | ||
36 | using Nini.Config; | ||
37 | using log4net; | ||
36 | using OpenMetaverse; | 38 | using OpenMetaverse; |
37 | using OpenSim.Region.Framework; | ||
38 | 39 | ||
39 | // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) | 40 | // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) |
40 | // Debug linkset | 41 | // Debug linkset |
@@ -44,15 +45,17 @@ using OpenSim.Region.Framework; | |||
44 | // Compute physics FPS reasonably | 45 | // Compute physics FPS reasonably |
45 | // Based on material, set density and friction | 46 | // Based on material, set density and friction |
46 | // More efficient memory usage when passing hull information from BSPrim to BulletSim | 47 | // More efficient memory usage when passing hull information from BSPrim to BulletSim |
48 | // Move all logic out of the C++ code and into the C# code for easier future modifications. | ||
47 | // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? | 49 | // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? |
48 | // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) | 50 | // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) |
49 | // At the moment, physical and phantom causes object to drop through the terrain | 51 | // At the moment, physical and phantom causes object to drop through the terrain |
50 | // Physical phantom objects and related typing (collision options ) | 52 | // Physical phantom objects and related typing (collision options ) |
53 | // Use collision masks for collision with terrain and phantom objects | ||
51 | // Check out llVolumeDetect. Must do something for that. | 54 | // Check out llVolumeDetect. Must do something for that. |
52 | // Should prim.link() and prim.delink() membership checking happen at taint time? | 55 | // Should prim.link() and prim.delink() membership checking happen at taint time? |
56 | // changing the position and orientation of a linked prim must rebuild the constraint with the root. | ||
53 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once | 57 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once |
54 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect | 58 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect |
55 | // Use collision masks for collision with terrain and phantom objects | ||
56 | // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) | 59 | // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) |
57 | // Implement LockAngularMotion | 60 | // Implement LockAngularMotion |
58 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) | 61 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) |
@@ -60,9 +63,6 @@ using OpenSim.Region.Framework; | |||
60 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. | 63 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. |
61 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? | 64 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? |
62 | // Check terrain size. 128 or 127? | 65 | // Check terrain size. 128 or 127? |
63 | // Multiple contact points on collision? | ||
64 | // See code in ode::near... calls to collision_accounting_events() | ||
65 | // (This might not be a problem. ODE collects all the collisions with one object in one tick.) | ||
66 | // Raycast | 66 | // Raycast |
67 | // | 67 | // |
68 | namespace OpenSim.Region.Physics.BulletSPlugin | 68 | namespace OpenSim.Region.Physics.BulletSPlugin |
@@ -72,6 +72,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
72 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 72 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
73 | private static readonly string LogHeader = "[BULLETS SCENE]"; | 73 | private static readonly string LogHeader = "[BULLETS SCENE]"; |
74 | 74 | ||
75 | private void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } | ||
76 | |||
75 | public string BulletSimVersion = "?"; | 77 | public string BulletSimVersion = "?"; |
76 | 78 | ||
77 | private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); | 79 | private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); |
@@ -105,6 +107,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
105 | private long m_simulationStep = 0; | 107 | private long m_simulationStep = 0; |
106 | public long SimulationStep { get { return m_simulationStep; } } | 108 | public long SimulationStep { get { return m_simulationStep; } } |
107 | 109 | ||
110 | public float LastSimulatedTimestep { get; private set; } | ||
111 | |||
108 | // A value of the time now so all the collision and update routines do not have to get their own | 112 | // A value of the time now so all the collision and update routines do not have to get their own |
109 | // Set to 'now' just before all the prims and actors are called for collisions and updates | 113 | // Set to 'now' just before all the prims and actors are called for collisions and updates |
110 | private int m_simulationNowTime; | 114 | private int m_simulationNowTime; |
@@ -121,6 +125,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
121 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed | 125 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed |
122 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes | 126 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes |
123 | 127 | ||
128 | public float PID_D { get; private set; } // derivative | ||
129 | public float PID_P { get; private set; } // proportional | ||
130 | |||
124 | public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero | 131 | public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero |
125 | public const uint GROUNDPLANE_ID = 1; | 132 | public const uint GROUNDPLANE_ID = 1; |
126 | 133 | ||
@@ -147,8 +154,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
147 | ConfigurationParameters[] m_params; | 154 | ConfigurationParameters[] m_params; |
148 | GCHandle m_paramsHandle; | 155 | GCHandle m_paramsHandle; |
149 | 156 | ||
157 | public bool shouldDebugLog { get; private set; } | ||
158 | |||
150 | private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; | 159 | private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; |
151 | 160 | ||
161 | // Sometimes you just have to log everything. | ||
162 | public Logging.LogWriter PhysicsLogging; | ||
163 | private bool m_physicsLoggingEnabled; | ||
164 | private string m_physicsLoggingDir; | ||
165 | private string m_physicsLoggingPrefix; | ||
166 | private int m_physicsLoggingFileMinutes; | ||
167 | |||
168 | private bool m_vehicleLoggingEnabled; | ||
169 | public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } } | ||
170 | |||
152 | public BSScene(string identifier) | 171 | public BSScene(string identifier) |
153 | { | 172 | { |
154 | m_initialized = false; | 173 | m_initialized = false; |
@@ -169,17 +188,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
169 | m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; | 188 | m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; |
170 | m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); | 189 | m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); |
171 | 190 | ||
191 | // Enable very detailed logging. | ||
192 | // By creating an empty logger when not logging, the log message invocation code | ||
193 | // can be left in and every call doesn't have to check for null. | ||
194 | if (m_physicsLoggingEnabled) | ||
195 | { | ||
196 | PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); | ||
197 | } | ||
198 | else | ||
199 | { | ||
200 | PhysicsLogging = new Logging.LogWriter(); | ||
201 | } | ||
202 | |||
172 | // Get the version of the DLL | 203 | // Get the version of the DLL |
173 | // TODO: this doesn't work yet. Something wrong with marshaling the returned string. | 204 | // TODO: this doesn't work yet. Something wrong with marshaling the returned string. |
174 | // BulletSimVersion = BulletSimAPI.GetVersion(); | 205 | // BulletSimVersion = BulletSimAPI.GetVersion(); |
175 | // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); | 206 | // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); |
176 | 207 | ||
177 | // if Debug, enable logging from the unmanaged code | 208 | // if Debug, enable logging from the unmanaged code |
178 | if (m_log.IsDebugEnabled) | 209 | if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) |
179 | { | 210 | { |
180 | m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); | 211 | m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); |
181 | // the handle is saved to it doesn't get freed after this call | 212 | if (PhysicsLogging.Enabled) |
182 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); | 213 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); |
214 | else | ||
215 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); | ||
216 | // the handle is saved in a variable to make sure it doesn't get freed after this call | ||
183 | BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); | 217 | BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); |
184 | } | 218 | } |
185 | 219 | ||
@@ -209,6 +243,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
209 | m_meshLOD = 8f; | 243 | m_meshLOD = 8f; |
210 | m_sculptLOD = 32f; | 244 | m_sculptLOD = 32f; |
211 | 245 | ||
246 | shouldDebugLog = false; | ||
212 | m_detailedStatsStep = 0; // disabled | 247 | m_detailedStatsStep = 0; // disabled |
213 | 248 | ||
214 | m_maxSubSteps = 10; | 249 | m_maxSubSteps = 10; |
@@ -217,6 +252,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
217 | m_maxUpdatesPerFrame = 2048; | 252 | m_maxUpdatesPerFrame = 2048; |
218 | m_maximumObjectMass = 10000.01f; | 253 | m_maximumObjectMass = 10000.01f; |
219 | 254 | ||
255 | PID_D = 2200f; | ||
256 | PID_P = 900f; | ||
257 | |||
220 | parms.defaultFriction = 0.5f; | 258 | parms.defaultFriction = 0.5f; |
221 | parms.defaultDensity = 10.000006836f; // Aluminum g/cm3 | 259 | parms.defaultDensity = 10.000006836f; // Aluminum g/cm3 |
222 | parms.defaultRestitution = 0f; | 260 | parms.defaultRestitution = 0f; |
@@ -261,7 +299,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
261 | _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); | 299 | _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); |
262 | _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); | 300 | _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); |
263 | 301 | ||
302 | shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog); | ||
264 | m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); | 303 | m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); |
304 | |||
265 | m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); | 305 | m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); |
266 | m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); | 306 | m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); |
267 | 307 | ||
@@ -271,6 +311,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
271 | m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame); | 311 | m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame); |
272 | m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass); | 312 | m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass); |
273 | 313 | ||
314 | PID_D = pConfig.GetFloat("PIDDerivative", PID_D); | ||
315 | PID_P = pConfig.GetFloat("PIDProportional", PID_P); | ||
316 | |||
274 | parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction); | 317 | parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction); |
275 | parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity); | 318 | parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity); |
276 | parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution); | 319 | parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution); |
@@ -303,6 +346,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
303 | parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands); | 346 | parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands); |
304 | parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching); | 347 | parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching); |
305 | parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations); | 348 | parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations); |
349 | |||
350 | // Very detailed logging for physics debugging | ||
351 | m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); | ||
352 | m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); | ||
353 | m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); | ||
354 | m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); | ||
355 | // Very detailed logging for vehicle debugging | ||
356 | m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); | ||
306 | } | 357 | } |
307 | } | 358 | } |
308 | m_params[0] = parms; | 359 | m_params[0] = parms; |
@@ -323,12 +374,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
323 | return ret; | 374 | return ret; |
324 | } | 375 | } |
325 | 376 | ||
326 | |||
327 | // Called directly from unmanaged code so don't do much | 377 | // Called directly from unmanaged code so don't do much |
328 | private void BulletLogger(string msg) | 378 | private void BulletLogger(string msg) |
329 | { | 379 | { |
330 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); | 380 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); |
331 | } | 381 | } |
382 | |||
383 | // Called directly from unmanaged code so don't do much | ||
384 | private void BulletLoggerPhysLog(string msg) | ||
385 | { | ||
386 | PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); | ||
387 | } | ||
332 | 388 | ||
333 | public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) | 389 | public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) |
334 | { | 390 | { |
@@ -347,34 +403,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
347 | public override void RemoveAvatar(PhysicsActor actor) | 403 | public override void RemoveAvatar(PhysicsActor actor) |
348 | { | 404 | { |
349 | // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); | 405 | // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); |
350 | if (actor is BSCharacter) | 406 | BSCharacter bsactor = actor as BSCharacter; |
351 | { | 407 | if (bsactor != null) |
352 | ((BSCharacter)actor).Destroy(); | ||
353 | } | ||
354 | try | ||
355 | { | 408 | { |
356 | lock (m_avatars) m_avatars.Remove(actor.LocalID); | 409 | try |
357 | } | 410 | { |
358 | catch (Exception e) | 411 | lock (m_avatars) m_avatars.Remove(actor.LocalID); |
359 | { | 412 | } |
360 | m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); | 413 | catch (Exception e) |
414 | { | ||
415 | m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); | ||
416 | } | ||
417 | bsactor.Destroy(); | ||
418 | // bsactor.dispose(); | ||
361 | } | 419 | } |
362 | } | 420 | } |
363 | 421 | ||
364 | public override void RemovePrim(PhysicsActor prim) | 422 | public override void RemovePrim(PhysicsActor prim) |
365 | { | 423 | { |
366 | // m_log.DebugFormat("{0}: RemovePrim", LogHeader); | 424 | BSPrim bsprim = prim as BSPrim; |
367 | if (prim is BSPrim) | 425 | if (bsprim != null) |
368 | { | ||
369 | ((BSPrim)prim).Destroy(); | ||
370 | } | ||
371 | try | ||
372 | { | 426 | { |
373 | lock (m_prims) m_prims.Remove(prim.LocalID); | 427 | m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); |
428 | try | ||
429 | { | ||
430 | lock (m_prims) m_prims.Remove(bsprim.LocalID); | ||
431 | } | ||
432 | catch (Exception e) | ||
433 | { | ||
434 | m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); | ||
435 | } | ||
436 | bsprim.Destroy(); | ||
437 | // bsprim.dispose(); | ||
374 | } | 438 | } |
375 | catch (Exception e) | 439 | else |
376 | { | 440 | { |
377 | m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); | 441 | m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader); |
378 | } | 442 | } |
379 | } | 443 | } |
380 | 444 | ||
@@ -400,6 +464,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
400 | int collidersCount; | 464 | int collidersCount; |
401 | IntPtr collidersPtr; | 465 | IntPtr collidersPtr; |
402 | 466 | ||
467 | LastSimulatedTimestep = timeStep; | ||
468 | |||
403 | // prevent simulation until we've been initialized | 469 | // prevent simulation until we've been initialized |
404 | if (!m_initialized) return 10.0f; | 470 | if (!m_initialized) return 10.0f; |
405 | 471 | ||
@@ -459,7 +525,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
459 | for (int ii = 0; ii < updatedEntityCount; ii++) | 525 | for (int ii = 0; ii < updatedEntityCount; ii++) |
460 | { | 526 | { |
461 | EntityProperties entprop = m_updateArray[ii]; | 527 | EntityProperties entprop = m_updateArray[ii]; |
462 | // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position); | ||
463 | BSPrim prim; | 528 | BSPrim prim; |
464 | if (m_prims.TryGetValue(entprop.ID, out prim)) | 529 | if (m_prims.TryGetValue(entprop.ID, out prim)) |
465 | { | 530 | { |
@@ -532,8 +597,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
532 | }); | 597 | }); |
533 | } | 598 | } |
534 | 599 | ||
600 | // Someday we will have complex terrain with caves and tunnels | ||
601 | // For the moment, it's flat and convex | ||
602 | public float GetTerrainHeightAtXYZ(Vector3 loc) | ||
603 | { | ||
604 | return GetTerrainHeightAtXY(loc.X, loc.Y); | ||
605 | } | ||
606 | |||
535 | public float GetTerrainHeightAtXY(float tX, float tY) | 607 | public float GetTerrainHeightAtXY(float tX, float tY) |
536 | { | 608 | { |
609 | if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) | ||
610 | return 30; | ||
537 | return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; | 611 | return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; |
538 | } | 612 | } |
539 | 613 | ||