diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSScene.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 127 |
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 | */ |
27 | using System; | 27 | using System; |
28 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
29 | using System.Reflection; | ||
29 | using System.Runtime.InteropServices; | 30 | using System.Runtime.InteropServices; |
30 | using System.Text; | 31 | using System.Text; |
31 | using System.Threading; | 32 | using System.Threading; |
@@ -42,8 +43,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
42 | { | 43 | { |
43 | public sealed class BSScene : PhysicsScene, IPhysicsParameters | 44 | public 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 | ||