aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs127
1 files changed, 62 insertions, 65 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 28c6680..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,8 +43,8 @@ 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; }
@@ -51,6 +52,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
51 public string BulletSimVersion = "?"; 52 public string BulletSimVersion = "?";
52 53
53 // The handle to the underlying managed or unmanaged version of Bullet being used. 54 // The handle to the underlying managed or unmanaged version of Bullet being used.
55 public string BulletEngineName { get; private set; }
54 public BSAPITemplate PE; 56 public BSAPITemplate PE;
55 57
56 public Dictionary<uint, BSPhysObject> PhysObjects; 58 public Dictionary<uint, BSPhysObject> PhysObjects;
@@ -102,11 +104,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
102 // Pinned memory used to pass step information between managed and unmanaged 104 // Pinned memory used to pass step information between managed and unmanaged
103 internal int m_maxCollisionsPerFrame; 105 internal int m_maxCollisionsPerFrame;
104 internal CollisionDesc[] m_collisionArray; 106 internal CollisionDesc[] m_collisionArray;
105 internal GCHandle m_collisionArrayPinnedHandle;
106 107
107 internal int m_maxUpdatesPerFrame; 108 internal int m_maxUpdatesPerFrame;
108 internal EntityProperties[] m_updateArray; 109 internal EntityProperties[] m_updateArray;
109 internal GCHandle m_updateArrayPinnedHandle;
110 110
111 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
112 public const uint GROUNDPLANE_ID = 1; 112 public const uint GROUNDPLANE_ID = 1;
@@ -152,12 +152,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
152 // 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
153 // Used to pass basic configuration values to the unmanaged code. 153 // Used to pass basic configuration values to the unmanaged code.
154 internal ConfigurationParameters[] UnmanagedParams; 154 internal ConfigurationParameters[] UnmanagedParams;
155 GCHandle m_paramsHandle;
156
157 // Handle to the callback used by the unmanaged code to call into the managed code.
158 // Used for debug logging.
159 // Need to store the handle in a persistant variable so it won't be freed.
160 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
161 155
162 // Sometimes you just have to log everything. 156 // Sometimes you just have to log everything.
163 public Logging.LogWriter PhysicsLogging; 157 public Logging.LogWriter PhysicsLogging;
@@ -194,15 +188,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
194 // 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
195 GetInitialParameterValues(config); 189 GetInitialParameterValues(config);
196 190
197 // For the moment, only one version of the interface 191 // Get the connection to the physics engine (could be native or one of many DLLs)
198 PE = new BSAPIUnman(); 192 PE = SelectUnderlyingBulletEngine(BulletEngineName);
199
200 // Allocate more pinned memory. Do this early to try and get all pinned memory close together.
201 m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned);
202 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
203 m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned);
204 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
205 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
206 193
207 // Enable very detailed logging. 194 // Enable very detailed logging.
208 // 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
@@ -217,22 +204,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
217 PhysicsLogging = new Logging.LogWriter(); 204 PhysicsLogging = new Logging.LogWriter();
218 } 205 }
219 206
220 // If Debug logging level, enable logging from the unmanaged code 207 // Allocate memory for returning of the updates and collisions from the physics engine
221 m_DebugLogCallbackHandle = null; 208 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
222 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 209 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
223 {
224 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
225 if (PhysicsLogging.Enabled)
226 // The handle is saved in a variable to make sure it doesn't get freed after this call
227 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
228 else
229 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
230 }
231
232 // Get the version of the DLL
233 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
234 // BulletSimVersion = BulletSimAPI.GetVersion();
235 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
236 210
237 // 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
238 // a child in a mega-region. 212 // a child in a mega-region.
@@ -240,11 +214,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
240 // area. It tracks active objects no matter where they are. 214 // area. It tracks active objects no matter where they are.
241 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 215 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
242 216
243 // 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);
244 World = new BulletWorld(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
245 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
246 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
247 m_DebugLogCallbackHandle));
248 218
249 Constraints = new BSConstraintCollection(World); 219 Constraints = new BSConstraintCollection(World);
250 220
@@ -274,6 +244,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
274 { 244 {
275 BSParam.SetParameterConfigurationValues(this, pConfig); 245 BSParam.SetParameterConfigurationValues(this, pConfig);
276 246
247 // There are two Bullet implementations to choose from
248 BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged");
249
277 // Very detailed logging for physics debugging 250 // Very detailed logging for physics debugging
278 // 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.
279 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 252 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -315,16 +288,41 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
315 return ret; 288 return ret;
316 } 289 }
317 290
318 // Called directly from unmanaged code so don't do much 291 // Select the connection to the actual Bullet implementation.
319 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)
320 { 296 {
321 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 297 // For the moment, do a simple switch statement.
322 } 298 // Someday do fancyness with looking up the interfaces in the assembly.
299 BSAPITemplate ret = null;
323 300
324 // Called directly from unmanaged code so don't do much 301 string selectionName = engineName.ToLower();
325 private void BulletLoggerPhysLog(string msg) 302 int hyphenIndex = engineName.IndexOf("-");
326 { 303 if (hyphenIndex > 0)
327 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;
328 } 326 }
329 327
330 public override void Dispose() 328 public override void Dispose()
@@ -361,7 +359,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
361 } 359 }
362 360
363 // Anything left in the unmanaged code should be cleaned out 361 // Anything left in the unmanaged code should be cleaned out
364 BulletSimAPI.Shutdown2(World.ptr); 362 PE.Shutdown(World);
365 363
366 // Not logging any more 364 // Not logging any more
367 PhysicsLogging.Close(); 365 PhysicsLogging.Close();
@@ -474,9 +472,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
474 LastTimeStep = timeStep; 472 LastTimeStep = timeStep;
475 473
476 int updatedEntityCount = 0; 474 int updatedEntityCount = 0;
477 IntPtr updatedEntitiesPtr;
478 int collidersCount = 0; 475 int collidersCount = 0;
479 IntPtr collidersPtr;
480 476
481 int beforeTime = 0; 477 int beforeTime = 0;
482 int simTime = 0; 478 int simTime = 0;
@@ -492,6 +488,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
492 TriggerPreStepEvent(timeStep); 488 TriggerPreStepEvent(timeStep);
493 489
494 // the prestep actions might have added taints 490 // the prestep actions might have added taints
491 numTaints += _taintOperations.Count;
495 ProcessTaints(); 492 ProcessTaints();
496 493
497 InTaintTime = false; // Only used for debugging so locking is not necessary. 494 InTaintTime = false; // Only used for debugging so locking is not necessary.
@@ -499,23 +496,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
499 // 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.
500 // Only enable this in a limited test world with few objects. 497 // Only enable this in a limited test world with few objects.
501 if (m_physicsPhysicalDumpEnabled) 498 if (m_physicsPhysicalDumpEnabled)
502 BulletSimAPI.DumpAllInfo2(World.ptr); 499 PE.DumpAllInfo(World);
503 500
504 // step the physical world one interval 501 // step the physical world one interval
505 m_simulationStep++; 502 m_simulationStep++;
506 int numSubSteps = 0; 503 int numSubSteps = 0;
507
508 try 504 try
509 { 505 {
510 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 506 if (PhysicsLogging.Enabled)
507 beforeTime = Util.EnvironmentTickCount();
511 508
512 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 509 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
513 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
514 510
515 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 511 if (PhysicsLogging.Enabled)
516 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", 512 {
517 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, 513 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
518 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 }
519 } 518 }
520 catch (Exception e) 519 catch (Exception e)
521 { 520 {
@@ -527,8 +526,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
527 collidersCount = 0; 526 collidersCount = 0;
528 } 527 }
529 528
530 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in.
531
532 // 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.
533 SimulationNowTime = Util.EnvironmentTickCount(); 530 SimulationNowTime = Util.EnvironmentTickCount();
534 531
@@ -570,7 +567,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
570 // Objects that are done colliding are removed from the ObjectsWithCollisions list. 567 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
571 // Not done above because it is inside an iteration of ObjectWithCollisions. 568 // Not done above because it is inside an iteration of ObjectWithCollisions.
572 // This complex collision processing is required to create an empty collision 569 // This complex collision processing is required to create an empty collision
573 // 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
574 // the simulator to generate the 'collision end' event. 571 // the simulator to generate the 'collision end' event.
575 if (ObjectsWithNoMoreCollisions.Count > 0) 572 if (ObjectsWithNoMoreCollisions.Count > 0)
576 { 573 {
@@ -599,11 +596,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
599 // 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.
600 // Only enable this in a limited test world with few objects. 597 // Only enable this in a limited test world with few objects.
601 if (m_physicsPhysicalDumpEnabled) 598 if (m_physicsPhysicalDumpEnabled)
602 BulletSimAPI.DumpAllInfo2(World.ptr); 599 PE.DumpAllInfo(World);
603 600
604 // 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.
605 // 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.
606 // 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).
607 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; 604 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
608 } 605 }
609 606