aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs129
1 files changed, 68 insertions, 61 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 4133107..7017194 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection;
29using System.Runtime.InteropServices; 30using System.Runtime.InteropServices;
30using System.Text; 31using System.Text;
31using System.Threading; 32using System.Threading;
@@ -42,14 +43,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
42{ 43{
43public sealed class BSScene : PhysicsScene, IPhysicsParameters 44public sealed class BSScene : PhysicsScene, IPhysicsParameters
44{ 45{
45 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 46 internal static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
46 private static readonly string LogHeader = "[BULLETS SCENE]"; 47 internal static readonly string LogHeader = "[BULLETS SCENE]";
47 48
48 // The name of the region we're working for. 49 // The name of the region we're working for.
49 public string RegionName { get; private set; } 50 public string RegionName { get; private set; }
50 51
51 public string BulletSimVersion = "?"; 52 public string BulletSimVersion = "?";
52 53
54 // The handle to the underlying managed or unmanaged version of Bullet being used.
55 public string BulletEngineName { get; private set; }
56 public BSAPITemplate PE;
57
53 public Dictionary<uint, BSPhysObject> PhysObjects; 58 public Dictionary<uint, BSPhysObject> PhysObjects;
54 public BSShapeCollection Shapes; 59 public BSShapeCollection Shapes;
55 60
@@ -99,11 +104,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
99 // Pinned memory used to pass step information between managed and unmanaged 104 // Pinned memory used to pass step information between managed and unmanaged
100 internal int m_maxCollisionsPerFrame; 105 internal int m_maxCollisionsPerFrame;
101 internal CollisionDesc[] m_collisionArray; 106 internal CollisionDesc[] m_collisionArray;
102 internal GCHandle m_collisionArrayPinnedHandle;
103 107
104 internal int m_maxUpdatesPerFrame; 108 internal int m_maxUpdatesPerFrame;
105 internal EntityProperties[] m_updateArray; 109 internal EntityProperties[] m_updateArray;
106 internal GCHandle m_updateArrayPinnedHandle;
107 110
108 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 111 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
109 public const uint GROUNDPLANE_ID = 1; 112 public const uint GROUNDPLANE_ID = 1;
@@ -149,12 +152,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
149 // A pointer to an instance if this structure is passed to the C++ code 152 // A pointer to an instance if this structure is passed to the C++ code
150 // Used to pass basic configuration values to the unmanaged code. 153 // Used to pass basic configuration values to the unmanaged code.
151 internal ConfigurationParameters[] UnmanagedParams; 154 internal ConfigurationParameters[] UnmanagedParams;
152 GCHandle m_paramsHandle;
153
154 // Handle to the callback used by the unmanaged code to call into the managed code.
155 // Used for debug logging.
156 // Need to store the handle in a persistant variable so it won't be freed.
157 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
158 155
159 // Sometimes you just have to log everything. 156 // Sometimes you just have to log everything.
160 public Logging.LogWriter PhysicsLogging; 157 public Logging.LogWriter PhysicsLogging;
@@ -164,6 +161,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
164 private int m_physicsLoggingFileMinutes; 161 private int m_physicsLoggingFileMinutes;
165 private bool m_physicsLoggingDoFlush; 162 private bool m_physicsLoggingDoFlush;
166 private bool m_physicsPhysicalDumpEnabled; 163 private bool m_physicsPhysicalDumpEnabled;
164 public float PhysicsMetricDumpFrames { get; set; }
167 // 'true' of the vehicle code is to log lots of details 165 // 'true' of the vehicle code is to log lots of details
168 public bool VehicleLoggingEnabled { get; private set; } 166 public bool VehicleLoggingEnabled { get; private set; }
169 public bool VehiclePhysicalLoggingEnabled { get; private set; } 167 public bool VehiclePhysicalLoggingEnabled { get; private set; }
@@ -187,16 +185,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
187 185
188 // Allocate pinned memory to pass parameters. 186 // Allocate pinned memory to pass parameters.
189 UnmanagedParams = new ConfigurationParameters[1]; 187 UnmanagedParams = new ConfigurationParameters[1];
190 m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned);
191 188
192 // Set default values for physics parameters plus any overrides from the ini file 189 // Set default values for physics parameters plus any overrides from the ini file
193 GetInitialParameterValues(config); 190 GetInitialParameterValues(config);
194 191
195 // allocate more pinned memory close to the above in an attempt to get the memory all together 192 // Get the connection to the physics engine (could be native or one of many DLLs)
196 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame]; 193 PE = SelectUnderlyingBulletEngine(BulletEngineName);
197 m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned);
198 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
199 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
200 194
201 // Enable very detailed logging. 195 // Enable very detailed logging.
202 // By creating an empty logger when not logging, the log message invocation code 196 // By creating an empty logger when not logging, the log message invocation code
@@ -211,22 +205,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
211 PhysicsLogging = new Logging.LogWriter(); 205 PhysicsLogging = new Logging.LogWriter();
212 } 206 }
213 207
214 // If Debug logging level, enable logging from the unmanaged code 208 // Allocate memory for returning of the updates and collisions from the physics engine
215 m_DebugLogCallbackHandle = null; 209 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
216 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 210 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
217 {
218 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
219 if (PhysicsLogging.Enabled)
220 // The handle is saved in a variable to make sure it doesn't get freed after this call
221 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
222 else
223 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
224 }
225
226 // Get the version of the DLL
227 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
228 // BulletSimVersion = BulletSimAPI.GetVersion();
229 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
230 211
231 // The bounding box for the simulated world. The origin is 0,0,0 unless we're 212 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
232 // a child in a mega-region. 213 // a child in a mega-region.
@@ -234,11 +215,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
234 // area. It tracks active objects no matter where they are. 215 // area. It tracks active objects no matter where they are.
235 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 216 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
236 217
237 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 218 World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray);
238 World = new BulletWorld(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
239 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
240 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
241 m_DebugLogCallbackHandle));
242 219
243 Constraints = new BSConstraintCollection(World); 220 Constraints = new BSConstraintCollection(World);
244 221
@@ -268,6 +245,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
268 { 245 {
269 BSParam.SetParameterConfigurationValues(this, pConfig); 246 BSParam.SetParameterConfigurationValues(this, pConfig);
270 247
248 // There are two Bullet implementations to choose from
249 BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged");
250
271 // Very detailed logging for physics debugging 251 // Very detailed logging for physics debugging
272 // TODO: the boolean values can be moved to the normal parameter processing. 252 // TODO: the boolean values can be moved to the normal parameter processing.
273 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 253 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -309,16 +289,41 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
309 return ret; 289 return ret;
310 } 290 }
311 291
312 // Called directly from unmanaged code so don't do much 292 // Select the connection to the actual Bullet implementation.
313 private void BulletLogger(string msg) 293 // The main engine selection is the engineName up to the first hypen.
294 // So "Bullet-2.80-OpenCL-Intel" specifies the 'bullet' class here and the whole name
295 // is passed to the engine to do its special selection, etc.
296 private BSAPITemplate SelectUnderlyingBulletEngine(string engineName)
314 { 297 {
315 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 298 // For the moment, do a simple switch statement.
316 } 299 // Someday do fancyness with looking up the interfaces in the assembly.
300 BSAPITemplate ret = null;
317 301
318 // Called directly from unmanaged code so don't do much 302 string selectionName = engineName.ToLower();
319 private void BulletLoggerPhysLog(string msg) 303 int hyphenIndex = engineName.IndexOf("-");
320 { 304 if (hyphenIndex > 0)
321 DetailLog("[BULLETS UNMANAGED]:" + msg); 305 selectionName = engineName.ToLower().Substring(0, hyphenIndex - 1);
306
307 switch (selectionName)
308 {
309 case "bulletunmanaged":
310 ret = new BSAPIUnman(engineName, this);
311 break;
312 case "bulletxna":
313 ret = new BSAPIXNA(engineName, this);
314 break;
315 }
316
317 if (ret == null)
318 {
319 m_log.ErrorFormat("{0) COULD NOT SELECT BULLET ENGINE: '[BulletSim]PhysicsEngine' must be either 'BulletUnmanaged-*' or 'BulletXNA-*'", LogHeader);
320 }
321 else
322 {
323 m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion);
324 }
325
326 return ret;
322 } 327 }
323 328
324 public override void Dispose() 329 public override void Dispose()
@@ -355,7 +360,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
355 } 360 }
356 361
357 // Anything left in the unmanaged code should be cleaned out 362 // Anything left in the unmanaged code should be cleaned out
358 BulletSimAPI.Shutdown2(World.ptr); 363 PE.Shutdown(World);
359 364
360 // Not logging any more 365 // Not logging any more
361 PhysicsLogging.Close(); 366 PhysicsLogging.Close();
@@ -468,9 +473,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
468 LastTimeStep = timeStep; 473 LastTimeStep = timeStep;
469 474
470 int updatedEntityCount = 0; 475 int updatedEntityCount = 0;
471 IntPtr updatedEntitiesPtr;
472 int collidersCount = 0; 476 int collidersCount = 0;
473 IntPtr collidersPtr;
474 477
475 int beforeTime = 0; 478 int beforeTime = 0;
476 int simTime = 0; 479 int simTime = 0;
@@ -486,6 +489,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
486 TriggerPreStepEvent(timeStep); 489 TriggerPreStepEvent(timeStep);
487 490
488 // the prestep actions might have added taints 491 // the prestep actions might have added taints
492 numTaints += _taintOperations.Count;
489 ProcessTaints(); 493 ProcessTaints();
490 494
491 InTaintTime = false; // Only used for debugging so locking is not necessary. 495 InTaintTime = false; // Only used for debugging so locking is not necessary.
@@ -493,23 +497,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
493 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. 497 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
494 // Only enable this in a limited test world with few objects. 498 // Only enable this in a limited test world with few objects.
495 if (m_physicsPhysicalDumpEnabled) 499 if (m_physicsPhysicalDumpEnabled)
496 BulletSimAPI.DumpAllInfo2(World.ptr); 500 PE.DumpAllInfo(World);
497 501
498 // step the physical world one interval 502 // step the physical world one interval
499 m_simulationStep++; 503 m_simulationStep++;
500 int numSubSteps = 0; 504 int numSubSteps = 0;
501
502 try 505 try
503 { 506 {
504 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 507 if (PhysicsLogging.Enabled)
508 beforeTime = Util.EnvironmentTickCount();
505 509
506 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 510 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
507 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
508 511
509 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 512 if (PhysicsLogging.Enabled)
510 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", 513 {
511 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, 514 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
512 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); 515 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
516 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
517 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
518 }
513 } 519 }
514 catch (Exception e) 520 catch (Exception e)
515 { 521 {
@@ -521,7 +527,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
521 collidersCount = 0; 527 collidersCount = 0;
522 } 528 }
523 529
524 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in. 530 if ((m_simulationStep % PhysicsMetricDumpFrames) == 0)
531 PE.DumpPhysicsStatistics(World);
525 532
526 // Get a value for 'now' so all the collision and update routines don't have to get their own. 533 // Get a value for 'now' so all the collision and update routines don't have to get their own.
527 SimulationNowTime = Util.EnvironmentTickCount(); 534 SimulationNowTime = Util.EnvironmentTickCount();
@@ -564,7 +571,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
564 // Objects that are done colliding are removed from the ObjectsWithCollisions list. 571 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
565 // Not done above because it is inside an iteration of ObjectWithCollisions. 572 // Not done above because it is inside an iteration of ObjectWithCollisions.
566 // This complex collision processing is required to create an empty collision 573 // This complex collision processing is required to create an empty collision
567 // event call after all collisions have happened on an object. This enables 574 // event call after all real collisions have happened on an object. This enables
568 // the simulator to generate the 'collision end' event. 575 // the simulator to generate the 'collision end' event.
569 if (ObjectsWithNoMoreCollisions.Count > 0) 576 if (ObjectsWithNoMoreCollisions.Count > 0)
570 { 577 {
@@ -593,11 +600,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
593 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. 600 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
594 // Only enable this in a limited test world with few objects. 601 // Only enable this in a limited test world with few objects.
595 if (m_physicsPhysicalDumpEnabled) 602 if (m_physicsPhysicalDumpEnabled)
596 BulletSimAPI.DumpAllInfo2(World.ptr); 603 PE.DumpAllInfo(World);
597 604
598 // The physics engine returns the number of milliseconds it simulated this call. 605 // The physics engine returns the number of milliseconds it simulated this call.
599 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 606 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
600 // Multiply by 55 to give a nominal frame rate of 55. 607 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
601 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; 608 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
602 } 609 }
603 610