diff options
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 | */ | ||
27 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | |||
31 | using OpenSim.Region.Physics.Manager; | ||
32 | |||
33 | using OpenMetaverse; | ||
34 | using Nini.Config; | ||
35 | |||
36 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
37 | { | ||
38 | public 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 | |||
48 | public abstract class BSPhysObject : PhysicsActor | 58 | public 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)] |
145 | public struct ConfigurationParameters | 147 | public 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. | |||
112 | Debounce avatar contact so legs don't keep folding up when standing. | 112 | Debounce avatar contact so legs don't keep folding up when standing. |
113 | Implement LSL physics controls. Like STATUS_ROTATE_X. | 113 | Implement LSL physics controls. Like STATUS_ROTATE_X. |
114 | Add border extensions to terrain to help region crossings and objects leaving region. | 114 | Add border extensions to terrain to help region crossings and objects leaving region. |
115 | Use 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 | ||
116 | Performance test with lots of avatars. Can BulletSim support a thousand? | 119 | Performance test with lots of avatars. Can BulletSim support a thousand? |
117 | Optimize collisions in C++: only send up to the object subscribed to collisions. | 120 | Optimize collisions in C++: only send up to the object subscribed to collisions. |