aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/Util.cs7
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs113
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs39
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs14
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs32
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs559
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs63
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs192
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs748
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs8
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs10
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs6
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs68
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt3
17 files changed, 967 insertions, 911 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index d206fc1..4d132bb 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -299,6 +299,13 @@ namespace OpenSim.Framework
299 x; 299 x;
300 } 300 }
301 301
302 // Inclusive, within range test (true if equal to the endpoints)
303 public static bool InRange<T>(T x, T min, T max)
304 where T : IComparable<T>
305 {
306 return x.CompareTo(max) <= 0 && x.CompareTo(min) >= 0;
307 }
308
302 public static uint GetNextXferID() 309 public static uint GetNextXferID()
303 { 310 {
304 uint id = 0; 311 uint id = 0;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 57c5898..8e059ee 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -88,8 +88,8 @@ public sealed class BSCharacter : BSPhysObject
88 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 88 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
89 // replace with the default values. 89 // replace with the default values.
90 _size = size; 90 _size = size;
91 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; 91 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
92 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; 92 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
93 93
94 // A motor to control the acceleration and deceleration of the avatar movement. 94 // A motor to control the acceleration and deceleration of the avatar movement.
95 // _velocityMotor = new BSVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f); 95 // _velocityMotor = new BSVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
@@ -108,8 +108,8 @@ public sealed class BSCharacter : BSPhysObject
108 _velocity = OMV.Vector3.Zero; 108 _velocity = OMV.Vector3.Zero;
109 _appliedVelocity = OMV.Vector3.Zero; 109 _appliedVelocity = OMV.Vector3.Zero;
110 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 110 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
111 _currentFriction = PhysicsScene.Params.avatarStandingFriction; 111 _currentFriction = BSParam.AvatarStandingFriction;
112 _avatarDensity = PhysicsScene.Params.avatarDensity; 112 _avatarDensity = BSParam.AvatarDensity;
113 113
114 // The dimensions of the avatar capsule are kept in the scale. 114 // The dimensions of the avatar capsule are kept in the scale.
115 // Physics creates a unit capsule which is scaled by the physics engine. 115 // Physics creates a unit capsule which is scaled by the physics engine.
@@ -134,6 +134,8 @@ public sealed class BSCharacter : BSPhysObject
134 // called when this character is being destroyed and the resources should be released 134 // called when this character is being destroyed and the resources should be released
135 public override void Destroy() 135 public override void Destroy()
136 { 136 {
137 base.Destroy();
138
137 DetailLog("{0},BSCharacter.Destroy", LocalID); 139 DetailLog("{0},BSCharacter.Destroy", LocalID);
138 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 140 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
139 { 141 {
@@ -156,19 +158,20 @@ public sealed class BSCharacter : BSPhysObject
156 _velocityMotor.Reset(); 158 _velocityMotor.Reset();
157 _velocityMotor.SetCurrent(_velocity); 159 _velocityMotor.SetCurrent(_velocity);
158 _velocityMotor.SetTarget(_velocity); 160 _velocityMotor.SetTarget(_velocity);
161 _velocityMotor.Enabled = false;
159 162
160 // This will enable or disable the flying buoyancy of the avatar. 163 // This will enable or disable the flying buoyancy of the avatar.
161 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 164 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
162 Flying = _flying; 165 Flying = _flying;
163 166
164 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); 167 BulletSimAPI.SetRestitution2(PhysBody.ptr, BSParam.AvatarRestitution);
165 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); 168 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin);
166 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); 169 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
167 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); 170 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, BSParam.ContactProcessingThreshold);
168 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 171 if (BSParam.CcdMotionThreshold > 0f)
169 { 172 {
170 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 173 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold);
171 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 174 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius);
172 } 175 }
173 176
174 UpdatePhysicalMassProperties(RawMass); 177 UpdatePhysicalMassProperties(RawMass);
@@ -208,8 +211,8 @@ public sealed class BSCharacter : BSPhysObject
208 _size = value; 211 _size = value;
209 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 212 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
210 // replace with the default values. 213 // replace with the default values.
211 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; 214 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
212 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; 215 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
213 216
214 ComputeAvatarScale(_size); 217 ComputeAvatarScale(_size);
215 ComputeAvatarVolumeAndMass(); 218 ComputeAvatarVolumeAndMass();
@@ -433,13 +436,13 @@ public sealed class BSCharacter : BSPhysObject
433 OMV.Vector3 targetVel = value; 436 OMV.Vector3 targetVel = value;
434 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() 437 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate()
435 { 438 {
436 float timeStep = 0.089f; // DEBUG DEBUG FIX FIX FIX
437 _velocityMotor.Reset(); 439 _velocityMotor.Reset();
438 _velocityMotor.SetTarget(targetVel); 440 _velocityMotor.SetTarget(targetVel);
439 _velocityMotor.SetCurrent(_velocity); 441 _velocityMotor.SetCurrent(_velocity);
440 // Compute a velocity value and make sure it gets pushed into the avatar. 442 _velocityMotor.Enabled = true;
441 // This makes sure the avatar will start from a stop. 443
442 ForceVelocity = _velocityMotor.Step(timeStep); 444 // Make sure a property update happens next step so the motor gets incorporated.
445 BulletSimAPI.PushUpdate2(PhysBody.ptr);
443 }); 446 });
444 } 447 }
445 } 448 }
@@ -448,12 +451,15 @@ public sealed class BSCharacter : BSPhysObject
448 get { return _velocity; } 451 get { return _velocity; }
449 set { 452 set {
450 _velocity = value; 453 _velocity = value;
451 _velocityMotor.Reset();
452 _velocityMotor.SetCurrent(_velocity);
453 _velocityMotor.SetTarget(_velocity);
454 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 454 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
455 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 455 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
456 { 456 {
457 _velocityMotor.Reset();
458 _velocityMotor.SetCurrent(_velocity);
459 _velocityMotor.SetTarget(_velocity);
460 // Even though the motor is initialized, it's not used and the velocity goes straight into the avatar.
461 _velocityMotor.Enabled = false;
462
457 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 463 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
458 ForceVelocity = _velocity; 464 ForceVelocity = _velocity;
459 }); 465 });
@@ -464,27 +470,27 @@ public sealed class BSCharacter : BSPhysObject
464 set { 470 set {
465 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 471 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
466 472
473 _velocity = value;
467 // Depending on whether the avatar is moving or not, change the friction 474 // Depending on whether the avatar is moving or not, change the friction
468 // to keep the avatar from slipping around 475 // to keep the avatar from slipping around
469 if (_velocity.Length() == 0) 476 if (_velocity.Length() == 0)
470 { 477 {
471 if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) 478 if (_currentFriction != BSParam.AvatarStandingFriction)
472 { 479 {
473 _currentFriction = PhysicsScene.Params.avatarStandingFriction; 480 _currentFriction = BSParam.AvatarStandingFriction;
474 if (PhysBody.HasPhysicalBody) 481 if (PhysBody.HasPhysicalBody)
475 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); 482 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
476 } 483 }
477 } 484 }
478 else 485 else
479 { 486 {
480 if (_currentFriction != PhysicsScene.Params.avatarFriction) 487 if (_currentFriction != BSParam.AvatarFriction)
481 { 488 {
482 _currentFriction = PhysicsScene.Params.avatarFriction; 489 _currentFriction = BSParam.AvatarFriction;
483 if (PhysBody.HasPhysicalBody) 490 if (PhysBody.HasPhysicalBody)
484 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); 491 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
485 } 492 }
486 } 493 }
487 _velocity = value;
488 // Remember the set velocity so we can suppress the reduction by friction, ... 494 // Remember the set velocity so we can suppress the reduction by friction, ...
489 _appliedVelocity = value; 495 _appliedVelocity = value;
490 496
@@ -561,12 +567,6 @@ public sealed class BSCharacter : BSPhysObject
561 set { 567 set {
562 _flying = value; 568 _flying = value;
563 569
564 // Velocity movement is different when flying: flying velocity degrades over time.
565 if (_flying)
566 _velocityMotor.TargetValueDecayTimeScale = 1f;
567 else
568 _velocityMotor.TargetValueDecayTimeScale = BSMotor.Infinite;
569
570 // simulate flying by changing the effect of gravity 570 // simulate flying by changing the effect of gravity
571 Buoyancy = ComputeBuoyancyFromFlying(_flying); 571 Buoyancy = ComputeBuoyancyFromFlying(_flying);
572 } 572 }
@@ -750,39 +750,42 @@ public sealed class BSCharacter : BSPhysObject
750 _velocity = entprop.Velocity; 750 _velocity = entprop.Velocity;
751 _acceleration = entprop.Acceleration; 751 _acceleration = entprop.Acceleration;
752 _rotationalVelocity = entprop.RotationalVelocity; 752 _rotationalVelocity = entprop.RotationalVelocity;
753
753 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. 754 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
754 PositionSanityCheck(true); 755 PositionSanityCheck(true);
755 756
757 if (_velocityMotor.Enabled)
758 {
759 // TODO: Decide if the step parameters should be changed depending on the avatar's
760 // state (flying, colliding, ...).
761
762 OMV.Vector3 stepVelocity = _velocityMotor.Step(PhysicsScene.LastTimeStep);
763
764 // If falling, we keep the world's downward vector no matter what the other axis specify.
765 if (!Flying && !IsColliding)
766 {
767 stepVelocity.Z = entprop.Velocity.Z;
768 DetailLog("{0},BSCharacter.UpdateProperties,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
769 }
770
771 // If the user has said stop and we've stopped applying velocity correction,
772 // the motor can be turned off. Set the velocity to zero so the zero motion is sent to the viewer.
773 if (_velocityMotor.TargetValue.ApproxEquals(OMV.Vector3.Zero, 0.01f) && _velocityMotor.ErrorIsZero)
774 {
775 stepVelocity = OMV.Vector3.Zero;
776 _velocityMotor.Enabled = false;
777 DetailLog("{0},BSCharacter.UpdateProperties,taint,disableVelocityMotor,m={1}", LocalID, _velocityMotor);
778 }
779
780 _velocity = stepVelocity;
781 entprop.Velocity = _velocity;
782 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
783 }
784
756 // remember the current and last set values 785 // remember the current and last set values
757 LastEntityProperties = CurrentEntityProperties; 786 LastEntityProperties = CurrentEntityProperties;
758 CurrentEntityProperties = entprop; 787 CurrentEntityProperties = entprop;
759 788
760 // Avatars don't respond to world friction, etc. They only go the speed I tell them too.
761 // Special kludge here for falling. Even though the target velocity might not have a
762 // Z component, the avatar could be falling (walked off a ledge, stopped flying, ...)
763 // and that velocity component must be retained.
764 float timeStep = 0.089f; // DEBUG DEBUG FIX FIX FIX
765 OMV.Vector3 stepVelocity = _velocityMotor.Step(timeStep);
766 // Remove next line so avatars don't fly up forever. DEBUG DEBUG this is only temporary.
767 // stepVelocity.Z += entprop.Velocity.Z;
768 _velocity = stepVelocity;
769 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
770 /*
771 OMV.Vector3 stepVelocity = _velocityMotor.Step(timeStep);
772 OMV.Vector3 avVel = new OMV.Vector3(stepVelocity.X, stepVelocity.Y, entprop.Velocity.Z);
773 _velocity = avVel;
774 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel);
775
776 if (entprop.Velocity != LastEntityProperties.Velocity)
777 {
778 // Changes in the velocity are suppressed in avatars.
779 // That's just the way they are defined.
780 OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z);
781 _velocity = avVel;
782 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel);
783 }
784 */
785
786 // Tell the linkset about value changes 789 // Tell the linkset about value changes
787 Linkset.UpdateProperties(this, true); 790 Linkset.UpdateProperties(this, true);
788 791
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 6b1e304..e77fb50 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -122,7 +122,7 @@ public abstract class BSConstraint : IDisposable
122 // Setting an object's mass to zero (making it static like when it's selected) 122 // Setting an object's mass to zero (making it static like when it's selected)
123 // automatically disables the constraints. 123 // automatically disables the constraints.
124 // If the link is enabled, be sure to set the constraint itself to enabled. 124 // If the link is enabled, be sure to set the constraint itself to enabled.
125 BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true)); 125 BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, BSParam.NumericBool(true));
126 } 126 }
127 else 127 else
128 { 128 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index a5acd86..3fde57b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -563,7 +563,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
563 // Moderate angular movement introduced by Bullet. 563 // Moderate angular movement introduced by Bullet.
564 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. 564 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
565 // Maybe compute linear and angular factor and damping from params. 565 // Maybe compute linear and angular factor and damping from params.
566 float angularDamping = PhysicsScene.Params.vehicleAngularDamping; 566 float angularDamping = BSParam.VehicleAngularDamping;
567 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); 567 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
568 568
569 // Vehicles report collision events so we know when it's on the ground 569 // Vehicles report collision events so we know when it's on the ground
@@ -634,28 +634,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
634 m_knownHas = 0; 634 m_knownHas = 0;
635 m_knownChanged = 0; 635 m_knownChanged = 0;
636 } 636 }
637 // Push all the changed values back into the physics engine
637 private void PushKnownChanged() 638 private void PushKnownChanged()
638 { 639 {
639 if (m_knownChanged != 0) 640 if (m_knownChanged != 0)
640 { 641 {
641 if ((m_knownChanged & m_knownChangedPosition) != 0) 642 if ((m_knownChanged & m_knownChangedPosition) != 0)
642 Prim.ForcePosition = VehiclePosition; 643 Prim.ForcePosition = m_knownPosition;
644
643 if ((m_knownChanged & m_knownChangedOrientation) != 0) 645 if ((m_knownChanged & m_knownChangedOrientation) != 0)
644 Prim.ForceOrientation = VehicleOrientation; 646 Prim.ForceOrientation = m_knownOrientation;
647
645 if ((m_knownChanged & m_knownChangedVelocity) != 0) 648 if ((m_knownChanged & m_knownChangedVelocity) != 0)
646 { 649 {
647 Prim.ForceVelocity = VehicleVelocity; 650 Prim.ForceVelocity = m_knownVelocity;
648 BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity); 651 BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity);
649 } 652 }
653
650 if ((m_knownChanged & m_knownChangedForce) != 0) 654 if ((m_knownChanged & m_knownChangedForce) != 0)
651 Prim.AddForce((Vector3)m_knownForce, false, true); 655 Prim.AddForce((Vector3)m_knownForce, false, true);
652 656
653 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) 657 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
654 { 658 {
655 Prim.ForceRotationalVelocity = VehicleRotationalVelocity; 659 Prim.ForceRotationalVelocity = m_knownRotationalVelocity;
656 // Fake out Bullet by making it think the velocity is the same as last time. 660 // Fake out Bullet by making it think the velocity is the same as last time.
657 BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity); 661 BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, m_knownRotationalVelocity);
658 } 662 }
663
659 if ((m_knownChanged & m_knownChangedRotationalForce) != 0) 664 if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
660 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); 665 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true);
661 666
@@ -667,7 +672,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
667 } 672 }
668 673
669 // Since the computation of terrain height can be a little involved, this routine 674 // Since the computation of terrain height can be a little involved, this routine
670 // is used ot fetch the height only once for each vehicle simulation step. 675 // is used to fetch the height only once for each vehicle simulation step.
671 private float GetTerrainHeight(Vector3 pos) 676 private float GetTerrainHeight(Vector3 pos)
672 { 677 {
673 if ((m_knownHas & m_knownChangedTerrainHeight) == 0) 678 if ((m_knownHas & m_knownChangedTerrainHeight) == 0)
@@ -699,12 +704,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
699 m_knownPosition = Prim.ForcePosition; 704 m_knownPosition = Prim.ForcePosition;
700 m_knownHas |= m_knownChangedPosition; 705 m_knownHas |= m_knownChangedPosition;
701 } 706 }
702 return (Vector3)m_knownPosition; 707 return m_knownPosition;
703 } 708 }
704 set 709 set
705 { 710 {
706 m_knownPosition = value; 711 m_knownPosition = value;
707 m_knownChanged |= m_knownChangedPosition; 712 m_knownChanged |= m_knownChangedPosition;
713 m_knownHas |= m_knownChangedPosition;
708 } 714 }
709 } 715 }
710 716
@@ -717,12 +723,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
717 m_knownOrientation = Prim.ForceOrientation; 723 m_knownOrientation = Prim.ForceOrientation;
718 m_knownHas |= m_knownChangedOrientation; 724 m_knownHas |= m_knownChangedOrientation;
719 } 725 }
720 return (Quaternion)m_knownOrientation; 726 return m_knownOrientation;
721 } 727 }
722 set 728 set
723 { 729 {
724 m_knownOrientation = value; 730 m_knownOrientation = value;
725 m_knownChanged |= m_knownChangedOrientation; 731 m_knownChanged |= m_knownChangedOrientation;
732 m_knownHas |= m_knownChangedOrientation;
726 } 733 }
727 } 734 }
728 735
@@ -741,13 +748,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
741 { 748 {
742 m_knownVelocity = value; 749 m_knownVelocity = value;
743 m_knownChanged |= m_knownChangedVelocity; 750 m_knownChanged |= m_knownChangedVelocity;
751 m_knownHas |= m_knownChangedVelocity;
744 } 752 }
745 } 753 }
746 754
747 private void VehicleAddForce(Vector3 aForce) 755 private void VehicleAddForce(Vector3 aForce)
748 { 756 {
757 if ((m_knownHas & m_knownChangedForce) == 0)
758 {
759 m_knownForce = Vector3.Zero;
760 }
749 m_knownForce += aForce; 761 m_knownForce += aForce;
750 m_knownChanged |= m_knownChangedForce; 762 m_knownChanged |= m_knownChangedForce;
763 m_knownHas |= m_knownChangedForce;
751 } 764 }
752 765
753 private Vector3 VehicleRotationalVelocity 766 private Vector3 VehicleRotationalVelocity
@@ -765,12 +778,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
765 { 778 {
766 m_knownRotationalVelocity = value; 779 m_knownRotationalVelocity = value;
767 m_knownChanged |= m_knownChangedRotationalVelocity; 780 m_knownChanged |= m_knownChangedRotationalVelocity;
781 m_knownHas |= m_knownChangedRotationalVelocity;
768 } 782 }
769 } 783 }
770 private void VehicleAddAngularForce(Vector3 aForce) 784 private void VehicleAddAngularForce(Vector3 aForce)
771 { 785 {
786 if ((m_knownHas & m_knownChangedRotationalForce) == 0)
787 {
788 m_knownRotationalForce = Vector3.Zero;
789 }
772 m_knownRotationalForce += aForce; 790 m_knownRotationalForce += aForce;
773 m_knownChanged |= m_knownChangedRotationalForce; 791 m_knownChanged |= m_knownChangedRotationalForce;
792 m_knownHas |= m_knownChangedRotationalForce;
774 } 793 }
775 // Vehicle relative forward velocity 794 // Vehicle relative forward velocity
776 private Vector3 VehicleForwardVelocity 795 private Vector3 VehicleForwardVelocity
@@ -782,7 +801,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
782 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); 801 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
783 m_knownHas |= m_knownChangedForwardVelocity; 802 m_knownHas |= m_knownChangedForwardVelocity;
784 } 803 }
785 return (Vector3)m_knownForwardVelocity; 804 return m_knownForwardVelocity;
786 } 805 }
787 } 806 }
788 private float VehicleForwardSpeed 807 private float VehicleForwardSpeed
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 2017fa5..8580928 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -56,7 +56,7 @@ public abstract class BSLinkset
56 { 56 {
57 BSLinkset ret = null; 57 BSLinkset ret = null;
58 58
59 switch ((int)physScene.Params.linksetImplementation) 59 switch ((int)BSParam.LinksetImplementation)
60 { 60 {
61 case (int)LinksetImplementation.Constraint: 61 case (int)LinksetImplementation.Constraint:
62 ret = new BSLinksetConstraints(physScene, parent); 62 ret = new BSLinksetConstraints(physScene, parent);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 8c36c31..d95f223 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -226,14 +226,14 @@ public sealed class BSLinksetConstraints : BSLinkset
226 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 226 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
227 227
228 // tweek the constraint to increase stability 228 // tweek the constraint to increase stability
229 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); 229 constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset));
230 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), 230 constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor),
231 PhysicsScene.Params.linkConstraintTransMotorMaxVel, 231 BSParam.LinkConstraintTransMotorMaxVel,
232 PhysicsScene.Params.linkConstraintTransMotorMaxForce); 232 BSParam.LinkConstraintTransMotorMaxForce);
233 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); 233 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
234 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) 234 if (BSParam.LinkConstraintSolverIterations != 0f)
235 { 235 {
236 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); 236 constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations);
237 } 237 }
238 return constrain; 238 return constrain;
239 } 239 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index 34a87c6..9e1a9ba 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -43,7 +43,9 @@ public abstract class BSMotor
43 { 43 {
44 UseName = useName; 44 UseName = useName;
45 PhysicsScene = null; 45 PhysicsScene = null;
46 Enabled = true;
46 } 47 }
48 public virtual bool Enabled { get; set; }
47 public virtual void Reset() { } 49 public virtual void Reset() { }
48 public virtual void Zero() { } 50 public virtual void Zero() { }
49 public virtual void GenerateTestOutput(float timeStep) { } 51 public virtual void GenerateTestOutput(float timeStep) { }
@@ -98,6 +100,12 @@ public class BSVMotor : BSMotor
98 public virtual Vector3 CurrentValue { get; protected set; } 100 public virtual Vector3 CurrentValue { get; protected set; }
99 public virtual Vector3 LastError { get; protected set; } 101 public virtual Vector3 LastError { get; protected set; }
100 102
103 public virtual bool ErrorIsZero
104 { get {
105 return (LastError == Vector3.Zero || LastError.LengthSquared() <= ErrorZeroThreshold);
106 }
107 }
108
101 public BSVMotor(string useName) 109 public BSVMotor(string useName)
102 : base(useName) 110 : base(useName)
103 { 111 {
@@ -105,7 +113,7 @@ public class BSVMotor : BSMotor
105 Efficiency = 1f; 113 Efficiency = 1f;
106 FrictionTimescale = BSMotor.InfiniteVector; 114 FrictionTimescale = BSMotor.InfiniteVector;
107 CurrentValue = TargetValue = Vector3.Zero; 115 CurrentValue = TargetValue = Vector3.Zero;
108 ErrorZeroThreshold = 0.01f; 116 ErrorZeroThreshold = 0.001f;
109 } 117 }
110 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
111 : this(useName) 119 : this(useName)
@@ -133,6 +141,8 @@ public class BSVMotor : BSMotor
133 // Compute the next step and return the new current value 141 // Compute the next step and return the new current value
134 public virtual Vector3 Step(float timeStep) 142 public virtual Vector3 Step(float timeStep)
135 { 143 {
144 if (!Enabled) return TargetValue;
145
136 Vector3 origTarget = TargetValue; // DEBUG 146 Vector3 origTarget = TargetValue; // DEBUG
137 Vector3 origCurrVal = CurrentValue; // DEBUG 147 Vector3 origCurrVal = CurrentValue; // DEBUG
138 148
@@ -178,7 +188,7 @@ public class BSVMotor : BSMotor
178 { 188 {
179 // Difference between what we have and target is small. Motor is done. 189 // Difference between what we have and target is small. Motor is done.
180 CurrentValue = TargetValue; 190 CurrentValue = TargetValue;
181 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={2}", 191 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}",
182 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); 192 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue);
183 } 193 }
184 194
@@ -186,6 +196,8 @@ public class BSVMotor : BSMotor
186 } 196 }
187 public virtual Vector3 Step(float timeStep, Vector3 error) 197 public virtual Vector3 Step(float timeStep, Vector3 error)
188 { 198 {
199 if (!Enabled) return Vector3.Zero;
200
189 LastError = error; 201 LastError = error;
190 Vector3 returnCorrection = Vector3.Zero; 202 Vector3 returnCorrection = Vector3.Zero;
191 if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) 203 if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
@@ -268,12 +280,14 @@ public class BSPIDVMotor : BSVMotor
268 public Vector3 proportionFactor { get; set; } 280 public Vector3 proportionFactor { get; set; }
269 public Vector3 integralFactor { get; set; } 281 public Vector3 integralFactor { get; set; }
270 public Vector3 derivFactor { get; set; } 282 public Vector3 derivFactor { get; set; }
283
271 // Arbritrary factor range. 284 // Arbritrary factor range.
272 // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct. 285 // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct.
273 public float EfficiencyHigh = 0.4f; 286 public float EfficiencyHigh = 0.4f;
274 public float EfficiencyLow = 4.0f; 287 public float EfficiencyLow = 4.0f;
275 288
276 Vector3 IntegralFactor { get; set; } 289 // Running integration of the error
290 Vector3 RunningIntegration { get; set; }
277 291
278 public BSPIDVMotor(string useName) 292 public BSPIDVMotor(string useName)
279 : base(useName) 293 : base(useName)
@@ -281,7 +295,7 @@ public class BSPIDVMotor : BSVMotor
281 proportionFactor = new Vector3(1.00f, 1.00f, 1.00f); 295 proportionFactor = new Vector3(1.00f, 1.00f, 1.00f);
282 integralFactor = new Vector3(1.00f, 1.00f, 1.00f); 296 integralFactor = new Vector3(1.00f, 1.00f, 1.00f);
283 derivFactor = new Vector3(1.00f, 1.00f, 1.00f); 297 derivFactor = new Vector3(1.00f, 1.00f, 1.00f);
284 IntegralFactor = Vector3.Zero; 298 RunningIntegration = Vector3.Zero;
285 LastError = Vector3.Zero; 299 LastError = Vector3.Zero;
286 } 300 }
287 301
@@ -311,15 +325,21 @@ public class BSPIDVMotor : BSVMotor
311 // Ignore Current and Target Values and just advance the PID computation on this error. 325 // Ignore Current and Target Values and just advance the PID computation on this error.
312 public override Vector3 Step(float timeStep, Vector3 error) 326 public override Vector3 Step(float timeStep, Vector3 error)
313 { 327 {
328 if (!Enabled) return Vector3.Zero;
329
314 // Add up the error so we can integrate over the accumulated errors 330 // Add up the error so we can integrate over the accumulated errors
315 IntegralFactor += error * timeStep; 331 RunningIntegration += error * timeStep;
316 332
317 // A simple derivitive is the rate of change from the last error. 333 // A simple derivitive is the rate of change from the last error.
318 Vector3 derivFactor = (error - LastError) * timeStep; 334 Vector3 derivFactor = (error - LastError) * timeStep;
319 LastError = error; 335 LastError = error;
320 336
321 // Correction = -(proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError) 337 // Correction = -(proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError)
322 Vector3 ret = -(error * proportionFactor + IntegralFactor * integralFactor + derivFactor * derivFactor); 338 Vector3 ret = -(
339 error * proportionFactor
340 + RunningIntegration * integralFactor
341 + derivFactor * derivFactor
342 );
323 343
324 return ret; 344 return ret;
325 } 345 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
new file mode 100755
index 0000000..5558ad5
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -0,0 +1,559 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Region.Physics.Manager;
32
33using OpenMetaverse;
34using Nini.Config;
35
36namespace OpenSim.Region.Physics.BulletSPlugin
37{
38public static class BSParam
39{
40 // Level of Detail values kept as float because that's what the Meshmerizer wants
41 public static float MeshLOD { get; private set; }
42 public static float MeshMegaPrimLOD { get; private set; }
43 public static float MeshMegaPrimThreshold { get; private set; }
44 public static float SculptLOD { get; private set; }
45
46 public static float MinimumObjectMass { get; private set; }
47 public static float MaximumObjectMass { get; private set; }
48
49 public static float LinearDamping { get; private set; }
50 public static float AngularDamping { get; private set; }
51 public static float DeactivationTime { get; private set; }
52 public static float LinearSleepingThreshold { get; private set; }
53 public static float AngularSleepingThreshold { get; private set; }
54 public static float CcdMotionThreshold { get; private set; }
55 public static float CcdSweptSphereRadius { get; private set; }
56 public static float ContactProcessingThreshold { get; private set; }
57
58 public static bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
59 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
60 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
61
62 public static float TerrainImplementation { get; private set; }
63 public static float TerrainFriction { get; private set; }
64 public static float TerrainHitFraction { get; private set; }
65 public static float TerrainRestitution { get; private set; }
66 public static float TerrainCollisionMargin { get; private set; }
67
68 // Avatar parameters
69 public static float AvatarFriction { get; private set; }
70 public static float AvatarStandingFriction { get; private set; }
71 public static float AvatarDensity { get; private set; }
72 public static float AvatarRestitution { get; private set; }
73 public static float AvatarCapsuleWidth { get; private set; }
74 public static float AvatarCapsuleDepth { get; private set; }
75 public static float AvatarCapsuleHeight { get; private set; }
76 public static float AvatarContactProcessingThreshold { get; private set; }
77
78 public static float VehicleAngularDamping { get; private set; }
79
80 public static float LinksetImplementation { get; private set; }
81 public static float LinkConstraintUseFrameOffset { get; private set; }
82 public static float LinkConstraintEnableTransMotor { get; private set; }
83 public static float LinkConstraintTransMotorMaxVel { get; private set; }
84 public static float LinkConstraintTransMotorMaxForce { get; private set; }
85 public static float LinkConstraintERP { get; private set; }
86 public static float LinkConstraintCFM { get; private set; }
87 public static float LinkConstraintSolverIterations { get; private set; }
88
89 public static float PID_D { get; private set; } // derivative
90 public static float PID_P { get; private set; } // proportional
91
92 public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
93 public delegate float ParamGet(BSScene scene);
94 public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
95 public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
96
97 public struct ParameterDefn
98 {
99 public string name; // string name of the parameter
100 public string desc; // a short description of what the parameter means
101 public float defaultValue; // default value if not specified anywhere else
102 public ParamUser userParam; // get the value from the configuration file
103 public ParamGet getter; // return the current value stored for this parameter
104 public ParamSet setter; // set the current value for this parameter
105 public SetOnObject onObject; // set the value on an object in the physical domain
106 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
107 {
108 name = n;
109 desc = d;
110 defaultValue = v;
111 userParam = u;
112 getter = g;
113 setter = s;
114 onObject = null;
115 }
116 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
117 {
118 name = n;
119 desc = d;
120 defaultValue = v;
121 userParam = u;
122 getter = g;
123 setter = s;
124 onObject = o;
125 }
126 }
127
128 // List of all of the externally visible parameters.
129 // For each parameter, this table maps a text name to getter and setters.
130 // To add a new externally referencable/settable parameter, add the paramter storage
131 // location somewhere in the program and make an entry in this table with the
132 // getters and setters.
133 // It is easiest to find an existing definition and copy it.
134 // Parameter values are floats. Booleans are converted to a floating value.
135 //
136 // A ParameterDefn() takes the following parameters:
137 // -- the text name of the parameter. This is used for console input and ini file.
138 // -- a short text description of the parameter. This shows up in the console listing.
139 // -- a default value (float)
140 // -- a delegate for fetching the parameter from the ini file.
141 // Should handle fetching the right type from the ini file and converting it.
142 // -- a delegate for getting the value as a float
143 // -- a delegate for setting the value from a float
144 // -- an optional delegate to update the value in the world. Most often used to
145 // push the new value to an in-world object.
146 //
147 // The single letter parameters for the delegates are:
148 // s = BSScene
149 // o = BSPhysObject
150 // p = string parameter name
151 // l = localID of referenced object
152 // v = value (float)
153 // cf = parameter configuration class (for fetching values from ini file)
154 private static ParameterDefn[] ParameterDefinitions =
155 {
156 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
157 ConfigurationParameters.numericTrue,
158 (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
159 (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); },
160 (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ),
161 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
162 ConfigurationParameters.numericFalse,
163 (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
164 (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); },
165 (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ),
166 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
167 ConfigurationParameters.numericTrue,
168 (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
169 (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); },
170 (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ),
171
172 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
173 8f,
174 (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
175 (s) => { return MeshLOD; },
176 (s,p,l,v) => { MeshLOD = v; } ),
177 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
178 16f,
179 (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
180 (s) => { return MeshMegaPrimLOD; },
181 (s,p,l,v) => { MeshMegaPrimLOD = v; } ),
182 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
183 10f,
184 (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
185 (s) => { return MeshMegaPrimThreshold; },
186 (s,p,l,v) => { MeshMegaPrimThreshold = v; } ),
187 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
188 32f,
189 (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
190 (s) => { return SculptLOD; },
191 (s,p,l,v) => { SculptLOD = v; } ),
192
193 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
194 10f,
195 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
196 (s) => { return (float)s.m_maxSubSteps; },
197 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
198 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
199 1f / 60f,
200 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
201 (s) => { return (float)s.m_fixedTimeStep; },
202 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
203 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
204 2048f,
205 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
206 (s) => { return (float)s.m_maxCollisionsPerFrame; },
207 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
208 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
209 8000f,
210 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
211 (s) => { return (float)s.m_maxUpdatesPerFrame; },
212 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
213 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
214 500f,
215 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
216 (s) => { return (float)s.m_taintsToProcessPerStep; },
217 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
218 new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
219 0.0001f,
220 (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
221 (s) => { return (float)MinimumObjectMass; },
222 (s,p,l,v) => { MinimumObjectMass = v; } ),
223 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
224 10000.01f,
225 (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
226 (s) => { return (float)MaximumObjectMass; },
227 (s,p,l,v) => { MaximumObjectMass = v; } ),
228
229 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
230 2200f,
231 (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
232 (s) => { return (float)PID_D; },
233 (s,p,l,v) => { PID_D = v; } ),
234 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
235 900f,
236 (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
237 (s) => { return (float)PID_P; },
238 (s,p,l,v) => { PID_P = v; } ),
239
240 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
241 0.2f,
242 (s,cf,p,v) => { s.UnmanagedParams[0].defaultFriction = cf.GetFloat(p, v); },
243 (s) => { return s.UnmanagedParams[0].defaultFriction; },
244 (s,p,l,v) => { s.UnmanagedParams[0].defaultFriction = v; } ),
245 new ParameterDefn("DefaultDensity", "Density for new objects" ,
246 10.000006836f, // Aluminum g/cm3
247 (s,cf,p,v) => { s.UnmanagedParams[0].defaultDensity = cf.GetFloat(p, v); },
248 (s) => { return s.UnmanagedParams[0].defaultDensity; },
249 (s,p,l,v) => { s.UnmanagedParams[0].defaultDensity = v; } ),
250 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
251 0f,
252 (s,cf,p,v) => { s.UnmanagedParams[0].defaultRestitution = cf.GetFloat(p, v); },
253 (s) => { return s.UnmanagedParams[0].defaultRestitution; },
254 (s,p,l,v) => { s.UnmanagedParams[0].defaultRestitution = v; } ),
255 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
256 0.04f,
257 (s,cf,p,v) => { s.UnmanagedParams[0].collisionMargin = cf.GetFloat(p, v); },
258 (s) => { return s.UnmanagedParams[0].collisionMargin; },
259 (s,p,l,v) => { s.UnmanagedParams[0].collisionMargin = v; } ),
260 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
261 -9.80665f,
262 (s,cf,p,v) => { s.UnmanagedParams[0].gravity = cf.GetFloat(p, v); },
263 (s) => { return s.UnmanagedParams[0].gravity; },
264 (s,p,l,v) => { s.UpdateParameterObject((x)=>{s.UnmanagedParams[0].gravity=x;}, p, PhysParameterEntry.APPLY_TO_NONE, v); },
265 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
266
267
268 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
269 0f,
270 (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
271 (s) => { return LinearDamping; },
272 (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearDamping=x;}, p, l, v); },
273 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, AngularDamping); } ),
274 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
275 0f,
276 (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
277 (s) => { return AngularDamping; },
278 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularDamping=x;}, p, l, v); },
279 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, LinearDamping, v); } ),
280 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
281 0.2f,
282 (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
283 (s) => { return DeactivationTime; },
284 (s,p,l,v) => { s.UpdateParameterObject((x)=>{DeactivationTime=x;}, p, l, v); },
285 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
286 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
287 0.8f,
288 (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
289 (s) => { return LinearSleepingThreshold; },
290 (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearSleepingThreshold=x;}, p, l, v); },
291 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
292 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
293 1.0f,
294 (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
295 (s) => { return AngularSleepingThreshold; },
296 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); },
297 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
298 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
299 0f, // set to zero to disable
300 (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
301 (s) => { return CcdMotionThreshold; },
302 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); },
303 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
304 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
305 0f,
306 (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
307 (s) => { return CcdSweptSphereRadius; },
308 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); },
309 (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
310 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
311 0.1f,
312 (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
313 (s) => { return ContactProcessingThreshold; },
314 (s,p,l,v) => { s.UpdateParameterObject((x)=>{ContactProcessingThreshold=x;}, p, l, v); },
315 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
316
317 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
318 (float)BSTerrainPhys.TerrainImplementation.Mesh,
319 (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
320 (s) => { return TerrainImplementation; },
321 (s,p,l,v) => { TerrainImplementation = v; } ),
322 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
323 0.3f,
324 (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
325 (s) => { return TerrainFriction; },
326 (s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
327 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
328 0.8f,
329 (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
330 (s) => { return TerrainHitFraction; },
331 (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
332 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
333 0f,
334 (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
335 (s) => { return TerrainRestitution; },
336 (s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
337 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
338 0.04f,
339 (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
340 (s) => { return TerrainCollisionMargin; },
341 (s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
342
343 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
344 0.2f,
345 (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
346 (s) => { return AvatarFriction; },
347 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarFriction=x;}, p, l, v); } ),
348 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
349 10.0f,
350 (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
351 (s) => { return AvatarStandingFriction; },
352 (s,p,l,v) => { AvatarStandingFriction = v; } ),
353 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
354 60f,
355 (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
356 (s) => { return AvatarDensity; },
357 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ),
358 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
359 0f,
360 (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
361 (s) => { return AvatarRestitution; },
362 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarRestitution=x;}, p, l, v); } ),
363 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
364 0.6f,
365 (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
366 (s) => { return AvatarCapsuleWidth; },
367 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleWidth=x;}, p, l, v); } ),
368 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
369 0.45f,
370 (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
371 (s) => { return AvatarCapsuleDepth; },
372 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleDepth=x;}, p, l, v); } ),
373 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
374 1.5f,
375 (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
376 (s) => { return AvatarCapsuleHeight; },
377 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleHeight=x;}, p, l, v); } ),
378 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
379 0.1f,
380 (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
381 (s) => { return AvatarContactProcessingThreshold; },
382 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ),
383
384 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
385 0.95f,
386 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
387 (s) => { return VehicleAngularDamping; },
388 (s,p,l,v) => { VehicleAngularDamping = v; } ),
389
390 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
391 0f,
392 (s,cf,p,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
393 (s) => { return s.UnmanagedParams[0].maxPersistantManifoldPoolSize; },
394 (s,p,l,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
395 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
396 0f,
397 (s,cf,p,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
398 (s) => { return s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize; },
399 (s,p,l,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
400 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
401 ConfigurationParameters.numericFalse,
402 (s,cf,p,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
403 (s) => { return s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation; },
404 (s,p,l,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ),
405 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
406 ConfigurationParameters.numericFalse,
407 (s,cf,p,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
408 (s) => { return s.UnmanagedParams[0].shouldForceUpdateAllAabbs; },
409 (s,p,l,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ),
410 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
411 ConfigurationParameters.numericTrue,
412 (s,cf,p,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
413 (s) => { return s.UnmanagedParams[0].shouldRandomizeSolverOrder; },
414 (s,p,l,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ),
415 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
416 ConfigurationParameters.numericTrue,
417 (s,cf,p,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
418 (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; },
419 (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ),
420 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
421 ConfigurationParameters.numericFalse,
422 (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
423 (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; },
424 (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ),
425 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
426 0f, // zero says use Bullet default
427 (s,cf,p,v) => { s.UnmanagedParams[0].numberOfSolverIterations = cf.GetFloat(p, v); },
428 (s) => { return s.UnmanagedParams[0].numberOfSolverIterations; },
429 (s,p,l,v) => { s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
430
431 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
432 (float)BSLinkset.LinksetImplementation.Compound,
433 (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
434 (s) => { return LinksetImplementation; },
435 (s,p,l,v) => { LinksetImplementation = v; } ),
436 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
437 ConfigurationParameters.numericFalse,
438 (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
439 (s) => { return LinkConstraintUseFrameOffset; },
440 (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ),
441 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
442 ConfigurationParameters.numericTrue,
443 (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
444 (s) => { return LinkConstraintEnableTransMotor; },
445 (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ),
446 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
447 5.0f,
448 (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
449 (s) => { return LinkConstraintTransMotorMaxVel; },
450 (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ),
451 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
452 0.1f,
453 (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
454 (s) => { return LinkConstraintTransMotorMaxForce; },
455 (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ),
456 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
457 0.1f,
458 (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
459 (s) => { return LinkConstraintCFM; },
460 (s,p,l,v) => { LinkConstraintCFM = v; } ),
461 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
462 0.1f,
463 (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
464 (s) => { return LinkConstraintERP; },
465 (s,p,l,v) => { LinkConstraintERP = v; } ),
466 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
467 40,
468 (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
469 (s) => { return LinkConstraintSolverIterations; },
470 (s,p,l,v) => { LinkConstraintSolverIterations = v; } ),
471
472 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
473 0f,
474 (s,cf,p,v) => { s.UnmanagedParams[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
475 (s) => { return (float)s.UnmanagedParams[0].physicsLoggingFrames; },
476 (s,p,l,v) => { s.UnmanagedParams[0].physicsLoggingFrames = (int)v; } ),
477 };
478
479 // Convert a boolean to our numeric true and false values
480 public static float NumericBool(bool b)
481 {
482 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
483 }
484
485 // Convert numeric true and false values to a boolean
486 public static bool BoolNumeric(float b)
487 {
488 return (b == ConfigurationParameters.numericTrue ? true : false);
489 }
490
491 // Search through the parameter definitions and return the matching
492 // ParameterDefn structure.
493 // Case does not matter as names are compared after converting to lower case.
494 // Returns 'false' if the parameter is not found.
495 internal static bool TryGetParameter(string paramName, out ParameterDefn defn)
496 {
497 bool ret = false;
498 ParameterDefn foundDefn = new ParameterDefn();
499 string pName = paramName.ToLower();
500
501 foreach (ParameterDefn parm in ParameterDefinitions)
502 {
503 if (pName == parm.name.ToLower())
504 {
505 foundDefn = parm;
506 ret = true;
507 break;
508 }
509 }
510 defn = foundDefn;
511 return ret;
512 }
513
514 // Pass through the settable parameters and set the default values
515 internal static void SetParameterDefaultValues(BSScene physicsScene)
516 {
517 foreach (ParameterDefn parm in ParameterDefinitions)
518 {
519 parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
520 }
521 }
522
523 // Get user set values out of the ini file.
524 internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
525 {
526 foreach (ParameterDefn parm in ParameterDefinitions)
527 {
528 parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue);
529 }
530 }
531
532 internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
533
534 // This creates an array in the correct format for returning the list of
535 // parameters. This is used by the 'list' option of the 'physics' command.
536 internal static void BuildParameterTable()
537 {
538 if (SettableParameters.Length < ParameterDefinitions.Length)
539 {
540 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
541 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
542 {
543 ParameterDefn pd = ParameterDefinitions[ii];
544 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
545 }
546
547 // make the list in alphabetical order for estetic reasons
548 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
549 {
550 return ppe1.name.CompareTo(ppe2.name);
551 });
552
553 SettableParameters = entries.ToArray();
554 }
555 }
556
557
558}
559}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 92a5f2f..c76f869 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -45,6 +45,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. 45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
46 * The last two (and certainly the last one) should be referenced only in taint-time. 46 * The last two (and certainly the last one) should be referenced only in taint-time.
47 */ 47 */
48
49/*
50 * As of 20121221, the following are the call sequences (going down) for different script physical functions:
51 * llApplyImpulse llApplyRotImpulse llSetTorque llSetForce
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque
56 */
57
48public abstract class BSPhysObject : PhysicsActor 58public abstract class BSPhysObject : PhysicsActor
49{ 59{
50 protected BSPhysObject() 60 protected BSPhysObject()
@@ -69,6 +79,12 @@ public abstract class BSPhysObject : PhysicsActor
69 CollidingGroundStep = 0; 79 CollidingGroundStep = 0;
70 } 80 }
71 81
82 // Tell the object to clean up.
83 public virtual void Destroy()
84 {
85 UnRegisterAllPreStepActions();
86 }
87
72 public BSScene PhysicsScene { get; protected set; } 88 public BSScene PhysicsScene { get; protected set; }
73 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 89 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
74 public string PhysObjectName { get; protected set; } 90 public string PhysObjectName { get; protected set; }
@@ -130,9 +146,6 @@ public abstract class BSPhysObject : PhysicsActor
130 // Update the physical location and motion of the object. Called with data from Bullet. 146 // Update the physical location and motion of the object. Called with data from Bullet.
131 public abstract void UpdateProperties(EntityProperties entprop); 147 public abstract void UpdateProperties(EntityProperties entprop);
132 148
133 // Tell the object to clean up.
134 public abstract void Destroy();
135
136 public abstract OMV.Vector3 RawPosition { get; set; } 149 public abstract OMV.Vector3 RawPosition { get; set; }
137 public abstract OMV.Vector3 ForcePosition { get; set; } 150 public abstract OMV.Vector3 ForcePosition { get; set; }
138 151
@@ -140,7 +153,7 @@ public abstract class BSPhysObject : PhysicsActor
140 public abstract OMV.Quaternion ForceOrientation { get; set; } 153 public abstract OMV.Quaternion ForceOrientation { get; set; }
141 154
142 // The system is telling us the velocity it wants to move at. 155 // The system is telling us the velocity it wants to move at.
143 protected OMV.Vector3 m_targetVelocity; 156 // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor
144 public override OMV.Vector3 TargetVelocity 157 public override OMV.Vector3 TargetVelocity
145 { 158 {
146 get { return m_targetVelocity; } 159 get { return m_targetVelocity; }
@@ -280,11 +293,53 @@ public abstract class BSPhysObject : PhysicsActor
280 293
281 #endregion // Collisions 294 #endregion // Collisions
282 295
296 #region Per Simulation Step actions
297 // There are some actions that must be performed for a physical object before each simulation step.
298 // These actions are optional so, rather than scanning all the physical objects and asking them
299 // if they have anything to do, a physical object registers for an event call before the step is performed.
300 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
301 private Dictionary<string, BSScene.PreStepAction> RegisteredActions = new Dictionary<string, BSScene.PreStepAction>();
302 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
303 {
304 string identifier = op + "-" + id.ToString();
305 RegisteredActions[identifier] = actn;
306 PhysicsScene.BeforeStep += actn;
307 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
308 }
309
310 // Unregister a pre step action. Safe to call if the action has not been registered.
311 protected void UnRegisterPreStepAction(string op, uint id)
312 {
313 string identifier = op + "-" + id.ToString();
314 bool removed = false;
315 if (RegisteredActions.ContainsKey(identifier))
316 {
317 PhysicsScene.BeforeStep -= RegisteredActions[identifier];
318 RegisteredActions.Remove(identifier);
319 removed = true;
320 }
321 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
322 }
323
324 protected void UnRegisterAllPreStepActions()
325 {
326 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
327 {
328 PhysicsScene.BeforeStep -= kvp.Value;
329 }
330 RegisteredActions.Clear();
331 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
332 }
333
334
335 #endregion // Per Simulation Step actions
336
283 // High performance detailed logging routine used by the physical objects. 337 // High performance detailed logging routine used by the physical objects.
284 protected void DetailLog(string msg, params Object[] args) 338 protected void DetailLog(string msg, params Object[] args)
285 { 339 {
286 if (PhysicsScene.PhysicsLogging.Enabled) 340 if (PhysicsScene.PhysicsLogging.Enabled)
287 PhysicsScene.DetailLog(msg, args); 341 PhysicsScene.DetailLog(msg, args);
288 } 342 }
343
289} 344}
290} 345}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 68a0db6..26b8df5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -129,6 +129,7 @@ public sealed class BSPrim : BSPhysObject
129 public override void Destroy() 129 public override void Destroy()
130 { 130 {
131 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 131 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
132 base.Destroy();
132 133
133 // Undo any links between me and any other object 134 // Undo any links between me and any other object
134 BSPhysObject parentBefore = Linkset.LinksetRoot; 135 BSPhysObject parentBefore = Linkset.LinksetRoot;
@@ -434,12 +435,26 @@ public sealed class BSPrim : BSPhysObject
434 get { return _force; } 435 get { return _force; }
435 set { 436 set {
436 _force = value; 437 _force = value;
437 PhysicsScene.TaintedObject("BSPrim.setForce", delegate() 438 if (_force != OMV.Vector3.Zero)
438 { 439 {
439 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 440 // If the force is non-zero, it must be reapplied each tick because
440 if (PhysBody.HasPhysicalBody) 441 // Bullet clears the forces applied last frame.
441 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 442 RegisterPreStepAction("BSPrim.setForce", LocalID,
442 }); 443 delegate(float timeStep)
444 {
445 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force);
446 if (PhysBody.HasPhysicalBody)
447 {
448 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, _force);
449 ActivateIfPhysical(false);
450 }
451 }
452 );
453 }
454 else
455 {
456 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
457 }
443 } 458 }
444 } 459 }
445 460
@@ -450,15 +465,18 @@ public sealed class BSPrim : BSPhysObject
450 set { 465 set {
451 Vehicle type = (Vehicle)value; 466 Vehicle type = (Vehicle)value;
452 467
453 // Tell the scene about the vehicle so it will get processing each frame.
454 PhysicsScene.VehicleInSceneTypeChanged(this, type);
455
456 PhysicsScene.TaintedObject("setVehicleType", delegate() 468 PhysicsScene.TaintedObject("setVehicleType", delegate()
457 { 469 {
458 // Done at taint time so we're sure the physics engine is not using the variables 470 // Done at taint time so we're sure the physics engine is not using the variables
459 // Vehicle code changes the parameters for this vehicle type. 471 // Vehicle code changes the parameters for this vehicle type.
460 _vehicle.ProcessTypeChange(type); 472 _vehicle.ProcessTypeChange(type);
461 ActivateIfPhysical(false); 473 ActivateIfPhysical(false);
474
475 // If an active vehicle, register the vehicle code to be called before each step
476 if (_vehicle.Type == Vehicle.TYPE_NONE)
477 UnRegisterPreStepAction("BSPrim.Vehicle", LocalID);
478 else
479 RegisterPreStepAction("BSPrim.Vehicle", LocalID, _vehicle.Step);
462 }); 480 });
463 } 481 }
464 } 482 }
@@ -494,23 +512,6 @@ public sealed class BSPrim : BSPhysObject
494 }); 512 });
495 } 513 }
496 514
497 // Called each simulation step to advance vehicle characteristics.
498 // Called from Scene when doing simulation step so we're in taint processing time.
499 public override void StepVehicle(float timeStep)
500 {
501 if (IsPhysical && _vehicle.IsActive)
502 {
503 _vehicle.Step(timeStep);
504 /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step
505 PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate()
506 {
507 // This resets the interpolation values and recomputes the tensor variables
508 BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation);
509 });
510 */
511 }
512 }
513
514 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 515 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
515 public override void SetVolumeDetect(int param) { 516 public override void SetVolumeDetect(int param) {
516 bool newValue = (param != 0); 517 bool newValue = (param != 0);
@@ -543,14 +544,32 @@ public sealed class BSPrim : BSPhysObject
543 544
544 _velocity = value; 545 _velocity = value;
545 if (PhysBody.HasPhysicalBody) 546 if (PhysBody.HasPhysicalBody)
547 {
546 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); 548 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
549 ActivateIfPhysical(false);
550 }
547 } 551 }
548 } 552 }
549 public override OMV.Vector3 Torque { 553 public override OMV.Vector3 Torque {
550 get { return _torque; } 554 get { return _torque; }
551 set { 555 set {
552 _torque = value; 556 _torque = value;
553 AddAngularForce(_torque, false, false); 557 if (_torque != OMV.Vector3.Zero)
558 {
559 // If the torque is non-zero, it must be reapplied each tick because
560 // Bullet clears the forces applied last frame.
561 RegisterPreStepAction("BSPrim.setTorque", LocalID,
562 delegate(float timeStep)
563 {
564 if (PhysBody.HasPhysicalBody)
565 AddAngularForce(_torque, false, true);
566 }
567 );
568 }
569 else
570 {
571 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
572 }
554 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 573 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
555 } 574 }
556 } 575 }
@@ -720,10 +739,10 @@ public sealed class BSPrim : BSPhysObject
720 // Mass is zero which disables a bunch of physics stuff in Bullet 739 // Mass is zero which disables a bunch of physics stuff in Bullet
721 UpdatePhysicalMassProperties(0f); 740 UpdatePhysicalMassProperties(0f);
722 // Set collision detection parameters 741 // Set collision detection parameters
723 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 742 if (BSParam.CcdMotionThreshold > 0f)
724 { 743 {
725 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 744 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold);
726 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 745 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius);
727 } 746 }
728 747
729 // The activation state is 'disabled' so Bullet will not try to act on it. 748 // The activation state is 'disabled' so Bullet will not try to act on it.
@@ -761,17 +780,17 @@ public sealed class BSPrim : BSPhysObject
761 UpdatePhysicalMassProperties(RawMass); 780 UpdatePhysicalMassProperties(RawMass);
762 781
763 // Set collision detection parameters 782 // Set collision detection parameters
764 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 783 if (BSParam.CcdMotionThreshold > 0f)
765 { 784 {
766 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 785 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, BSParam.CcdMotionThreshold);
767 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 786 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, BSParam.CcdSweptSphereRadius);
768 } 787 }
769 788
770 // Various values for simulation limits 789 // Various values for simulation limits
771 BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); 790 BulletSimAPI.SetDamping2(PhysBody.ptr, BSParam.LinearDamping, BSParam.AngularDamping);
772 BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); 791 BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, BSParam.DeactivationTime);
773 BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); 792 BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
774 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); 793 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, BSParam.ContactProcessingThreshold);
775 794
776 // This collides like an object. 795 // This collides like an object.
777 PhysBody.collisionType = CollisionType.Dynamic; 796 PhysBody.collisionType = CollisionType.Dynamic;
@@ -819,7 +838,7 @@ public sealed class BSPrim : BSPhysObject
819 // Called in taint-time!! 838 // Called in taint-time!!
820 private void ActivateIfPhysical(bool forceIt) 839 private void ActivateIfPhysical(bool forceIt)
821 { 840 {
822 if (IsPhysical) 841 if (IsPhysical && PhysBody.HasPhysicalBody)
823 BulletSimAPI.Activate2(PhysBody.ptr, forceIt); 842 BulletSimAPI.Activate2(PhysBody.ptr, forceIt);
824 } 843 }
825 844
@@ -893,8 +912,7 @@ public sealed class BSPrim : BSPhysObject
893 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 912 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
894 { 913 {
895 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 914 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
896 if (PhysBody.HasPhysicalBody) 915 ForceRotationalVelocity = _rotationalVelocity;
897 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
898 }); 916 });
899 } 917 }
900 } 918 }
@@ -904,7 +922,11 @@ public sealed class BSPrim : BSPhysObject
904 } 922 }
905 set { 923 set {
906 _rotationalVelocity = value; 924 _rotationalVelocity = value;
907 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); 925 if (PhysBody.HasPhysicalBody)
926 {
927 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
928 ActivateIfPhysical(false);
929 }
908 } 930 }
909 } 931 }
910 public override bool Kinematic { 932 public override bool Kinematic {
@@ -933,6 +955,7 @@ public sealed class BSPrim : BSPhysObject
933 { 955 {
934 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); 956 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
935 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); 957 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
958 ActivateIfPhysical(false);
936 } 959 }
937 } 960 }
938 } 961 }
@@ -969,56 +992,35 @@ public sealed class BSPrim : BSPhysObject
969 public override float APIDStrength { set { return; } } 992 public override float APIDStrength { set { return; } }
970 public override float APIDDamping { set { return; } } 993 public override float APIDDamping { set { return; } }
971 994
972 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
973 public override void AddForce(OMV.Vector3 force, bool pushforce) { 995 public override void AddForce(OMV.Vector3 force, bool pushforce) {
974 AddForce(force, pushforce, false); 996 AddForce(force, pushforce, false);
975 } 997 }
976 // Applying a force just adds this to the total force on the object. 998 // Applying a force just adds this to the total force on the object.
999 // This added force will only last the next simulation tick.
977 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1000 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
978 // for an object, doesn't matter if force is a pushforce or not 1001 // for an object, doesn't matter if force is a pushforce or not
979 if (force.IsFinite()) 1002 if (force.IsFinite())
980 { 1003 {
981 // _force += force; 1004 OMV.Vector3 addForce = force;
982 lock (m_accumulatedForces) 1005 DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
983 m_accumulatedForces.Add(new OMV.Vector3(force)); 1006 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1007 {
1008 // Bullet adds this central force to the total force for this tick
1009 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1010 if (PhysBody.HasPhysicalBody)
1011 {
1012 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, addForce);
1013 ActivateIfPhysical(false);
1014 }
1015 });
984 } 1016 }
985 else 1017 else
986 { 1018 {
987 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 1019 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
988 return; 1020 return;
989 } 1021 }
990 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
991 {
992 OMV.Vector3 fSum = OMV.Vector3.Zero;
993 lock (m_accumulatedForces)
994 {
995 // Sum the accumulated additional forces for one big force to apply once.
996 foreach (OMV.Vector3 v in m_accumulatedForces)
997 {
998 fSum += v;
999 }
1000 m_accumulatedForces.Clear();
1001 }
1002 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
1003 if (fSum != OMV.Vector3.Zero)
1004 if (PhysBody.HasPhysicalBody)
1005 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
1006 });
1007 } 1022 }
1008 1023
1009 // An impulse force is scaled by the mass of the object.
1010 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
1011 {
1012 OMV.Vector3 applyImpulse = impulse;
1013 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
1014 {
1015 DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
1016 if (PhysBody.HasPhysicalBody)
1017 BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
1018 });
1019 }
1020
1021 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
1022 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1024 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
1023 AddAngularForce(force, pushforce, false); 1025 AddAngularForce(force, pushforce, false);
1024 } 1026 }
@@ -1026,36 +1028,23 @@ public sealed class BSPrim : BSPhysObject
1026 { 1028 {
1027 if (force.IsFinite()) 1029 if (force.IsFinite())
1028 { 1030 {
1029 // _force += force; 1031 OMV.Vector3 angForce = force;
1030 lock (m_accumulatedAngularForces) 1032 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1031 m_accumulatedAngularForces.Add(new OMV.Vector3(force)); 1033 {
1034 if (PhysBody.HasPhysicalBody)
1035 {
1036 BulletSimAPI.ApplyTorque2(PhysBody.ptr, angForce);
1037 ActivateIfPhysical(false);
1038 }
1039 });
1032 } 1040 }
1033 else 1041 else
1034 { 1042 {
1035 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 1043 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
1036 return; 1044 return;
1037 } 1045 }
1038 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1039 {
1040 OMV.Vector3 fSum = OMV.Vector3.Zero;
1041 lock (m_accumulatedAngularForces)
1042 {
1043 // Sum the accumulated additional forces for one big force to apply once.
1044 foreach (OMV.Vector3 v in m_accumulatedAngularForces)
1045 {
1046 fSum += v;
1047 }
1048 m_accumulatedAngularForces.Clear();
1049 }
1050 DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
1051 if (fSum != OMV.Vector3.Zero)
1052 {
1053 if (PhysBody.HasPhysicalBody)
1054 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
1055 _torque = fSum;
1056 }
1057 });
1058 } 1046 }
1047
1059 // A torque impulse. 1048 // A torque impulse.
1060 // ApplyTorqueImpulse adds torque directly to the angularVelocity. 1049 // ApplyTorqueImpulse adds torque directly to the angularVelocity.
1061 // AddAngularForce accumulates the force and applied it to the angular velocity all at once. 1050 // AddAngularForce accumulates the force and applied it to the angular velocity all at once.
@@ -1066,7 +1055,10 @@ public sealed class BSPrim : BSPhysObject
1066 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1055 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1067 { 1056 {
1068 if (PhysBody.HasPhysicalBody) 1057 if (PhysBody.HasPhysicalBody)
1058 {
1069 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); 1059 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
1060 ActivateIfPhysical(false);
1061 }
1070 }); 1062 });
1071 } 1063 }
1072 1064
@@ -1361,11 +1353,7 @@ public sealed class BSPrim : BSPhysObject
1361 } 1353 }
1362 */ 1354 */
1363 1355
1364 if (returnMass <= 0) 1356 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
1365 returnMass = 0.0001f;
1366
1367 if (returnMass > PhysicsScene.MaximumObjectMass)
1368 returnMass = PhysicsScene.MaximumObjectMass;
1369 1357
1370 return returnMass; 1358 return returnMass;
1371 }// end CalculateMass 1359 }// end CalculateMass
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 2ca4912..e8e0d50 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -69,20 +69,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
69 // every tick so OpenSim will update its animation. 69 // every tick so OpenSim will update its animation.
70 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>(); 70 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
71 71
72 // List of all the objects that have vehicle properties and should be called
73 // to update each physics step.
74 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
75
76 // let my minuions use my logger 72 // let my minuions use my logger
77 public ILog Logger { get { return m_log; } } 73 public ILog Logger { get { return m_log; } }
78 74
79 public IMesher mesher; 75 public IMesher mesher;
80 // Level of Detail values kept as float because that's what the Meshmerizer wants
81 public float MeshLOD { get; private set; }
82 public float MeshMegaPrimLOD { get; private set; }
83 public float MeshMegaPrimThreshold { get; private set; }
84 public float SculptLOD { get; private set; }
85
86 public uint WorldID { get; private set; } 76 public uint WorldID { get; private set; }
87 public BulletSim World { get; private set; } 77 public BulletSim World { get; private set; }
88 78
@@ -90,24 +80,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
90 public BSConstraintCollection Constraints { get; private set; } 80 public BSConstraintCollection Constraints { get; private set; }
91 81
92 // Simulation parameters 82 // Simulation parameters
93 private int m_maxSubSteps; 83 internal int m_maxSubSteps;
94 private float m_fixedTimeStep; 84 internal float m_fixedTimeStep;
95 private long m_simulationStep = 0; 85 internal long m_simulationStep = 0;
96 public long SimulationStep { get { return m_simulationStep; } } 86 public long SimulationStep { get { return m_simulationStep; } }
97 private int m_taintsToProcessPerStep; 87 internal int m_taintsToProcessPerStep;
98 88 internal float LastTimeStep { get; private set; }
99 // Avatar parameters
100 public float ParamAvatarFriction { get; private set; }
101 public float ParamAvatarStandingFriction { get; private set; }
102 public float ParamAvatarDensity { get; private set; }
103 public float ParamAvatarRestitution { get; private set; }
104 public float ParamAvatarCapsuleWidth { get; private set; }
105 public float ParamAvatarCapsuleDepth { get; private set; }
106 public float ParamAvatarCapsuleHeight { get; private set; }
107 public float ParamAvatarContactProcessingThreshold { get; private set; }
108 89
90 // Physical objects can register for prestep or poststep events
109 public delegate void PreStepAction(float timeStep); 91 public delegate void PreStepAction(float timeStep);
92 public delegate void PostStepAction(float timeStep);
110 public event PreStepAction BeforeStep; 93 public event PreStepAction BeforeStep;
94 public event PreStepAction AfterStep;
111 95
112 // A value of the time now so all the collision and update routines do not have to get their own 96 // A value of the time now so all the collision and update routines do not have to get their own
113 // Set to 'now' just before all the prims and actors are called for collisions and updates 97 // Set to 'now' just before all the prims and actors are called for collisions and updates
@@ -121,20 +105,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
121 public bool InTaintTime { get; private set; } 105 public bool InTaintTime { get; private set; }
122 106
123 // Pinned memory used to pass step information between managed and unmanaged 107 // Pinned memory used to pass step information between managed and unmanaged
124 private int m_maxCollisionsPerFrame; 108 internal int m_maxCollisionsPerFrame;
125 private CollisionDesc[] m_collisionArray; 109 internal CollisionDesc[] m_collisionArray;
126 private GCHandle m_collisionArrayPinnedHandle; 110 internal GCHandle m_collisionArrayPinnedHandle;
127
128 private int m_maxUpdatesPerFrame;
129 private EntityProperties[] m_updateArray;
130 private GCHandle m_updateArrayPinnedHandle;
131 111
132 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed 112 internal int m_maxUpdatesPerFrame;
133 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 113 internal EntityProperties[] m_updateArray;
134 public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 114 internal GCHandle m_updateArrayPinnedHandle;
135
136 public float PID_D { get; private set; } // derivative
137 public float PID_P { get; private set; } // proportional
138 115
139 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 116 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
140 public const uint GROUNDPLANE_ID = 1; 117 public const uint GROUNDPLANE_ID = 1;
@@ -145,7 +122,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
145 122
146 public ConfigurationParameters Params 123 public ConfigurationParameters Params
147 { 124 {
148 get { return m_params[0]; } 125 get { return UnmanagedParams[0]; }
149 } 126 }
150 public Vector3 DefaultGravity 127 public Vector3 DefaultGravity
151 { 128 {
@@ -157,8 +134,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
157 get { return Params.gravity; } 134 get { return Params.gravity; }
158 } 135 }
159 136
160 public float MaximumObjectMass { get; private set; }
161
162 // When functions in the unmanaged code must be called, it is only 137 // When functions in the unmanaged code must be called, it is only
163 // done at a known time just before the simulation step. The taint 138 // done at a known time just before the simulation step. The taint
164 // system saves all these function calls and executes them in 139 // system saves all these function calls and executes them in
@@ -181,7 +156,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
181 156
182 // A pointer to an instance if this structure is passed to the C++ code 157 // A pointer to an instance if this structure is passed to the C++ code
183 // Used to pass basic configuration values to the unmanaged code. 158 // Used to pass basic configuration values to the unmanaged code.
184 ConfigurationParameters[] m_params; 159 internal ConfigurationParameters[] UnmanagedParams;
185 GCHandle m_paramsHandle; 160 GCHandle m_paramsHandle;
186 161
187 // Handle to the callback used by the unmanaged code to call into the managed code. 162 // Handle to the callback used by the unmanaged code to call into the managed code.
@@ -218,8 +193,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
218 Shapes = new BSShapeCollection(this); 193 Shapes = new BSShapeCollection(this);
219 194
220 // Allocate pinned memory to pass parameters. 195 // Allocate pinned memory to pass parameters.
221 m_params = new ConfigurationParameters[1]; 196 UnmanagedParams = new ConfigurationParameters[1];
222 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); 197 m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned);
223 198
224 // Set default values for physics parameters plus any overrides from the ini file 199 // Set default values for physics parameters plus any overrides from the ini file
225 GetInitialParameterValues(config); 200 GetInitialParameterValues(config);
@@ -277,7 +252,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
277 TerrainManager = new BSTerrainManager(this); 252 TerrainManager = new BSTerrainManager(this);
278 TerrainManager.CreateInitialGroundPlaneAndTerrain(); 253 TerrainManager.CreateInitialGroundPlaneAndTerrain();
279 254
280 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); 255 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation);
281 256
282 InTaintTime = false; 257 InTaintTime = false;
283 m_initialized = true; 258 m_initialized = true;
@@ -288,9 +263,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
288 private void GetInitialParameterValues(IConfigSource config) 263 private void GetInitialParameterValues(IConfigSource config)
289 { 264 {
290 ConfigurationParameters parms = new ConfigurationParameters(); 265 ConfigurationParameters parms = new ConfigurationParameters();
291 m_params[0] = parms; 266 UnmanagedParams[0] = parms;
292 267
293 SetParameterDefaultValues(); 268 BSParam.SetParameterDefaultValues(this);
294 269
295 if (config != null) 270 if (config != null)
296 { 271 {
@@ -298,7 +273,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
298 IConfig pConfig = config.Configs["BulletSim"]; 273 IConfig pConfig = config.Configs["BulletSim"];
299 if (pConfig != null) 274 if (pConfig != null)
300 { 275 {
301 SetParameterConfigurationValues(pConfig); 276 BSParam.SetParameterConfigurationValues(this, pConfig);
302 277
303 // Very detailed logging for physics debugging 278 // Very detailed logging for physics debugging
304 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 279 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@@ -492,6 +467,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
492 // Simulate one timestep 467 // Simulate one timestep
493 public override float Simulate(float timeStep) 468 public override float Simulate(float timeStep)
494 { 469 {
470 // prevent simulation until we've been initialized
471 if (!m_initialized) return 5.0f;
472
473 LastTimeStep = timeStep;
474
495 int updatedEntityCount = 0; 475 int updatedEntityCount = 0;
496 IntPtr updatedEntitiesPtr; 476 IntPtr updatedEntitiesPtr;
497 int collidersCount = 0; 477 int collidersCount = 0;
@@ -500,26 +480,27 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
500 int beforeTime = 0; 480 int beforeTime = 0;
501 int simTime = 0; 481 int simTime = 0;
502 482
503 // prevent simulation until we've been initialized
504 if (!m_initialized) return 5.0f;
505
506 // update the prim states while we know the physics engine is not busy 483 // update the prim states while we know the physics engine is not busy
507 int numTaints = _taintOperations.Count; 484 int numTaints = _taintOperations.Count;
485
486 InTaintTime = true; // Only used for debugging so locking is not necessary.
487
508 ProcessTaints(); 488 ProcessTaints();
509 489
510 // Some of the prims operate with special vehicle properties 490 // Some of the physical objects requre individual, pre-step calls
511 DoPreStepActions(timeStep); 491 TriggerPreStepEvent(timeStep);
512 492
513 // the prestep actions might have added taints 493 // the prestep actions might have added taints
514 ProcessTaints(); 494 ProcessTaints();
515 495
496 InTaintTime = false; // Only used for debugging so locking is not necessary.
497
516 // step the physical world one interval 498 // step the physical world one interval
517 m_simulationStep++; 499 m_simulationStep++;
518 int numSubSteps = 0; 500 int numSubSteps = 0;
519 501
520 try 502 try
521 { 503 {
522 if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
523 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 504 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
524 505
525 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 506 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
@@ -529,7 +510,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
529 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", 510 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
530 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, 511 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
531 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); 512 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
532 if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
533 } 513 }
534 catch (Exception e) 514 catch (Exception e)
535 { 515 {
@@ -608,7 +588,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
608 } 588 }
609 } 589 }
610 590
611 ProcessPostStepTaints(); 591 TriggerPostStepEvent(timeStep);
612 592
613 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. 593 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
614 // Only enable this in a limited test world with few objects. 594 // Only enable this in a limited test world with few objects.
@@ -700,6 +680,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
700 public override bool IsThreaded { get { return false; } } 680 public override bool IsThreaded { get { return false; } }
701 681
702 #region Taints 682 #region Taints
683 // The simulation execution order is:
684 // Simulate()
685 // DoOneTimeTaints
686 // TriggerPreStepEvent
687 // DoOneTimeTaints
688 // Step()
689 // ProcessAndForwardCollisions
690 // ProcessAndForwardPropertyUpdates
691 // TriggerPostStepEvent
703 692
704 // Calls to the PhysicsActors can't directly call into the physics engine 693 // Calls to the PhysicsActors can't directly call into the physics engine
705 // because it might be busy. We delay changes to a known time. 694 // because it might be busy. We delay changes to a known time.
@@ -726,58 +715,35 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
726 TaintedObject(ident, callback); 715 TaintedObject(ident, callback);
727 } 716 }
728 717
718 private void TriggerPreStepEvent(float timeStep)
719 {
720 PreStepAction actions = BeforeStep;
721 if (actions != null)
722 actions(timeStep);
723
724 }
725
726 private void TriggerPostStepEvent(float timeStep)
727 {
728 PreStepAction actions = AfterStep;
729 if (actions != null)
730 actions(timeStep);
731
732 }
733
729 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues 734 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
730 // a callback into itself to do the actual property change. That callback is called 735 // a callback into itself to do the actual property change. That callback is called
731 // here just before the physics engine is called to step the simulation. 736 // here just before the physics engine is called to step the simulation.
732 public void ProcessTaints() 737 public void ProcessTaints()
733 { 738 {
734 InTaintTime = true; // Only used for debugging so locking is not necessary.
735 ProcessRegularTaints(); 739 ProcessRegularTaints();
736 ProcessPostTaintTaints(); 740 ProcessPostTaintTaints();
737 InTaintTime = false;
738 } 741 }
739 742
740 private void ProcessRegularTaints() 743 private void ProcessRegularTaints()
741 { 744 {
742 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process 745 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process
743 { 746 {
744 /*
745 // Code to limit the number of taints processed per step. Meant to limit step time.
746 // Unsure if a good idea as code assumes that taints are done before the step.
747 int taintCount = m_taintsToProcessPerStep;
748 TaintCallbackEntry oneCallback = new TaintCallbackEntry();
749 while (_taintOperations.Count > 0 && taintCount-- > 0)
750 {
751 bool gotOne = false;
752 lock (_taintLock)
753 {
754 if (_taintOperations.Count > 0)
755 {
756 oneCallback = _taintOperations[0];
757 _taintOperations.RemoveAt(0);
758 gotOne = true;
759 }
760 }
761 if (gotOne)
762 {
763 try
764 {
765 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident);
766 oneCallback.callback();
767 }
768 catch (Exception e)
769 {
770 DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
771 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
772 }
773 }
774 }
775 if (_taintOperations.Count > 0)
776 {
777 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count);
778 }
779 */
780
781 // swizzle a new list into the list location so we can process what's there 747 // swizzle a new list into the list location so we can process what's there
782 List<TaintCallbackEntry> oldList; 748 List<TaintCallbackEntry> oldList;
783 lock (_taintLock) 749 lock (_taintLock)
@@ -816,6 +782,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
816 return; 782 return;
817 } 783 }
818 784
785 // Taints that happen after the normal taint processing but before the simulation step.
819 private void ProcessPostTaintTaints() 786 private void ProcessPostTaintTaints()
820 { 787 {
821 if (_postTaintOperations.Count > 0) 788 if (_postTaintOperations.Count > 0)
@@ -843,45 +810,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
843 } 810 }
844 } 811 }
845 812
846 public void PostStepTaintObject(String ident, TaintCallback callback)
847 {
848 if (!m_initialized) return;
849
850 lock (_taintLock)
851 {
852 _postStepOperations.Add(new TaintCallbackEntry(ident, callback));
853 }
854
855 return;
856 }
857
858 private void ProcessPostStepTaints()
859 {
860 if (_postStepOperations.Count > 0)
861 {
862 List<TaintCallbackEntry> oldList;
863 lock (_taintLock)
864 {
865 oldList = _postStepOperations;
866 _postStepOperations = new List<TaintCallbackEntry>();
867 }
868
869 foreach (TaintCallbackEntry tcbe in oldList)
870 {
871 try
872 {
873 DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
874 tcbe.callback();
875 }
876 catch (Exception e)
877 {
878 m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
879 }
880 }
881 oldList.Clear();
882 }
883 }
884
885 // Only used for debugging. Does not change state of anything so locking is not necessary. 813 // Only used for debugging. Does not change state of anything so locking is not necessary.
886 public bool AssertInTaintTime(string whereFrom) 814 public bool AssertInTaintTime(string whereFrom)
887 { 815 {
@@ -889,540 +817,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
889 { 817 {
890 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); 818 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
891 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); 819 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
892 Util.PrintCallStack(); // Prints the stack into the DEBUG log file. 820 Util.PrintCallStack(DetailLog);
893 } 821 }
894 return InTaintTime; 822 return InTaintTime;
895 } 823 }
896 824
897 #endregion // Taints 825 #endregion // Taints
898 826
899 #region Vehicles
900
901 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
902 {
903 RemoveVehiclePrim(vehic);
904 if (newType != Vehicle.TYPE_NONE)
905 {
906 // make it so the scene will call us each tick to do vehicle things
907 AddVehiclePrim(vehic);
908 }
909 }
910
911 // Make so the scene will call this prim for vehicle actions each tick.
912 // Safe to call if prim is already in the vehicle list.
913 public void AddVehiclePrim(BSPrim vehicle)
914 {
915 lock (m_vehicles)
916 {
917 if (!m_vehicles.Contains(vehicle))
918 {
919 m_vehicles.Add(vehicle);
920 }
921 }
922 }
923
924 // Remove a prim from our list of vehicles.
925 // Safe to call if the prim is not in the vehicle list.
926 public void RemoveVehiclePrim(BSPrim vehicle)
927 {
928 lock (m_vehicles)
929 {
930 if (m_vehicles.Contains(vehicle))
931 {
932 m_vehicles.Remove(vehicle);
933 }
934 }
935 }
936
937 private void DoPreStepActions(float timeStep)
938 {
939 ProcessVehicles(timeStep);
940
941 PreStepAction actions = BeforeStep;
942 if (actions != null)
943 actions(timeStep);
944
945 }
946
947 // Some prims have extra vehicle actions
948 // Called at taint time!
949 private void ProcessVehicles(float timeStep)
950 {
951 foreach (BSPhysObject pobj in m_vehicles)
952 {
953 pobj.StepVehicle(timeStep);
954 }
955 }
956 #endregion Vehicles
957
958 #region INI and command line parameter processing 827 #region INI and command line parameter processing
959 828
960 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
961 delegate float ParamGet(BSScene scene);
962 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
963 delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
964
965 private struct ParameterDefn
966 {
967 public string name; // string name of the parameter
968 public string desc; // a short description of what the parameter means
969 public float defaultValue; // default value if not specified anywhere else
970 public ParamUser userParam; // get the value from the configuration file
971 public ParamGet getter; // return the current value stored for this parameter
972 public ParamSet setter; // set the current value for this parameter
973 public SetOnObject onObject; // set the value on an object in the physical domain
974 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
975 {
976 name = n;
977 desc = d;
978 defaultValue = v;
979 userParam = u;
980 getter = g;
981 setter = s;
982 onObject = null;
983 }
984 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
985 {
986 name = n;
987 desc = d;
988 defaultValue = v;
989 userParam = u;
990 getter = g;
991 setter = s;
992 onObject = o;
993 }
994 }
995
996 // List of all of the externally visible parameters.
997 // For each parameter, this table maps a text name to getter and setters.
998 // To add a new externally referencable/settable parameter, add the paramter storage
999 // location somewhere in the program and make an entry in this table with the
1000 // getters and setters.
1001 // It is easiest to find an existing definition and copy it.
1002 // Parameter values are floats. Booleans are converted to a floating value.
1003 //
1004 // A ParameterDefn() takes the following parameters:
1005 // -- the text name of the parameter. This is used for console input and ini file.
1006 // -- a short text description of the parameter. This shows up in the console listing.
1007 // -- a delegate for fetching the parameter from the ini file.
1008 // Should handle fetching the right type from the ini file and converting it.
1009 // -- a delegate for getting the value as a float
1010 // -- a delegate for setting the value from a float
1011 // -- an optional delegate to update the value in the world. Most often used to
1012 // push the new value to an in-world object.
1013 //
1014 // The single letter parameters for the delegates are:
1015 // s = BSScene
1016 // o = BSPhysObject
1017 // p = string parameter name
1018 // l = localID of referenced object
1019 // v = float value
1020 // cf = parameter configuration class (for fetching values from ini file)
1021 private ParameterDefn[] ParameterDefinitions =
1022 {
1023 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
1024 ConfigurationParameters.numericTrue,
1025 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
1026 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
1027 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
1028 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
1029 ConfigurationParameters.numericFalse,
1030 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
1031 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
1032 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
1033 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
1034 ConfigurationParameters.numericTrue,
1035 (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
1036 (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
1037 (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
1038
1039 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
1040 8f,
1041 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
1042 (s) => { return s.MeshLOD; },
1043 (s,p,l,v) => { s.MeshLOD = v; } ),
1044 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
1045 16f,
1046 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
1047 (s) => { return s.MeshMegaPrimLOD; },
1048 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
1049 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
1050 10f,
1051 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
1052 (s) => { return s.MeshMegaPrimThreshold; },
1053 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
1054 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
1055 32f,
1056 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
1057 (s) => { return s.SculptLOD; },
1058 (s,p,l,v) => { s.SculptLOD = v; } ),
1059
1060 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
1061 10f,
1062 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
1063 (s) => { return (float)s.m_maxSubSteps; },
1064 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
1065 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
1066 1f / 60f,
1067 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
1068 (s) => { return (float)s.m_fixedTimeStep; },
1069 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
1070 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
1071 2048f,
1072 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
1073 (s) => { return (float)s.m_maxCollisionsPerFrame; },
1074 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
1075 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
1076 8000f,
1077 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
1078 (s) => { return (float)s.m_maxUpdatesPerFrame; },
1079 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
1080 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
1081 500f,
1082 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
1083 (s) => { return (float)s.m_taintsToProcessPerStep; },
1084 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
1085 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
1086 10000.01f,
1087 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
1088 (s) => { return (float)s.MaximumObjectMass; },
1089 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
1090
1091 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
1092 2200f,
1093 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
1094 (s) => { return (float)s.PID_D; },
1095 (s,p,l,v) => { s.PID_D = v; } ),
1096 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
1097 900f,
1098 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
1099 (s) => { return (float)s.PID_P; },
1100 (s,p,l,v) => { s.PID_P = v; } ),
1101
1102 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
1103 0.2f,
1104 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
1105 (s) => { return s.m_params[0].defaultFriction; },
1106 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
1107 new ParameterDefn("DefaultDensity", "Density for new objects" ,
1108 10.000006836f, // Aluminum g/cm3
1109 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
1110 (s) => { return s.m_params[0].defaultDensity; },
1111 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
1112 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
1113 0f,
1114 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
1115 (s) => { return s.m_params[0].defaultRestitution; },
1116 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
1117 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
1118 0.04f,
1119 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
1120 (s) => { return s.m_params[0].collisionMargin; },
1121 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
1122 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
1123 -9.80665f,
1124 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
1125 (s) => { return s.m_params[0].gravity; },
1126 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); },
1127 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
1128
1129
1130 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
1131 0f,
1132 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
1133 (s) => { return s.m_params[0].linearDamping; },
1134 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
1135 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ),
1136 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
1137 0f,
1138 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
1139 (s) => { return s.m_params[0].angularDamping; },
1140 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
1141 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, v); } ),
1142 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
1143 0.2f,
1144 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
1145 (s) => { return s.m_params[0].deactivationTime; },
1146 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); },
1147 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
1148 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
1149 0.8f,
1150 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
1151 (s) => { return s.m_params[0].linearSleepingThreshold; },
1152 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); },
1153 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1154 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
1155 1.0f,
1156 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
1157 (s) => { return s.m_params[0].angularSleepingThreshold; },
1158 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); },
1159 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1160 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1161 0f, // set to zero to disable
1162 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1163 (s) => { return s.m_params[0].ccdMotionThreshold; },
1164 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); },
1165 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
1166 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1167 0f,
1168 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1169 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1170 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); },
1171 (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
1172 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1173 0.1f,
1174 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1175 (s) => { return s.m_params[0].contactProcessingThreshold; },
1176 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1177 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1178
1179 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
1180 (float)BSTerrainPhys.TerrainImplementation.Mesh,
1181 (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); },
1182 (s) => { return s.m_params[0].terrainImplementation; },
1183 (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ),
1184 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1185 0.3f,
1186 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1187 (s) => { return s.m_params[0].terrainFriction; },
1188 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
1189 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
1190 0.8f,
1191 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
1192 (s) => { return s.m_params[0].terrainHitFraction; },
1193 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ),
1194 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
1195 0f,
1196 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1197 (s) => { return s.m_params[0].terrainRestitution; },
1198 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1199 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
1200 0.04f,
1201 (s,cf,p,v) => { s.m_params[0].terrainCollisionMargin = cf.GetFloat(p, v); },
1202 (s) => { return s.m_params[0].terrainCollisionMargin; },
1203 (s,p,l,v) => { s.m_params[0].terrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
1204
1205 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1206 0.2f,
1207 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1208 (s) => { return s.m_params[0].avatarFriction; },
1209 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1210 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1211 10.0f,
1212 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1213 (s) => { return s.m_params[0].avatarStandingFriction; },
1214 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
1215 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1216 60f,
1217 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1218 (s) => { return s.m_params[0].avatarDensity; },
1219 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1220 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1221 0f,
1222 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1223 (s) => { return s.m_params[0].avatarRestitution; },
1224 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1225 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
1226 0.6f,
1227 (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); },
1228 (s) => { return s.m_params[0].avatarCapsuleWidth; },
1229 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ),
1230 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
1231 0.45f,
1232 (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); },
1233 (s) => { return s.m_params[0].avatarCapsuleDepth; },
1234 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ),
1235 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1236 1.5f,
1237 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1238 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1239 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1240 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1241 0.1f,
1242 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1243 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1244 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1245
1246 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
1247 0.95f,
1248 (s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); },
1249 (s) => { return s.m_params[0].vehicleAngularDamping; },
1250 (s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ),
1251
1252 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1253 0f,
1254 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1255 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1256 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1257 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1258 0f,
1259 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1260 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1261 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
1262 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1263 ConfigurationParameters.numericFalse,
1264 (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1265 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1266 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1267 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1268 ConfigurationParameters.numericFalse,
1269 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1270 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1271 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1272 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1273 ConfigurationParameters.numericTrue,
1274 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1275 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1276 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1277 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1278 ConfigurationParameters.numericTrue,
1279 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1280 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1281 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1282 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1283 ConfigurationParameters.numericFalse,
1284 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1285 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1286 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1287 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1288 0f, // zero says use Bullet default
1289 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1290 (s) => { return s.m_params[0].numberOfSolverIterations; },
1291 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1292
1293 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
1294 (float)BSLinkset.LinksetImplementation.Compound,
1295 (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); },
1296 (s) => { return s.m_params[0].linksetImplementation; },
1297 (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ),
1298 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1299 ConfigurationParameters.numericFalse,
1300 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1301 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1302 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1303 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1304 ConfigurationParameters.numericTrue,
1305 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1306 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1307 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1308 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1309 5.0f,
1310 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1311 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1312 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1313 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1314 0.1f,
1315 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1316 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1317 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1318 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1319 0.1f,
1320 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1321 (s) => { return s.m_params[0].linkConstraintCFM; },
1322 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1323 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1324 0.1f,
1325 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1326 (s) => { return s.m_params[0].linkConstraintERP; },
1327 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1328 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1329 40,
1330 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1331 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1332 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1333
1334 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
1335 0f,
1336 (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
1337 (s) => { return (float)s.m_params[0].physicsLoggingFrames; },
1338 (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ),
1339 };
1340
1341 // Convert a boolean to our numeric true and false values
1342 public float NumericBool(bool b)
1343 {
1344 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1345 }
1346
1347 // Convert numeric true and false values to a boolean
1348 public bool BoolNumeric(float b)
1349 {
1350 return (b == ConfigurationParameters.numericTrue ? true : false);
1351 }
1352
1353 // Search through the parameter definitions and return the matching
1354 // ParameterDefn structure.
1355 // Case does not matter as names are compared after converting to lower case.
1356 // Returns 'false' if the parameter is not found.
1357 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1358 {
1359 bool ret = false;
1360 ParameterDefn foundDefn = new ParameterDefn();
1361 string pName = paramName.ToLower();
1362
1363 foreach (ParameterDefn parm in ParameterDefinitions)
1364 {
1365 if (pName == parm.name.ToLower())
1366 {
1367 foundDefn = parm;
1368 ret = true;
1369 break;
1370 }
1371 }
1372 defn = foundDefn;
1373 return ret;
1374 }
1375
1376 // Pass through the settable parameters and set the default values
1377 private void SetParameterDefaultValues()
1378 {
1379 foreach (ParameterDefn parm in ParameterDefinitions)
1380 {
1381 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1382 }
1383 }
1384
1385 // Get user set values out of the ini file.
1386 private void SetParameterConfigurationValues(IConfig cfg)
1387 {
1388 foreach (ParameterDefn parm in ParameterDefinitions)
1389 {
1390 parm.userParam(this, cfg, parm.name, parm.defaultValue);
1391 }
1392 }
1393
1394 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1395
1396 // This creates an array in the correct format for returning the list of
1397 // parameters. This is used by the 'list' option of the 'physics' command.
1398 private void BuildParameterTable()
1399 {
1400 if (SettableParameters.Length < ParameterDefinitions.Length)
1401 {
1402 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1403 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1404 {
1405 ParameterDefn pd = ParameterDefinitions[ii];
1406 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
1407 }
1408
1409 // make the list in alphabetical order for estetic reasons
1410 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1411 {
1412 return ppe1.name.CompareTo(ppe2.name);
1413 });
1414
1415 SettableParameters = entries.ToArray();
1416 }
1417 }
1418
1419
1420 #region IPhysicsParameters 829 #region IPhysicsParameters
1421 // Get the list of parameters this physics engine supports 830 // Get the list of parameters this physics engine supports
1422 public PhysParameterEntry[] GetParameterList() 831 public PhysParameterEntry[] GetParameterList()
1423 { 832 {
1424 BuildParameterTable(); 833 BSParam.BuildParameterTable();
1425 return SettableParameters; 834 return BSParam.SettableParameters;
1426 } 835 }
1427 836
1428 // Set parameter on a specific or all instances. 837 // Set parameter on a specific or all instances.
@@ -1434,8 +843,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1434 public bool SetPhysicsParameter(string parm, float val, uint localID) 843 public bool SetPhysicsParameter(string parm, float val, uint localID)
1435 { 844 {
1436 bool ret = false; 845 bool ret = false;
1437 ParameterDefn theParam; 846 BSParam.ParameterDefn theParam;
1438 if (TryGetParameter(parm, out theParam)) 847 if (BSParam.TryGetParameter(parm, out theParam))
1439 { 848 {
1440 theParam.setter(this, parm, localID, val); 849 theParam.setter(this, parm, localID, val);
1441 ret = true; 850 ret = true;
@@ -1447,19 +856,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1447 // If the local ID is APPLY_TO_NONE, just change the default value 856 // If the local ID is APPLY_TO_NONE, just change the default value
1448 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 857 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
1449 // If the localID is a specific object, apply the parameter change to only that object 858 // If the localID is a specific object, apply the parameter change to only that object
1450 private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) 859 internal delegate void AssignVal(float x);
860 internal void UpdateParameterObject(AssignVal setDefault, string parm, uint localID, float val)
1451 { 861 {
1452 List<uint> objectIDs = new List<uint>(); 862 List<uint> objectIDs = new List<uint>();
1453 switch (localID) 863 switch (localID)
1454 { 864 {
1455 case PhysParameterEntry.APPLY_TO_NONE: 865 case PhysParameterEntry.APPLY_TO_NONE:
1456 defaultLoc = val; // setting only the default value 866 setDefault(val); // setting only the default value
1457 // This will cause a call into the physical world if some operation is specified (SetOnObject). 867 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1458 objectIDs.Add(TERRAIN_ID); 868 objectIDs.Add(TERRAIN_ID);
1459 TaintedUpdateParameter(parm, objectIDs, val); 869 TaintedUpdateParameter(parm, objectIDs, val);
1460 break; 870 break;
1461 case PhysParameterEntry.APPLY_TO_ALL: 871 case PhysParameterEntry.APPLY_TO_ALL:
1462 defaultLoc = val; // setting ALL also sets the default value 872 setDefault(val); // setting ALL also sets the default value
1463 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); 873 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
1464 TaintedUpdateParameter(parm, objectIDs, val); 874 TaintedUpdateParameter(parm, objectIDs, val);
1465 break; 875 break;
@@ -1478,8 +888,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1478 List<uint> xlIDs = lIDs; 888 List<uint> xlIDs = lIDs;
1479 string xparm = parm; 889 string xparm = parm;
1480 TaintedObject("BSScene.UpdateParameterSet", delegate() { 890 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1481 ParameterDefn thisParam; 891 BSParam.ParameterDefn thisParam;
1482 if (TryGetParameter(xparm, out thisParam)) 892 if (BSParam.TryGetParameter(xparm, out thisParam))
1483 { 893 {
1484 if (thisParam.onObject != null) 894 if (thisParam.onObject != null)
1485 { 895 {
@@ -1500,8 +910,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1500 { 910 {
1501 float val = 0f; 911 float val = 0f;
1502 bool ret = false; 912 bool ret = false;
1503 ParameterDefn theParam; 913 BSParam.ParameterDefn theParam;
1504 if (TryGetParameter(parm, out theParam)) 914 if (BSParam.TryGetParameter(parm, out theParam))
1505 { 915 {
1506 val = theParam.getter(this); 916 val = theParam.getter(this);
1507 ret = true; 917 ret = true;
@@ -1514,16 +924,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1514 924
1515 #endregion Runtime settable parameters 925 #endregion Runtime settable parameters
1516 926
1517 // Debugging routine for dumping detailed physical information for vehicle prims
1518 private void DumpVehicles()
1519 {
1520 foreach (BSPrim prim in m_vehicles)
1521 {
1522 BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr);
1523 BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr);
1524 }
1525 }
1526
1527 // Invoke the detailed logger and output something if it's enabled. 927 // Invoke the detailed logger and output something if it's enabled.
1528 public void DetailLog(string msg, params Object[] args) 928 public void DetailLog(string msg, params Object[] args)
1529 { 929 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index d6e2fe9..855be0b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -456,7 +456,7 @@ public sealed class BSShapeCollection : IDisposable
456 if (!haveShape 456 if (!haveShape
457 && pbs != null 457 && pbs != null
458 && nativeShapePossible 458 && nativeShapePossible
459 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) 459 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim)
460 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 460 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
461 && pbs.ProfileHollow == 0 461 && pbs.ProfileHollow == 0
462 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 462 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
@@ -520,7 +520,7 @@ public sealed class BSShapeCollection : IDisposable
520 bool ret = false; 520 bool ret = false;
521 // Note that if it's a native shape, the check for physical/non-physical is not 521 // Note that if it's a native shape, the check for physical/non-physical is not
522 // made. Native shapes work in either case. 522 // made. Native shapes work in either case.
523 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) 523 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
524 { 524 {
525 // Update prim.BSShape to reference a hull of this shape. 525 // Update prim.BSShape to reference a hull of this shape.
526 ret = GetReferenceToHull(prim,shapeCallback); 526 ret = GetReferenceToHull(prim,shapeCallback);
@@ -836,14 +836,14 @@ public sealed class BSShapeCollection : IDisposable
836 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) 836 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
837 { 837 {
838 // level of detail based on size and type of the object 838 // level of detail based on size and type of the object
839 float lod = PhysicsScene.MeshLOD; 839 float lod = BSParam.MeshLOD;
840 if (pbs.SculptEntry) 840 if (pbs.SculptEntry)
841 lod = PhysicsScene.SculptLOD; 841 lod = BSParam.SculptLOD;
842 842
843 // Mega prims usually get more detail because one can interact with shape approximations at this size. 843 // Mega prims usually get more detail because one can interact with shape approximations at this size.
844 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); 844 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
845 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) 845 if (maxAxis > BSParam.MeshMegaPrimThreshold)
846 lod = PhysicsScene.MeshMegaPrimLOD; 846 lod = BSParam.MeshMegaPrimLOD;
847 847
848 retLod = lod; 848 retLod = lod;
849 return pbs.GetMeshKey(size, lod); 849 return pbs.GetMeshKey(size, lod);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index 2b120d6..07a9fd8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -93,7 +93,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
93 { 93 {
94 m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, 94 m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID,
95 m_mapInfo.minCoords, m_mapInfo.maxCoords, 95 m_mapInfo.minCoords, m_mapInfo.maxCoords,
96 m_mapInfo.heightMap, PhysicsScene.Params.terrainCollisionMargin); 96 m_mapInfo.heightMap, BSParam.TerrainCollisionMargin);
97 97
98 // Create the terrain shape from the mapInfo 98 // Create the terrain shape from the mapInfo
99 m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), 99 m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr),
@@ -110,9 +110,9 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
110 m_mapInfo.ID, centerPos, Quaternion.Identity)); 110 m_mapInfo.ID, centerPos, Quaternion.Identity));
111 111
112 // Set current terrain attributes 112 // Set current terrain attributes
113 BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); 113 BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, BSParam.TerrainFriction);
114 BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); 114 BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, BSParam.TerrainHitFraction);
115 BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); 115 BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, BSParam.TerrainRestitution);
116 BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 116 BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
117 117
118 // Return the new terrain to the world of physical objects 118 // Return the new terrain to the world of physical objects
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 3428b9c..86ccfbb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -135,7 +135,7 @@ public sealed class BSTerrainManager : IDisposable
135 // The ground plane is here to catch things that are trying to drop to negative infinity 135 // The ground plane is here to catch things that are trying to drop to negative infinity
136 BulletShape groundPlaneShape = new BulletShape( 136 BulletShape groundPlaneShape = new BulletShape(
137 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, 137 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f,
138 PhysicsScene.Params.terrainCollisionMargin), 138 BSParam.TerrainCollisionMargin),
139 BSPhysicsShapeType.SHAPE_GROUNDPLANE); 139 BSPhysicsShapeType.SHAPE_GROUNDPLANE);
140 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, 140 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
141 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, 141 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
@@ -309,9 +309,9 @@ public sealed class BSTerrainManager : IDisposable
309 { 309 {
310 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", 310 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
311 LogHeader, PhysicsScene.RegionName, terrainRegionBase, 311 LogHeader, PhysicsScene.RegionName, terrainRegionBase,
312 (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation); 312 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
313 BSTerrainPhys newTerrainPhys = null; 313 BSTerrainPhys newTerrainPhys = null;
314 switch ((int)PhysicsScene.Params.terrainImplementation) 314 switch ((int)BSParam.TerrainImplementation)
315 { 315 {
316 case (int)BSTerrainPhys.TerrainImplementation.Heightmap: 316 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
317 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, 317 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id,
@@ -324,8 +324,8 @@ public sealed class BSTerrainManager : IDisposable
324 default: 324 default:
325 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", 325 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
326 LogHeader, 326 LogHeader,
327 (int)PhysicsScene.Params.terrainImplementation, 327 (int)BSParam.TerrainImplementation,
328 PhysicsScene.Params.terrainImplementation, 328 BSParam.TerrainImplementation,
329 PhysicsScene.RegionName, terrainRegionBase); 329 PhysicsScene.RegionName, terrainRegionBase);
330 break; 330 break;
331 } 331 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 6dc0d92..061e232 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -116,9 +116,9 @@ public sealed class BSTerrainMesh : BSTerrainPhys
116 } 116 }
117 117
118 // Set current terrain attributes 118 // Set current terrain attributes
119 BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); 119 BulletSimAPI.SetFriction2(m_terrainBody.ptr, BSParam.TerrainFriction);
120 BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); 120 BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, BSParam.TerrainHitFraction);
121 BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); 121 BulletSimAPI.SetRestitution2(m_terrainBody.ptr, BSParam.TerrainRestitution);
122 BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 122 BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
123 123
124 // Static objects are not very massive. 124 // Static objects are not very massive.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 962b540..7857eaa 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -141,6 +141,8 @@ public struct EntityProperties
141} 141}
142 142
143// Format of this structure must match the definition in the C++ code 143// Format of this structure must match the definition in the C++ code
144// NOTE: adding the X causes compile breaks if used. These are unused symbols
145// that can be removed from both here and the unmanaged definition of this structure.
144[StructLayout(LayoutKind.Sequential)] 146[StructLayout(LayoutKind.Sequential)]
145public struct ConfigurationParameters 147public struct ConfigurationParameters
146{ 148{
@@ -150,31 +152,31 @@ public struct ConfigurationParameters
150 public float collisionMargin; 152 public float collisionMargin;
151 public float gravity; 153 public float gravity;
152 154
153 public float linearDamping; 155 public float XlinearDamping;
154 public float angularDamping; 156 public float XangularDamping;
155 public float deactivationTime; 157 public float XdeactivationTime;
156 public float linearSleepingThreshold; 158 public float XlinearSleepingThreshold;
157 public float angularSleepingThreshold; 159 public float XangularSleepingThreshold;
158 public float ccdMotionThreshold; 160 public float XccdMotionThreshold;
159 public float ccdSweptSphereRadius; 161 public float XccdSweptSphereRadius;
160 public float contactProcessingThreshold; 162 public float XcontactProcessingThreshold;
161 163
162 public float terrainImplementation; 164 public float XterrainImplementation;
163 public float terrainFriction; 165 public float XterrainFriction;
164 public float terrainHitFraction; 166 public float XterrainHitFraction;
165 public float terrainRestitution; 167 public float XterrainRestitution;
166 public float terrainCollisionMargin; 168 public float XterrainCollisionMargin;
167 169
168 public float avatarFriction; 170 public float XavatarFriction;
169 public float avatarStandingFriction; 171 public float XavatarStandingFriction;
170 public float avatarDensity; 172 public float XavatarDensity;
171 public float avatarRestitution; 173 public float XavatarRestitution;
172 public float avatarCapsuleWidth; 174 public float XavatarCapsuleWidth;
173 public float avatarCapsuleDepth; 175 public float XavatarCapsuleDepth;
174 public float avatarCapsuleHeight; 176 public float XavatarCapsuleHeight;
175 public float avatarContactProcessingThreshold; 177 public float XavatarContactProcessingThreshold;
176 178
177 public float vehicleAngularDamping; 179 public float XvehicleAngularDamping;
178 180
179 public float maxPersistantManifoldPoolSize; 181 public float maxPersistantManifoldPoolSize;
180 public float maxCollisionAlgorithmPoolSize; 182 public float maxCollisionAlgorithmPoolSize;
@@ -185,14 +187,14 @@ public struct ConfigurationParameters
185 public float shouldEnableFrictionCaching; 187 public float shouldEnableFrictionCaching;
186 public float numberOfSolverIterations; 188 public float numberOfSolverIterations;
187 189
188 public float linksetImplementation; 190 public float XlinksetImplementation;
189 public float linkConstraintUseFrameOffset; 191 public float XlinkConstraintUseFrameOffset;
190 public float linkConstraintEnableTransMotor; 192 public float XlinkConstraintEnableTransMotor;
191 public float linkConstraintTransMotorMaxVel; 193 public float XlinkConstraintTransMotorMaxVel;
192 public float linkConstraintTransMotorMaxForce; 194 public float XlinkConstraintTransMotorMaxForce;
193 public float linkConstraintERP; 195 public float XlinkConstraintERP;
194 public float linkConstraintCFM; 196 public float XlinkConstraintCFM;
195 public float linkConstraintSolverIterations; 197 public float XlinkConstraintSolverIterations;
196 198
197 public float physicsLoggingFrames; 199 public float physicsLoggingFrames;
198 200
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index c084ab4..9a7e965 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -112,6 +112,9 @@ Test avatar walking up stairs. How does compare with SL.
112Debounce avatar contact so legs don't keep folding up when standing. 112Debounce avatar contact so legs don't keep folding up when standing.
113Implement LSL physics controls. Like STATUS_ROTATE_X. 113Implement LSL physics controls. Like STATUS_ROTATE_X.
114Add border extensions to terrain to help region crossings and objects leaving region. 114Add border extensions to terrain to help region crossings and objects leaving region.
115Use a different capsule shape for avatar when sitting
116 LL uses a pyrimidal shape scaled by the avatar's bounding box
117 http://wiki.secondlife.com/wiki/File:Avmeshforms.png
115 118
116Performance test with lots of avatars. Can BulletSim support a thousand? 119Performance test with lots of avatars. Can BulletSim support a thousand?
117Optimize collisions in C++: only send up to the object subscribed to collisions. 120Optimize collisions in C++: only send up to the object subscribed to collisions.