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.cs123
1 files changed, 79 insertions, 44 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 52997dd..0cf8c91 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,20 +39,20 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) 42// Move all logic out of the C++ code and into the C# code for easier future modifications.
43// Test sculpties 43// Test sculpties (verified that they don't work)
44// Compute physics FPS reasonably 44// Compute physics FPS reasonably
45// Based on material, set density and friction 45// Based on material, set density and friction
46// More efficient memory usage when passing hull information from BSPrim to BulletSim 46// Don't use constraints in linksets of non-physical objects. Means having to move children manually.
47// Move all logic out of the C++ code and into the C# code for easier future modifications.
48// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 47// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
49// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 48// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
50// At the moment, physical and phantom causes object to drop through the terrain 49// At the moment, physical and phantom causes object to drop through the terrain
51// Physical phantom objects and related typing (collision options ) 50// Physical phantom objects and related typing (collision options )
52// Use collision masks for collision with terrain and phantom objects
53// Check out llVolumeDetect. Must do something for that. 51// Check out llVolumeDetect. Must do something for that.
52// Use collision masks for collision with terrain and phantom objects
53// More efficient memory usage when passing hull information from BSPrim to BulletSim
54// Should prim.link() and prim.delink() membership checking happen at taint time? 54// Should prim.link() and prim.delink() membership checking happen at taint time?
55// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 55// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once.
56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
57// Implement LockAngularMotion 57// Implement LockAngularMotion
58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -60,7 +60,7 @@ using OpenMetaverse;
60// Add PID movement operations. What does ScenePresence.MoveToTarget do? 60// Add PID movement operations. What does ScenePresence.MoveToTarget do?
61// Check terrain size. 128 or 127? 61// Check terrain size. 128 or 127?
62// Raycast 62// Raycast
63// 63//
64namespace OpenSim.Region.Physics.BulletSPlugin 64namespace OpenSim.Region.Physics.BulletSPlugin
65{ 65{
66public class BSScene : PhysicsScene, IPhysicsParameters 66public class BSScene : PhysicsScene, IPhysicsParameters
@@ -73,12 +73,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 73
74 public string BulletSimVersion = "?"; 74 public string BulletSimVersion = "?";
75 75
76 public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>(); 76 public Dictionary<uint, BSPhysObject> PhysObjects;
77 public BSShapeCollection Shapes;
77 78
78 private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>(); 79 // Keeping track of the objects with collisions so we can report begin and end of a collision
79 // Following is a kludge and can be removed when avatar animation updating is 80 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>();
80 // moved to a better place. 81 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>();
81 private HashSet<BSPhysObject> m_avatarsWithCollisions = new HashSet<BSPhysObject>(); 82 // Keep track of all the avatars so we can send them a collision event
83 // every tick so OpenSim will update its animation.
84 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
82 85
83 // List of all the objects that have vehicle properties and should be called 86 // List of all the objects that have vehicle properties and should be called
84 // to update each physics step. 87 // to update each physics step.
@@ -202,6 +205,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
202 205
203 public override void Initialise(IMesher meshmerizer, IConfigSource config) 206 public override void Initialise(IMesher meshmerizer, IConfigSource config)
204 { 207 {
208 mesher = meshmerizer;
209 _taintedObjects = new List<TaintCallbackEntry>();
210 PhysObjects = new Dictionary<uint, BSPhysObject>();
211 Shapes = new BSShapeCollection(this);
212
205 // Allocate pinned memory to pass parameters. 213 // Allocate pinned memory to pass parameters.
206 m_params = new ConfigurationParameters[1]; 214 m_params = new ConfigurationParameters[1];
207 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); 215 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned);
@@ -215,12 +223,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
215 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 223 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
216 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 224 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
217 225
218 mesher = meshmerizer;
219 _taintedObjects = new List<TaintCallbackEntry>();
220
221 // Enable very detailed logging. 226 // Enable very detailed logging.
222 // By creating an empty logger when not logging, the log message invocation code 227 // By creating an empty logger when not logging, the log message invocation code
223 // can be left in and every call doesn't have to check for null. 228 // can be left in and every call doesn't have to check for null.
224 if (m_physicsLoggingEnabled) 229 if (m_physicsLoggingEnabled)
225 { 230 {
226 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 231 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
@@ -251,7 +256,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
251 // a child in a mega-region. 256 // a child in a mega-region.
252 // Turns out that Bullet really doesn't care about the extents of the simulated 257 // Turns out that Bullet really doesn't care about the extents of the simulated
253 // area. It tracks active objects no matter where they are. 258 // area. It tracks active objects no matter where they are.
254 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); 259 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
255 260
256 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 261 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
257 WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 262 WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
@@ -322,7 +327,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
322 { 327 {
323 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 328 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
324 } 329 }
325 330
326 // Called directly from unmanaged code so don't do much 331 // Called directly from unmanaged code so don't do much
327 private void BulletLoggerPhysLog(string msg) 332 private void BulletLoggerPhysLog(string msg)
328 { 333 {
@@ -351,6 +356,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
351 Constraints = null; 356 Constraints = null;
352 } 357 }
353 358
359 if (Shapes != null)
360 {
361 Shapes.Dispose();
362 Shapes = null;
363 }
364
354 // Anything left in the unmanaged code should be cleaned out 365 // Anything left in the unmanaged code should be cleaned out
355 BulletSimAPI.Shutdown(WorldID); 366 BulletSimAPI.Shutdown(WorldID);
356 367
@@ -379,7 +390,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
379 // TODO: Remove kludge someday. 390 // TODO: Remove kludge someday.
380 // We must generate a collision for avatars whether they collide or not. 391 // We must generate a collision for avatars whether they collide or not.
381 // This is required by OpenSim to update avatar animations, etc. 392 // This is required by OpenSim to update avatar animations, etc.
382 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor); 393 lock (m_avatars) m_avatars.Add(actor);
383 394
384 return actor; 395 return actor;
385 } 396 }
@@ -397,7 +408,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
397 { 408 {
398 lock (PhysObjects) PhysObjects.Remove(actor.LocalID); 409 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
399 // Remove kludge someday 410 // Remove kludge someday
400 lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor); 411 lock (m_avatars) m_avatars.Remove(bsactor);
401 } 412 }
402 catch (Exception e) 413 catch (Exception e)
403 { 414 {
@@ -449,7 +460,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
449 } 460 }
450 461
451 // This is a call from the simulator saying that some physical property has been updated. 462 // This is a call from the simulator saying that some physical property has been updated.
452 // The BulletSim driver senses the changing of relevant properties so this taint 463 // The BulletSim driver senses the changing of relevant properties so this taint
453 // information call is not needed. 464 // information call is not needed.
454 public override void AddPhysicsActorTaint(PhysicsActor prim) { } 465 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
455 466
@@ -464,6 +475,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
464 int collidersCount = 0; 475 int collidersCount = 0;
465 IntPtr collidersPtr; 476 IntPtr collidersPtr;
466 477
478 int beforeTime = 0;
479 int simTime = 0;
480
467 // prevent simulation until we've been initialized 481 // prevent simulation until we've been initialized
468 if (!m_initialized) return 5.0f; 482 if (!m_initialized) return 5.0f;
469 483
@@ -481,16 +495,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
481 int numSubSteps = 0; 495 int numSubSteps = 0;
482 try 496 try
483 { 497 {
498 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
499
484 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 500 numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
485 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 501 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
486 DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}", 502
487 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); 503 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
504 DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}",
505 DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
488 } 506 }
489 catch (Exception e) 507 catch (Exception e)
490 { 508 {
491 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", 509 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
492 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); 510 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
493 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", 511 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
494 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); 512 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
495 updatedEntityCount = 0; 513 updatedEntityCount = 0;
496 collidersCount = 0; 514 collidersCount = 0;
@@ -502,12 +520,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
502 // Get a value for 'now' so all the collision and update routines don't have to get their own 520 // Get a value for 'now' so all the collision and update routines don't have to get their own
503 SimulationNowTime = Util.EnvironmentTickCount(); 521 SimulationNowTime = Util.EnvironmentTickCount();
504 522
505 // This is a kludge to get avatar movement updates.
506 // ODE sends collisions for avatars even if there are have been no collisions. This updates
507 // avatar animations and stuff.
508 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
509 m_objectsWithCollisions = new HashSet<BSPhysObject>(m_avatarsWithCollisions);
510
511 // If there were collisions, process them by sending the event to the prim. 523 // If there were collisions, process them by sending the event to the prim.
512 // Collisions must be processed before updates. 524 // Collisions must be processed before updates.
513 if (collidersCount > 0) 525 if (collidersCount > 0)
@@ -523,11 +535,34 @@ public class BSScene : PhysicsScene, IPhysicsParameters
523 } 535 }
524 } 536 }
525 537
538 // This is a kludge to get avatar movement updates.
539 // ODE sends collisions for avatars even if there are have been no collisions. This updates
540 // avatar animations and stuff.
541 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
542 foreach (BSPhysObject bsp in m_avatars)
543 bsp.SendCollisions();
544
526 // The above SendCollision's batch up the collisions on the objects. 545 // The above SendCollision's batch up the collisions on the objects.
527 // Now push the collisions into the simulator. 546 // Now push the collisions into the simulator.
528 foreach (BSPhysObject bsp in m_objectsWithCollisions) 547 if (ObjectsWithCollisions.Count > 0)
529 bsp.SendCollisions(); 548 {
530 m_objectsWithCollisions.Clear(); 549 foreach (BSPhysObject bsp in ObjectsWithCollisions)
550 if (!m_avatars.Contains(bsp)) // don't call avatars twice
551 if (!bsp.SendCollisions())
552 {
553 // If the object is done colliding, see that it's removed from the colliding list
554 ObjectsWithNoMoreCollisions.Add(bsp);
555 }
556 }
557
558 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
559 // This can't be done by SendCollisions because it is inside an iteration of ObjectWithCollisions.
560 if (ObjectsWithNoMoreCollisions.Count > 0)
561 {
562 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
563 ObjectsWithCollisions.Remove(po);
564 ObjectsWithNoMoreCollisions.Clear();
565 }
531 566
532 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 567 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
533 if (updatedEntityCount > 0) 568 if (updatedEntityCount > 0)
@@ -555,7 +590,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
555 // The physics engine returns the number of milliseconds it simulated this call. 590 // The physics engine returns the number of milliseconds it simulated this call.
556 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 591 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
557 // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. 592 // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS.
558 return numSubSteps * m_fixedTimeStep; 593 return numSubSteps * m_fixedTimeStep * 1000;
559 } 594 }
560 595
561 // Something has collided 596 // Something has collided
@@ -570,20 +605,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
570 if (!PhysObjects.TryGetValue(localID, out collider)) 605 if (!PhysObjects.TryGetValue(localID, out collider))
571 { 606 {
572 // If the object that is colliding cannot be found, just ignore the collision. 607 // If the object that is colliding cannot be found, just ignore the collision.
608 DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith);
573 return; 609 return;
574 } 610 }
575 611
576 // The terrain is not in the physical object list so 'collidee' 612 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called.
577 // can be null when Collide() is called.
578 BSPhysObject collidee = null; 613 BSPhysObject collidee = null;
579 PhysObjects.TryGetValue(collidingWith, out collidee); 614 PhysObjects.TryGetValue(collidingWith, out collidee);
580 615
581 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); 616 DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
582 617
583 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) 618 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
584 { 619 {
585 // If a collision was posted, remember to send it to the simulator 620 // If a collision was posted, remember to send it to the simulator
586 m_objectsWithCollisions.Add(collider); 621 ObjectsWithCollisions.Add(collider);
587 } 622 }
588 623
589 return; 624 return;
@@ -599,7 +634,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
599 TerrainManager.SetTerrain(heightMap); 634 TerrainManager.SetTerrain(heightMap);
600 } 635 }
601 636
602 public override void SetWaterLevel(float baseheight) 637 public override void SetWaterLevel(float baseheight)
603 { 638 {
604 m_waterLevel = baseheight; 639 m_waterLevel = baseheight;
605 } 640 }
@@ -609,7 +644,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
609 return m_waterLevel; 644 return m_waterLevel;
610 } 645 }
611 646
612 public override void DeleteTerrain() 647 public override void DeleteTerrain()
613 { 648 {
614 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); 649 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
615 } 650 }
@@ -771,7 +806,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
771 // getters and setters. 806 // getters and setters.
772 // It is easiest to find an existing definition and copy it. 807 // It is easiest to find an existing definition and copy it.
773 // Parameter values are floats. Booleans are converted to a floating value. 808 // Parameter values are floats. Booleans are converted to a floating value.
774 // 809 //
775 // A ParameterDefn() takes the following parameters: 810 // A ParameterDefn() takes the following parameters:
776 // -- the text name of the parameter. This is used for console input and ini file. 811 // -- the text name of the parameter. This is used for console input and ini file.
777 // -- a short text description of the parameter. This shows up in the console listing. 812 // -- a short text description of the parameter. This shows up in the console listing.
@@ -998,7 +1033,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
998 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, 1033 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
999 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), 1034 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1000 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", 1035 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1001 ConfigurationParameters.numericFalse, 1036 ConfigurationParameters.numericTrue,
1002 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1037 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1003 (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, 1038 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1004 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), 1039 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
@@ -1193,7 +1228,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1193 } 1228 }
1194 }); 1229 });
1195 break; 1230 break;
1196 default: 1231 default:
1197 // setting only one localID 1232 // setting only one localID
1198 TaintedUpdateParameter(parm, localID, val); 1233 TaintedUpdateParameter(parm, localID, val);
1199 break; 1234 break;