aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorRobert Adams2012-07-06 10:01:47 -0700
committerRobert Adams2012-07-06 15:09:19 -0700
commite4a6611865848ffcfa6adedd813534e0a0e4abf3 (patch)
treec01ee1f828f276d45b09fbebea08b4e730e721ef /OpenSim/Region/Physics
parentAdd assert to attachment regression tests to check that number of objects in ... (diff)
downloadopensim-SC_OLD-e4a6611865848ffcfa6adedd813534e0a0e4abf3.zip
opensim-SC_OLD-e4a6611865848ffcfa6adedd813534e0a0e4abf3.tar.gz
opensim-SC_OLD-e4a6611865848ffcfa6adedd813534e0a0e4abf3.tar.bz2
opensim-SC_OLD-e4a6611865848ffcfa6adedd813534e0a0e4abf3.tar.xz
Clean up collision reporting code so they are properly passed to
the simulator in batches. More comments.
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs102
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs11
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs29
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs23
4 files changed, 107 insertions, 58 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index b08d5db..dc0c008 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -74,7 +74,7 @@ public class BSCharacter : PhysicsActor
74 private float _buoyancy; 74 private float _buoyancy;
75 75
76 private int _subscribedEventsMs = 0; 76 private int _subscribedEventsMs = 0;
77 private int _lastCollisionTime = 0; 77 private int _nextCollisionOkTime = 0;
78 78
79 private Vector3 _PIDTarget; 79 private Vector3 _PIDTarget;
80 private bool _usePID; 80 private bool _usePID;
@@ -360,17 +360,22 @@ public class BSCharacter : PhysicsActor
360 } 360 }
361 //m_lastUpdateSent = false; 361 //m_lastUpdateSent = false;
362 } 362 }
363
363 public override void AddAngularForce(Vector3 force, bool pushforce) { 364 public override void AddAngularForce(Vector3 force, bool pushforce) {
364 } 365 }
365 public override void SetMomentum(Vector3 momentum) { 366 public override void SetMomentum(Vector3 momentum) {
366 } 367 }
368
369 // Turn on collision events at a rate no faster than one every the given milliseconds
367 public override void SubscribeEvents(int ms) { 370 public override void SubscribeEvents(int ms) {
368 _subscribedEventsMs = ms; 371 _subscribedEventsMs = ms;
369 _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 372 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen
370 } 373 }
374 // Stop collision events
371 public override void UnSubscribeEvents() { 375 public override void UnSubscribeEvents() {
372 _subscribedEventsMs = 0; 376 _subscribedEventsMs = 0;
373 } 377 }
378 // Return 'true' if someone has subscribed to events
374 public override bool SubscribedEvents() { 379 public override bool SubscribedEvents() {
375 return (_subscribedEventsMs > 0); 380 return (_subscribedEventsMs > 0);
376 } 381 }
@@ -386,47 +391,57 @@ public class BSCharacter : PhysicsActor
386 _mass = _density * _avatarVolume; 391 _mass = _density * _avatarVolume;
387 } 392 }
388 393
394 // Set to 'true' if the individual changed items should be checked
395 // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties)
396 const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false;
397
389 // The physics engine says that properties have updated. Update same and inform 398 // The physics engine says that properties have updated. Update same and inform
390 // the world that things have changed. 399 // the world that things have changed.
391 public void UpdateProperties(EntityProperties entprop) 400 public void UpdateProperties(EntityProperties entprop)
392 { 401 {
393 bool changed = false; 402 bool changed = false;
394 // we assign to the local variables so the normal set action does not happen 403 if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) {
395 if (_position != entprop.Position) 404 // we assign to the local variables so the normal set action does not happen
396 { 405 if (_position != entprop.Position) {
397 _position = entprop.Position; 406 _position = entprop.Position;
398 changed = true; 407 changed = true;
408 }
409 if (_orientation != entprop.Rotation) {
410 _orientation = entprop.Rotation;
411 changed = true;
412 }
413 if (_velocity != entprop.Velocity) {
414 _velocity = entprop.Velocity;
415 changed = true;
416 }
417 if (_acceleration != entprop.Acceleration) {
418 _acceleration = entprop.Acceleration;
419 changed = true;
420 }
421 if (_rotationalVelocity != entprop.RotationalVelocity) {
422 _rotationalVelocity = entprop.RotationalVelocity;
423 changed = true;
424 }
425 if (changed) {
426 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
427 // Avatar movement is not done by generating this event. There is code in the heartbeat
428 // loop that updates avatars.
429 // base.RequestPhysicsterseUpdate();
430 }
399 } 431 }
400 if (_orientation != entprop.Rotation) 432 else {
401 { 433 _position = entprop.Position;
402 _orientation = entprop.Rotation; 434 _orientation = entprop.Rotation;
403 changed = true;
404 }
405 if (_velocity != entprop.Velocity)
406 {
407 _velocity = entprop.Velocity; 435 _velocity = entprop.Velocity;
408 changed = true;
409 }
410 if (_acceleration != entprop.Acceleration)
411 {
412 _acceleration = entprop.Acceleration; 436 _acceleration = entprop.Acceleration;
413 changed = true;
414 }
415 if (_rotationalVelocity != entprop.RotationalVelocity)
416 {
417 _rotationalVelocity = entprop.RotationalVelocity; 437 _rotationalVelocity = entprop.RotationalVelocity;
418 changed = true;
419 }
420 if (changed)
421 {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is a system that
424 // checks for avatar updates each heartbeat loop.
425 // base.RequestPhysicsterseUpdate(); 438 // base.RequestPhysicsterseUpdate();
426 } 439 }
427 } 440 }
428 441
429 // Called by the scene when a collision with this object is reported 442 // Called by the scene when a collision with this object is reported
443 // The collision, if it should be reported to the character, is placed in a collection
444 // that will later be sent to the simulator when SendCollisions() is called.
430 CollisionEventUpdate collisionCollection = null; 445 CollisionEventUpdate collisionCollection = null;
431 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) 446 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
432 { 447 {
@@ -440,29 +455,34 @@ public class BSCharacter : PhysicsActor
440 } 455 }
441 456
442 // throttle collisions to the rate specified in the subscription 457 // throttle collisions to the rate specified in the subscription
443 if (_subscribedEventsMs == 0) return; // don't want collisions 458 if (_subscribedEventsMs != 0) {
444 int nowTime = _scene.SimulationNowTime; 459 int nowTime = _scene.SimulationNowTime;
445 if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; 460 if (nowTime >= _nextCollisionOkTime) {
446 _lastCollisionTime = nowTime; 461 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
447 462
448 if (collisionCollection == null) 463 if (collisionCollection == null)
449 collisionCollection = new CollisionEventUpdate(); 464 collisionCollection = new CollisionEventUpdate();
450 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 465 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
466 }
467 }
451 } 468 }
452 469
453 public void SendCollisions() 470 public void SendCollisions()
454 { 471 {
455 // if (collisionCollection != null) 472 /*
456 // { 473 if (collisionCollection != null && collisionCollection.Count > 0)
457 // base.SendCollisionUpdate(collisionCollection); 474 {
458 // collisionCollection = null; 475 base.SendCollisionUpdate(collisionCollection);
459 // } 476 collisionCollection = null;
477 }
478 */
460 // Kludge to make a collision call even if there are no collisions. 479 // Kludge to make a collision call even if there are no collisions.
461 // This causes the avatar animation to get updated. 480 // This causes the avatar animation to get updated.
462 if (collisionCollection == null) 481 if (collisionCollection == null)
463 collisionCollection = new CollisionEventUpdate(); 482 collisionCollection = new CollisionEventUpdate();
464 base.SendCollisionUpdate(collisionCollection); 483 base.SendCollisionUpdate(collisionCollection);
465 collisionCollection = null; 484 collisionCollection.Clear();
485 // End kludge
466 } 486 }
467 487
468} 488}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 0730824..0f027b8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
@@ -32,6 +32,14 @@ using OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 /// <summary>
36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim.
37 /// This module interfaces to an unmanaged C++ library which makes the
38 /// actual calls into the Bullet physics engine.
39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/.
40 /// The unmanaged library is compiled and linked statically with Bullet
41 /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit).
42 /// </summary>
35public class BSPlugin : IPhysicsPlugin 43public class BSPlugin : IPhysicsPlugin
36{ 44{
37 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 45 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@@ -53,6 +61,9 @@ public class BSPlugin : IPhysicsPlugin
53 { 61 {
54 if (Util.IsWindows()) 62 if (Util.IsWindows())
55 Util.LoadArchSpecificWindowsDll("BulletSim.dll"); 63 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
64 // If not Windows, loading is performed by the
65 // Mono loader as specified in
66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
56 67
57 _mScene = new BSScene(sceneIdentifier); 68 _mScene = new BSScene(sceneIdentifier);
58 } 69 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 248d1f2..130f1ca 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -90,7 +90,7 @@ public sealed class BSPrim : PhysicsActor
90 private BSPrim _parentPrim; 90 private BSPrim _parentPrim;
91 91
92 private int _subscribedEventsMs = 0; 92 private int _subscribedEventsMs = 0;
93 private int _lastCollisionTime = 0; 93 private int _nextCollisionOkTime = 0;
94 long _collidingStep; 94 long _collidingStep;
95 long _collidingGroundStep; 95 long _collidingGroundStep;
96 96
@@ -597,7 +597,8 @@ public sealed class BSPrim : PhysicsActor
597 } 597 }
598 public override void SubscribeEvents(int ms) { 598 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 599 _subscribedEventsMs = ms;
600 _lastCollisionTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 600 // make sure first collision happens
601 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
601 } 602 }
602 public override void UnSubscribeEvents() { 603 public override void UnSubscribeEvents() {
603 _subscribedEventsMs = 0; 604 _subscribedEventsMs = 0;
@@ -1338,23 +1339,27 @@ public sealed class BSPrim : PhysicsActor
1338 _collidingGroundStep = _scene.SimulationStep; 1339 _collidingGroundStep = _scene.SimulationStep;
1339 } 1340 }
1340 1341
1341 if (_subscribedEventsMs == 0) return; // nothing in the object is waiting for collision events 1342 // if someone is subscribed to collision events....
1342 // throttle the collisions to the number of milliseconds specified in the subscription 1343 if (_subscribedEventsMs != 0) {
1343 int nowTime = _scene.SimulationNowTime; 1344 // throttle the collisions to the number of milliseconds specified in the subscription
1344 if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; 1345 int nowTime = _scene.SimulationNowTime;
1345 _lastCollisionTime = nowTime; 1346 if (nowTime >= _nextCollisionOkTime) {
1347 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1346 1348
1347 if (collisionCollection == null) 1349 if (collisionCollection == null)
1348 collisionCollection = new CollisionEventUpdate(); 1350 collisionCollection = new CollisionEventUpdate();
1349 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 1351 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1352 }
1353 }
1350 } 1354 }
1351 1355
1356 // The scene is telling us it's time to pass our collected collisions into the simulator
1352 public void SendCollisions() 1357 public void SendCollisions()
1353 { 1358 {
1354 if (collisionCollection != null) 1359 if (collisionCollection != null && collisionCollection.Count > 0)
1355 { 1360 {
1356 base.SendCollisionUpdate(collisionCollection); 1361 base.SendCollisionUpdate(collisionCollection);
1357 collisionCollection = null; 1362 collisionCollection.Clear();
1358 } 1363 }
1359 } 1364 }
1360} 1365}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 94a0ccf..417cb5f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -52,6 +52,7 @@ using OpenSim.Region.Framework;
52// Should prim.link() and prim.delink() membership checking happen at taint time? 52// Should prim.link() and prim.delink() membership checking happen at taint time?
53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
55// Use collision masks for collision with terrain and phantom objects
55// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 56// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
56// Implement LockAngularMotion 57// Implement LockAngularMotion
57// 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)
@@ -62,9 +63,6 @@ using OpenSim.Region.Framework;
62// Multiple contact points on collision? 63// Multiple contact points on collision?
63// See code in ode::near... calls to collision_accounting_events() 64// See code in ode::near... calls to collision_accounting_events()
64// (This might not be a problem. ODE collects all the collisions with one object in one tick.) 65// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
65// Use collision masks for collision with terrain and phantom objects
66// Figure out how to not allocate a new Dictionary and List for every collision
67// in BSPrim.Collide() and BSCharacter.Collide(). Can the same ones be reused?
68// Raycast 66// Raycast
69// 67//
70namespace OpenSim.Region.Physics.BulletSPlugin 68namespace OpenSim.Region.Physics.BulletSPlugin
@@ -405,6 +403,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
405 // prevent simulation until we've been initialized 403 // prevent simulation until we've been initialized
406 if (!m_initialized) return 10.0f; 404 if (!m_initialized) return 10.0f;
407 405
406 long simulateStartTime = Util.EnvironmentTickCount();
407
408 // update the prim states while we know the physics engine is not busy 408 // update the prim states while we know the physics engine is not busy
409 ProcessTaints(); 409 ProcessTaints();
410 410
@@ -437,13 +437,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
437 } 437 }
438 } 438 }
439 439
440 // The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator. 440 // The above SendCollision's batch up the collisions on the objects.
441 // Now push the collisions into the simulator.
441 foreach (BSPrim bsp in m_primsWithCollisions) 442 foreach (BSPrim bsp in m_primsWithCollisions)
442 bsp.SendCollisions(); 443 bsp.SendCollisions();
443 m_primsWithCollisions.Clear(); 444 m_primsWithCollisions.Clear();
445
446 // This is a kludge to get avatar movement updated.
447 // Don't send collisions only if there were collisions -- send everytime.
448 // ODE sends collisions even if there are none and this is used to update
449 // avatar animations and stuff.
444 // foreach (BSCharacter bsc in m_avatarsWithCollisions) 450 // foreach (BSCharacter bsc in m_avatarsWithCollisions)
445 // bsc.SendCollisions(); 451 // bsc.SendCollisions();
446 // This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any
447 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 452 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
448 kvp.Value.SendCollisions(); 453 kvp.Value.SendCollisions();
449 m_avatarsWithCollisions.Clear(); 454 m_avatarsWithCollisions.Clear();
@@ -465,10 +470,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
465 if (m_avatars.TryGetValue(entprop.ID, out actor)) 470 if (m_avatars.TryGetValue(entprop.ID, out actor))
466 { 471 {
467 actor.UpdateProperties(entprop); 472 actor.UpdateProperties(entprop);
473 continue;
468 } 474 }
469 } 475 }
470 } 476 }
471 477
478 // If enabled, call into the physics engine to dump statistics
472 if (m_detailedStatsStep > 0) 479 if (m_detailedStatsStep > 0)
473 { 480 {
474 if ((m_simulationStep % m_detailedStatsStep) == 0) 481 if ((m_simulationStep % m_detailedStatsStep) == 0)
@@ -477,6 +484,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
477 } 484 }
478 } 485 }
479 486
487 // this is a waste since the outside routine also calcuates the physics simulation
488 // period. TODO: There should be a way of computing physics frames from simulator computation.
489 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
490 // return (timeStep * (float)simulateTotalTime);
491
480 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. 492 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation.
481 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; 493 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
482 } 494 }
@@ -528,6 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
528 public override void SetWaterLevel(float baseheight) 540 public override void SetWaterLevel(float baseheight)
529 { 541 {
530 m_waterLevel = baseheight; 542 m_waterLevel = baseheight;
543 // TODO: pass to physics engine so things will float?
531 } 544 }
532 public float GetWaterLevel() 545 public float GetWaterLevel()
533 { 546 {