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.cs127
1 files changed, 65 insertions, 62 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 4133107..258b72f 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;
@@ -187,16 +184,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
187 184
188 // Allocate pinned memory to pass parameters. 185 // Allocate pinned memory to pass parameters.
189 UnmanagedParams = new ConfigurationParameters[1]; 186 UnmanagedParams = new ConfigurationParameters[1];
190 m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned);
191 187
192 // Set default values for physics parameters plus any overrides from the ini file 188 // Set default values for physics parameters plus any overrides from the ini file
193 GetInitialParameterValues(config); 189 GetInitialParameterValues(config);
194 190
195 // allocate more pinned memory close to the above in an attempt to get the memory all together 191 // Get the connection to the physics engine (could be native or one of many DLLs)
196 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame]; 192 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 193
201 // Enable very detailed logging. 194 // Enable very detailed logging.
202 // By creating an empty logger when not logging, the log message invocation code 195 // By creating an empty logger when not logging, the log message invocation code
@@ -211,22 +204,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
211 PhysicsLogging = new Logging.LogWriter(); 204 PhysicsLogging = new Logging.LogWriter();
212 } 205 }
213 206
214 // If Debug logging level, enable logging from the unmanaged code 207 // Allocate memory for returning of the updates and collisions from the physics engine
215 m_DebugLogCallbackHandle = null; 208 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
216 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 209 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 210
231 // The bounding box for the simulated world. The origin is 0,0,0 unless we're 211 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
232 // a child in a mega-region. 212 // a child in a mega-region.
@@ -234,11 +214,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
234 // area. It tracks active objects no matter where they are. 214 // area. It tracks active objects no matter where they are.
235 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 215 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
236 216
237 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 217 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 218
243 Constraints = new BSConstraintCollection(World); 219 Constraints = new BSConstraintCollection(World);
244 220
@@ -268,6 +244,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
268 { 244 {
269 BSParam.SetParameterConfigurationValues(this, pConfig); 245 BSParam.SetParameterConfigurationValues(this, pConfig);
270 246
247 // There are two Bullet implementations to choose from
248 BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged");
249
271 // Very detailed logging for physics debugging 250 // Very detailed logging for physics debugging
272 // TODO: the boolean values can be moved to the normal parameter processing. 251 // TODO: the boolean values can be moved to the normal parameter processing.
273 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 252 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -309,16 +288,41 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
309 return ret; 288 return ret;
310 } 289 }
311 290
312 // Called directly from unmanaged code so don't do much 291 // Select the connection to the actual Bullet implementation.
313 private void BulletLogger(string msg) 292 // The main engine selection is the engineName up to the first hypen.
293 // So "Bullet-2.80-OpenCL-Intel" specifies the 'bullet' class here and the whole name
294 // is passed to the engine to do its special selection, etc.
295 private BSAPITemplate SelectUnderlyingBulletEngine(string engineName)
314 { 296 {
315 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 297 // For the moment, do a simple switch statement.
316 } 298 // Someday do fancyness with looking up the interfaces in the assembly.
299 BSAPITemplate ret = null;
317 300
318 // Called directly from unmanaged code so don't do much 301 string selectionName = engineName.ToLower();
319 private void BulletLoggerPhysLog(string msg) 302 int hyphenIndex = engineName.IndexOf("-");
320 { 303 if (hyphenIndex > 0)
321 DetailLog("[BULLETS UNMANAGED]:" + msg); 304 selectionName = engineName.ToLower().Substring(0, hyphenIndex - 1);
305
306 switch (selectionName)
307 {
308 case "bulletunmanaged":
309 ret = new BSAPIUnman(engineName, this);
310 break;
311 case "bulletxna":
312 // ret = new BSAPIXNA(engineName, this);
313 break;
314 }
315
316 if (ret == null)
317 {
318 m_log.ErrorFormat("{0) COULD NOT SELECT BULLET ENGINE: '[BulletSim]PhysicsEngine' must be either 'BulletUnmanaged-*' or 'BulletXNA-*'", LogHeader);
319 }
320 else
321 {
322 m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion);
323 }
324
325 return ret;
322 } 326 }
323 327
324 public override void Dispose() 328 public override void Dispose()
@@ -355,7 +359,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
355 } 359 }
356 360
357 // Anything left in the unmanaged code should be cleaned out 361 // Anything left in the unmanaged code should be cleaned out
358 BulletSimAPI.Shutdown2(World.ptr); 362 PE.Shutdown(World);
359 363
360 // Not logging any more 364 // Not logging any more
361 PhysicsLogging.Close(); 365 PhysicsLogging.Close();
@@ -468,9 +472,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
468 LastTimeStep = timeStep; 472 LastTimeStep = timeStep;
469 473
470 int updatedEntityCount = 0; 474 int updatedEntityCount = 0;
471 IntPtr updatedEntitiesPtr;
472 int collidersCount = 0; 475 int collidersCount = 0;
473 IntPtr collidersPtr;
474 476
475 int beforeTime = 0; 477 int beforeTime = 0;
476 int simTime = 0; 478 int simTime = 0;
@@ -486,6 +488,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
486 TriggerPreStepEvent(timeStep); 488 TriggerPreStepEvent(timeStep);
487 489
488 // the prestep actions might have added taints 490 // the prestep actions might have added taints
491 numTaints += _taintOperations.Count;
489 ProcessTaints(); 492 ProcessTaints();
490 493
491 InTaintTime = false; // Only used for debugging so locking is not necessary. 494 InTaintTime = false; // Only used for debugging so locking is not necessary.
@@ -493,23 +496,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. 496 // 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. 497 // Only enable this in a limited test world with few objects.
495 if (m_physicsPhysicalDumpEnabled) 498 if (m_physicsPhysicalDumpEnabled)
496 BulletSimAPI.DumpAllInfo2(World.ptr); 499 PE.DumpAllInfo(World);
497 500
498 // step the physical world one interval 501 // step the physical world one interval
499 m_simulationStep++; 502 m_simulationStep++;
500 int numSubSteps = 0; 503 int numSubSteps = 0;
501
502 try 504 try
503 { 505 {
504 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 506 if (PhysicsLogging.Enabled)
507 beforeTime = Util.EnvironmentTickCount();
505 508
506 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 509 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
507 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
508 510
509 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 511 if (PhysicsLogging.Enabled)
510 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", 512 {
511 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, 513 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
512 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); 514 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
515 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
516 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
517 }
513 } 518 }
514 catch (Exception e) 519 catch (Exception e)
515 { 520 {
@@ -521,8 +526,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
521 collidersCount = 0; 526 collidersCount = 0;
522 } 527 }
523 528
524 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in.
525
526 // Get a value for 'now' so all the collision and update routines don't have to get their own. 529 // Get a value for 'now' so all the collision and update routines don't have to get their own.
527 SimulationNowTime = Util.EnvironmentTickCount(); 530 SimulationNowTime = Util.EnvironmentTickCount();
528 531
@@ -564,7 +567,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
564 // Objects that are done colliding are removed from the ObjectsWithCollisions list. 567 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
565 // Not done above because it is inside an iteration of ObjectWithCollisions. 568 // Not done above because it is inside an iteration of ObjectWithCollisions.
566 // This complex collision processing is required to create an empty collision 569 // This complex collision processing is required to create an empty collision
567 // event call after all collisions have happened on an object. This enables 570 // event call after all real collisions have happened on an object. This enables
568 // the simulator to generate the 'collision end' event. 571 // the simulator to generate the 'collision end' event.
569 if (ObjectsWithNoMoreCollisions.Count > 0) 572 if (ObjectsWithNoMoreCollisions.Count > 0)
570 { 573 {
@@ -593,11 +596,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. 596 // 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. 597 // Only enable this in a limited test world with few objects.
595 if (m_physicsPhysicalDumpEnabled) 598 if (m_physicsPhysicalDumpEnabled)
596 BulletSimAPI.DumpAllInfo2(World.ptr); 599 PE.DumpAllInfo(World);
597 600
598 // The physics engine returns the number of milliseconds it simulated this call. 601 // 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. 602 // 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. 603 // 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; 604 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
602 } 605 }
603 606