aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie2012-12-21 22:13:41 +0000
committerMelanie2012-12-21 22:13:41 +0000
commit569f39e1242044a46693926c31d86fff6b4b228c (patch)
tree69fb5c2b0ce512336680b48bbf89bb42bb8f5b88
parentMerge branch 'avination' into careminster (diff)
parentBulletSim: small fix to avatar movement motor use which keeps avatar from fly... (diff)
downloadopensim-SC-569f39e1242044a46693926c31d86fff6b4b228c.zip
opensim-SC-569f39e1242044a46693926c31d86fff6b4b228c.tar.gz
opensim-SC-569f39e1242044a46693926c31d86fff6b4b228c.tar.bz2
opensim-SC-569f39e1242044a46693926c31d86fff6b4b228c.tar.xz
Merge branch 'master' into careminster
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs12
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs78
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs145
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs193
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs17
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs10
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt46
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs7
10 files changed, 396 insertions, 134 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 2aeb4cc..7035e38 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -204,9 +204,12 @@ namespace OpenMetaverse
204 { 204 {
205 UDPPacketBuffer buf; 205 UDPPacketBuffer buf;
206 206
207 if (UsePools) 207 // FIXME: Disabled for now as this causes issues with reused packet objects interfering with each other
208 buf = Pool.GetObject(); 208 // on Windows with m_asyncPacketHandling = true, though this has not been seen on Linux.
209 else 209 // Possibly some unexpected issue with fetching UDP data concurrently with multiple threads. Requires more investigation.
210// if (UsePools)
211// buf = Pool.GetObject();
212// else
210 buf = new UDPPacketBuffer(); 213 buf = new UDPPacketBuffer();
211 214
212 if (IsRunningInbound) 215 if (IsRunningInbound)
@@ -287,8 +290,8 @@ namespace OpenMetaverse
287 catch (ObjectDisposedException) { } 290 catch (ObjectDisposedException) { }
288 finally 291 finally
289 { 292 {
290 if (UsePools) 293// if (UsePools)
291 Pool.ReturnObject(buffer); 294// Pool.ReturnObject(buffer);
292 295
293 // Synchronous mode waits until the packet callback completes 296 // Synchronous mode waits until the packet callback completes
294 // before starting the receive to fetch another packet 297 // before starting the receive to fetch another packet
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 2051a53..1fc8d3d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -101,6 +101,15 @@ namespace OpenSim.Region.Framework.Scenes
101 /// </summary> 101 /// </summary>
102 public partial class SceneObjectGroup : EntityBase, ISceneObject 102 public partial class SceneObjectGroup : EntityBase, ISceneObject
103 { 103 {
104 // Axis selection bitmask used by SetAxisRotation()
105 // Just happen to be the same bits used by llSetStatus() and defined in ScriptBaseClass.
106 public enum axisSelect : int
107 {
108 STATUS_ROTATE_X = 0x002,
109 STATUS_ROTATE_Y = 0x004,
110 STATUS_ROTATE_Z = 0x008,
111 }
112
104 // private PrimCountTaintedDelegate handlerPrimCountTainted = null; 113 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
105 114
106 /// <summary> 115 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index c746690..143a339 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2431,11 +2431,11 @@ namespace OpenSim.Region.Framework.Scenes
2431 public int GetAxisRotation(int axis) 2431 public int GetAxisRotation(int axis)
2432 { 2432 {
2433 //Cannot use ScriptBaseClass constants as no referance to it currently. 2433 //Cannot use ScriptBaseClass constants as no referance to it currently.
2434 if (axis == 2)//STATUS_ROTATE_X 2434 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X)
2435 return STATUS_ROTATE_X; 2435 return STATUS_ROTATE_X;
2436 if (axis == 4)//STATUS_ROTATE_Y 2436 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
2437 return STATUS_ROTATE_Y; 2437 return STATUS_ROTATE_Y;
2438 if (axis == 8)//STATUS_ROTATE_Z 2438 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
2439 return STATUS_ROTATE_Z; 2439 return STATUS_ROTATE_Z;
2440 2440
2441 return 0; 2441 return 0;
@@ -3316,13 +3316,13 @@ namespace OpenSim.Region.Framework.Scenes
3316 ParentGroup.SetAxisRotation(axis, rotate); 3316 ParentGroup.SetAxisRotation(axis, rotate);
3317 3317
3318 //Cannot use ScriptBaseClass constants as no referance to it currently. 3318 //Cannot use ScriptBaseClass constants as no referance to it currently.
3319 if (axis == 2)//STATUS_ROTATE_X 3319 if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
3320 STATUS_ROTATE_X = rotate; 3320 STATUS_ROTATE_X = rotate;
3321 3321
3322 if (axis == 4)//STATUS_ROTATE_Y 3322 if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
3323 STATUS_ROTATE_Y = rotate; 3323 STATUS_ROTATE_Y = rotate;
3324 3324
3325 if (axis == 8)//STATUS_ROTATE_Z 3325 if ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
3326 STATUS_ROTATE_Z = rotate; 3326 STATUS_ROTATE_Z = rotate;
3327 } 3327 }
3328 3328
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 4dd6264..57c5898 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -69,6 +69,8 @@ public sealed class BSCharacter : BSPhysObject
69 private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar 69 private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar
70 private float _currentFriction; // the friction currently being used (changed by setVelocity). 70 private float _currentFriction; // the friction currently being used (changed by setVelocity).
71 71
72 private BSVMotor _velocityMotor;
73
72 private OMV.Vector3 _PIDTarget; 74 private OMV.Vector3 _PIDTarget;
73 private bool _usePID; 75 private bool _usePID;
74 private float _PIDTau; 76 private float _PIDTau;
@@ -89,6 +91,18 @@ public sealed class BSCharacter : BSPhysObject
89 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; 91 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth;
90 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; 92 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth;
91 93
94 // A motor to control the acceleration and deceleration of the avatar movement.
95 // _velocityMotor = new BSVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
96 // _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
97 // Infinite decay and timescale values so motor only changes current to target values.
98 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
99 0.2f, // time scale
100 BSMotor.Infinite, // decay time scale
101 BSMotor.InfiniteVector, // friction timescale
102 1f // efficiency
103 );
104 _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
105
92 _flying = isFlying; 106 _flying = isFlying;
93 _orientation = OMV.Quaternion.Identity; 107 _orientation = OMV.Quaternion.Identity;
94 _velocity = OMV.Vector3.Zero; 108 _velocity = OMV.Vector3.Zero;
@@ -138,6 +152,10 @@ public sealed class BSCharacter : BSPhysObject
138 ForcePosition = _position; 152 ForcePosition = _position;
139 // Set the velocity and compute the proper friction 153 // Set the velocity and compute the proper friction
140 ForceVelocity = _velocity; 154 ForceVelocity = _velocity;
155 // Setting the current and target in the motor will cause it to start computing any deceleration.
156 _velocityMotor.Reset();
157 _velocityMotor.SetCurrent(_velocity);
158 _velocityMotor.SetTarget(_velocity);
141 159
142 // This will enable or disable the flying buoyancy of the avatar. 160 // This will enable or disable the flying buoyancy of the avatar.
143 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 161 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
@@ -239,6 +257,7 @@ public sealed class BSCharacter : BSPhysObject
239 public override void ZeroMotion(bool inTaintTime) 257 public override void ZeroMotion(bool inTaintTime)
240 { 258 {
241 _velocity = OMV.Vector3.Zero; 259 _velocity = OMV.Vector3.Zero;
260 _velocityMotor.Zero();
242 _acceleration = OMV.Vector3.Zero; 261 _acceleration = OMV.Vector3.Zero;
243 _rotationalVelocity = OMV.Vector3.Zero; 262 _rotationalVelocity = OMV.Vector3.Zero;
244 263
@@ -400,10 +419,38 @@ public sealed class BSCharacter : BSPhysObject
400 419
401 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } 420 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
402 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } 421 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
422
423 // Sets the target in the motor. This starts the changing of the avatar's velocity.
424 public override OMV.Vector3 TargetVelocity
425 {
426 get
427 {
428 return _velocityMotor.TargetValue;
429 }
430 set
431 {
432 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
433 OMV.Vector3 targetVel = value;
434 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate()
435 {
436 float timeStep = 0.089f; // DEBUG DEBUG FIX FIX FIX
437 _velocityMotor.Reset();
438 _velocityMotor.SetTarget(targetVel);
439 _velocityMotor.SetCurrent(_velocity);
440 // Compute a velocity value and make sure it gets pushed into the avatar.
441 // This makes sure the avatar will start from a stop.
442 ForceVelocity = _velocityMotor.Step(timeStep);
443 });
444 }
445 }
446 // Directly setting velocity means this is what the user really wants now.
403 public override OMV.Vector3 Velocity { 447 public override OMV.Vector3 Velocity {
404 get { return _velocity; } 448 get { return _velocity; }
405 set { 449 set {
406 _velocity = value; 450 _velocity = value;
451 _velocityMotor.Reset();
452 _velocityMotor.SetCurrent(_velocity);
453 _velocityMotor.SetTarget(_velocity);
407 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 454 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
408 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 455 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
409 { 456 {
@@ -415,6 +462,8 @@ public sealed class BSCharacter : BSPhysObject
415 public override OMV.Vector3 ForceVelocity { 462 public override OMV.Vector3 ForceVelocity {
416 get { return _velocity; } 463 get { return _velocity; }
417 set { 464 set {
465 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
466
418 // Depending on whether the avatar is moving or not, change the friction 467 // Depending on whether the avatar is moving or not, change the friction
419 // to keep the avatar from slipping around 468 // to keep the avatar from slipping around
420 if (_velocity.Length() == 0) 469 if (_velocity.Length() == 0)
@@ -511,6 +560,13 @@ public sealed class BSCharacter : BSPhysObject
511 get { return _flying; } 560 get { return _flying; }
512 set { 561 set {
513 _flying = value; 562 _flying = value;
563
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
514 // simulate flying by changing the effect of gravity 570 // simulate flying by changing the effect of gravity
515 Buoyancy = ComputeBuoyancyFromFlying(_flying); 571 Buoyancy = ComputeBuoyancyFromFlying(_flying);
516 } 572 }
@@ -581,7 +637,10 @@ public sealed class BSCharacter : BSPhysObject
581 } 637 }
582 public override float ForceBuoyancy { 638 public override float ForceBuoyancy {
583 get { return _buoyancy; } 639 get { return _buoyancy; }
584 set { _buoyancy = value; 640 set {
641 PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
642
643 _buoyancy = value;
585 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 644 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
586 // Buoyancy is faked by changing the gravity applied to the object 645 // Buoyancy is faked by changing the gravity applied to the object
587 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); 646 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
@@ -698,6 +757,22 @@ public sealed class BSCharacter : BSPhysObject
698 LastEntityProperties = CurrentEntityProperties; 757 LastEntityProperties = CurrentEntityProperties;
699 CurrentEntityProperties = entprop; 758 CurrentEntityProperties = entprop;
700 759
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
701 if (entprop.Velocity != LastEntityProperties.Velocity) 776 if (entprop.Velocity != LastEntityProperties.Velocity)
702 { 777 {
703 // Changes in the velocity are suppressed in avatars. 778 // Changes in the velocity are suppressed in avatars.
@@ -706,6 +781,7 @@ public sealed class BSCharacter : BSPhysObject
706 _velocity = avVel; 781 _velocity = avVel;
707 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); 782 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel);
708 } 783 }
784 */
709 785
710 // Tell the linkset about value changes 786 // Tell the linkset about value changes
711 Linkset.UpdateProperties(this, true); 787 Linkset.UpdateProperties(this, true);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 5887249..a5acd86 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -91,6 +91,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
91 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body 91 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
92 92
93 //Deflection properties 93 //Deflection properties
94 private BSVMotor m_angularDeflectionMotor = new BSVMotor("AngularDeflection");
94 private float m_angularDeflectionEfficiency = 0; 95 private float m_angularDeflectionEfficiency = 0;
95 private float m_angularDeflectionTimescale = 0; 96 private float m_angularDeflectionTimescale = 0;
96 private float m_linearDeflectionEfficiency = 0; 97 private float m_linearDeflectionEfficiency = 0;
@@ -102,6 +103,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
102 private float m_bankingTimescale = 0; 103 private float m_bankingTimescale = 0;
103 104
104 //Hover and Buoyancy properties 105 //Hover and Buoyancy properties
106 private BSVMotor m_hoverMotor = new BSVMotor("Hover");
105 private float m_VhoverHeight = 0f; 107 private float m_VhoverHeight = 0f;
106 private float m_VhoverEfficiency = 0f; 108 private float m_VhoverEfficiency = 0f;
107 private float m_VhoverTimescale = 0f; 109 private float m_VhoverTimescale = 0f;
@@ -118,6 +120,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
118 // Timescale > cutoff means no vert attractor. 120 // Timescale > cutoff means no vert attractor.
119 private float m_verticalAttractionTimescale = 510f; 121 private float m_verticalAttractionTimescale = 510f;
120 122
123 // Just some recomputed constants:
124 static readonly float PIOverFour = ((float)Math.PI) / 4f;
125 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
126
121 public BSDynamics(BSScene myScene, BSPrim myPrim) 127 public BSDynamics(BSScene myScene, BSPrim myPrim)
122 { 128 {
123 PhysicsScene = myScene; 129 PhysicsScene = myScene;
@@ -563,9 +569,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
563 // 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
564 BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS); 570 BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
565 571
566 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
567 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
568 // Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
569 Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass); 572 Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass);
570 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); 573 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
571 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); 574 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
@@ -599,21 +602,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
599 602
600 #region Known vehicle value functions 603 #region Known vehicle value functions
601 // Vehicle physical parameters that we buffer from constant getting and setting. 604 // Vehicle physical parameters that we buffer from constant getting and setting.
602 // The "m_known*" variables are initialized to 'null', fetched only if referenced 605 // The "m_known*" values are unknown until they are fetched and the m_knownHas flag is set.
603 // and stored back into the physics engine only if updated. 606 // Changing is remembered and the parameter is stored back into the physics engine only if updated.
604 // This does two things: 1) saves continuious calls into unmanaged code, and 607 // This does two things: 1) saves continuious calls into unmanaged code, and
605 // 2) signals when a physics property update must happen back to the simulator 608 // 2) signals when a physics property update must happen back to the simulator
606 // to update values modified for the vehicle. 609 // to update values modified for the vehicle.
607 private int m_knownChanged; 610 private int m_knownChanged;
608 private float? m_knownTerrainHeight; 611 private int m_knownHas;
609 private float? m_knownWaterLevel; 612 private float m_knownTerrainHeight;
610 private Vector3? m_knownPosition; 613 private float m_knownWaterLevel;
611 private Vector3? m_knownVelocity; 614 private Vector3 m_knownPosition;
615 private Vector3 m_knownVelocity;
612 private Vector3 m_knownForce; 616 private Vector3 m_knownForce;
613 private Quaternion? m_knownOrientation; 617 private Quaternion m_knownOrientation;
614 private Vector3? m_knownRotationalVelocity; 618 private Vector3 m_knownRotationalVelocity;
615 private Vector3 m_knownRotationalForce; 619 private Vector3 m_knownRotationalForce;
616 private float? m_knownForwardSpeed; 620 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
617 621
618 private const int m_knownChangedPosition = 1 << 0; 622 private const int m_knownChangedPosition = 1 << 0;
619 private const int m_knownChangedVelocity = 1 << 1; 623 private const int m_knownChangedVelocity = 1 << 1;
@@ -621,18 +625,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
621 private const int m_knownChangedOrientation = 1 << 3; 625 private const int m_knownChangedOrientation = 1 << 3;
622 private const int m_knownChangedRotationalVelocity = 1 << 4; 626 private const int m_knownChangedRotationalVelocity = 1 << 4;
623 private const int m_knownChangedRotationalForce = 1 << 5; 627 private const int m_knownChangedRotationalForce = 1 << 5;
628 private const int m_knownChangedTerrainHeight = 1 << 6;
629 private const int m_knownChangedWaterLevel = 1 << 7;
630 private const int m_knownChangedForwardVelocity = 1 << 8;
624 631
625 private void ForgetKnownVehicleProperties() 632 private void ForgetKnownVehicleProperties()
626 { 633 {
627 m_knownTerrainHeight = null; 634 m_knownHas = 0;
628 m_knownWaterLevel = null;
629 m_knownPosition = null;
630 m_knownVelocity = null;
631 m_knownForce = Vector3.Zero;
632 m_knownOrientation = null;
633 m_knownRotationalVelocity = null;
634 m_knownRotationalForce = Vector3.Zero;
635 m_knownForwardSpeed = null;
636 m_knownChanged = 0; 635 m_knownChanged = 0;
637 } 636 }
638 private void PushKnownChanged() 637 private void PushKnownChanged()
@@ -671,17 +670,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
671 // is used ot fetch the height only once for each vehicle simulation step. 670 // is used ot fetch the height only once for each vehicle simulation step.
672 private float GetTerrainHeight(Vector3 pos) 671 private float GetTerrainHeight(Vector3 pos)
673 { 672 {
674 if (m_knownTerrainHeight == null) 673 if ((m_knownHas & m_knownChangedTerrainHeight) == 0)
674 {
675 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 675 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
676 return (float)m_knownTerrainHeight; 676 m_knownHas |= m_knownChangedTerrainHeight;
677 }
678 return m_knownTerrainHeight;
677 } 679 }
678 680
679 // Since the computation of water level can be a little involved, this routine 681 // Since the computation of water level can be a little involved, this routine
680 // is used ot fetch the level only once for each vehicle simulation step. 682 // is used ot fetch the level only once for each vehicle simulation step.
681 private float GetWaterLevel(Vector3 pos) 683 private float GetWaterLevel(Vector3 pos)
682 { 684 {
683 if (m_knownWaterLevel == null) 685 if ((m_knownHas & m_knownChangedWaterLevel) == 0)
686 {
684 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 687 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos);
688 m_knownHas |= m_knownChangedWaterLevel;
689 }
685 return (float)m_knownWaterLevel; 690 return (float)m_knownWaterLevel;
686 } 691 }
687 692
@@ -689,8 +694,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
689 { 694 {
690 get 695 get
691 { 696 {
692 if (m_knownPosition == null) 697 if ((m_knownHas & m_knownChangedPosition) == 0)
698 {
693 m_knownPosition = Prim.ForcePosition; 699 m_knownPosition = Prim.ForcePosition;
700 m_knownHas |= m_knownChangedPosition;
701 }
694 return (Vector3)m_knownPosition; 702 return (Vector3)m_knownPosition;
695 } 703 }
696 set 704 set
@@ -704,8 +712,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
704 { 712 {
705 get 713 get
706 { 714 {
707 if (m_knownOrientation == null) 715 if ((m_knownHas & m_knownChangedOrientation) == 0)
716 {
708 m_knownOrientation = Prim.ForceOrientation; 717 m_knownOrientation = Prim.ForceOrientation;
718 m_knownHas |= m_knownChangedOrientation;
719 }
709 return (Quaternion)m_knownOrientation; 720 return (Quaternion)m_knownOrientation;
710 } 721 }
711 set 722 set
@@ -719,8 +730,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
719 { 730 {
720 get 731 get
721 { 732 {
722 if (m_knownVelocity == null) 733 if ((m_knownHas & m_knownChangedVelocity) == 0)
734 {
723 m_knownVelocity = Prim.ForceVelocity; 735 m_knownVelocity = Prim.ForceVelocity;
736 m_knownHas |= m_knownChangedVelocity;
737 }
724 return (Vector3)m_knownVelocity; 738 return (Vector3)m_knownVelocity;
725 } 739 }
726 set 740 set
@@ -740,8 +754,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
740 { 754 {
741 get 755 get
742 { 756 {
743 if (m_knownRotationalVelocity == null) 757 if ((m_knownHas & m_knownChangedRotationalVelocity) == 0)
758 {
744 m_knownRotationalVelocity = Prim.ForceRotationalVelocity; 759 m_knownRotationalVelocity = Prim.ForceRotationalVelocity;
760 m_knownHas |= m_knownChangedRotationalVelocity;
761 }
745 return (Vector3)m_knownRotationalVelocity; 762 return (Vector3)m_knownRotationalVelocity;
746 } 763 }
747 set 764 set
@@ -755,13 +772,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
755 m_knownRotationalForce += aForce; 772 m_knownRotationalForce += aForce;
756 m_knownChanged |= m_knownChangedRotationalForce; 773 m_knownChanged |= m_knownChangedRotationalForce;
757 } 774 }
775 // Vehicle relative forward velocity
776 private Vector3 VehicleForwardVelocity
777 {
778 get
779 {
780 if ((m_knownHas & m_knownChangedForwardVelocity) == 0)
781 {
782 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
783 m_knownHas |= m_knownChangedForwardVelocity;
784 }
785 return (Vector3)m_knownForwardVelocity;
786 }
787 }
758 private float VehicleForwardSpeed 788 private float VehicleForwardSpeed
759 { 789 {
760 get 790 get
761 { 791 {
762 if (m_knownForwardSpeed == null) 792 return VehicleForwardVelocity.X;
763 m_knownForwardSpeed = (VehicleVelocity * Quaternion.Inverse(VehicleOrientation)).X;
764 return (float)m_knownForwardSpeed;
765 } 793 }
766 } 794 }
767 795
@@ -832,13 +860,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
832 // ================================================================== 860 // ==================================================================
833 // Clamp high or low velocities 861 // Clamp high or low velocities
834 float newVelocityLengthSq = newVelocity.LengthSquared(); 862 float newVelocityLengthSq = newVelocity.LengthSquared();
835 // if (newVelocityLengthSq > 1e6f)
836 if (newVelocityLengthSq > 1000f) 863 if (newVelocityLengthSq > 1000f)
837 { 864 {
838 newVelocity /= newVelocity.Length(); 865 newVelocity /= newVelocity.Length();
839 newVelocity *= 1000f; 866 newVelocity *= 1000f;
840 } 867 }
841 // else if (newVelocityLengthSq < 1e-6f)
842 else if (newVelocityLengthSq < 0.001f) 868 else if (newVelocityLengthSq < 0.001f)
843 newVelocity = Vector3.Zero; 869 newVelocity = Vector3.Zero;
844 870
@@ -1003,7 +1029,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1003 // Not colliding if the vehicle is off the ground 1029 // Not colliding if the vehicle is off the ground
1004 if (!Prim.IsColliding) 1030 if (!Prim.IsColliding)
1005 { 1031 {
1006 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
1007 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1032 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1008 ret = new Vector3(0, 0, -distanceAboveGround); 1033 ret = new Vector3(0, 0, -distanceAboveGround);
1009 } 1034 }
@@ -1026,7 +1051,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1026 // set directly on the vehicle. 1051 // set directly on the vehicle.
1027 private void MoveAngular(float pTimestep) 1052 private void MoveAngular(float pTimestep)
1028 { 1053 {
1029 // The user wants how many radians per second angular change? 1054 // The user wants this many radians per second angular change?
1030 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); 1055 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
1031 1056
1032 // ================================================================== 1057 // ==================================================================
@@ -1135,31 +1160,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1135 // zero and one. 1160 // zero and one.
1136 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. 1161 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1137 1162
1163 // Y error means needed rotation around X axis and visa versa.
1164 // Since the error goes from zero to one, the asin is the corresponding angle.
1165 ret.X = (float)Math.Asin(verticalError.Y);
1166 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1167 ret.Y = -(float)Math.Asin(verticalError.X);
1168
1138 // If verticalError.Z is negative, the vehicle is upside down. Add additional push. 1169 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1139 if (verticalError.Z < 0f) 1170 if (verticalError.Z < 0f)
1140 { 1171 {
1141 verticalError.X = 2f - verticalError.X; 1172 ret.X += PIOverFour;
1142 verticalError.Y = 2f - verticalError.Y; 1173 ret.Y += PIOverFour;
1143 } 1174 }
1144 1175
1145 // Y error means needed rotation around X axis and visa versa. 1176 // 'ret' is now the necessary velocity to correct tilt in one second.
1146 ret.X = verticalError.Y; 1177 // Correction happens over a number of seconds.
1147 ret.Y = - verticalError.X;
1148 ret.Z = 0f;
1149
1150 // Scale the correction force by how far we're off from vertical.
1151 // Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over.
1152 float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f);
1153 float vertForce = 1f / clampedSqrZError;
1154
1155 ret *= vertForce;
1156
1157 // Correction happens over a number of seconds.
1158 Vector3 unscaledContrib = ret; 1178 Vector3 unscaledContrib = ret;
1159 ret /= m_verticalAttractionTimescale; 1179 ret /= m_verticalAttractionTimescale;
1160 1180
1161 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},vertForce={3},eff={4},vertAttr={5}", 1181 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}",
1162 Prim.LocalID, verticalError, unscaledContrib, vertForce, m_verticalAttractionEfficiency, ret); 1182 Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret);
1163 } 1183 }
1164 return ret; 1184 return ret;
1165 } 1185 }
@@ -1172,7 +1192,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1172 public Vector3 ComputeAngularDeflection() 1192 public Vector3 ComputeAngularDeflection()
1173 { 1193 {
1174 Vector3 ret = Vector3.Zero; 1194 Vector3 ret = Vector3.Zero;
1175 return ret; // DEBUG DEBUG DEBUG debug one force at a time 1195 return ret; // DEBUG DEBUG DEBUG
1196 // Disable angular deflection for the moment.
1197 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1198 // approximately the same X or Y correction. When added together (when contributions are combined)
1199 // this creates an over-correction and then wabbling as the target is overshot.
1200 // TODO: rethink how the different correction computations inter-relate.
1176 1201
1177 if (m_angularDeflectionEfficiency != 0) 1202 if (m_angularDeflectionEfficiency != 0)
1178 { 1203 {
@@ -1184,15 +1209,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1184 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1209 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1185 pointingDirection.Normalize(); 1210 pointingDirection.Normalize();
1186 1211
1187 // The difference between what is and what should be 1212 // The difference between what is and what should be.
1188 Vector3 deflectionError = movingDirection - pointingDirection; 1213 Vector3 deflectionError = movingDirection - pointingDirection;
1189 1214
1215 // Don't try to correct very large errors (not our job)
1216 if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f;
1217 if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f;
1218 if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f;
1219
1220 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1221
1190 // Scale the correction by recovery timescale and efficiency 1222 // Scale the correction by recovery timescale and efficiency
1191 ret = (-deflectionError * VehicleForwardSpeed) * m_angularDeflectionEfficiency; 1223 ret = (-deflectionError) * m_angularDeflectionEfficiency;
1192 ret /= m_angularDeflectionTimescale; 1224 ret /= m_angularDeflectionTimescale;
1193 1225
1194 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1226 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1195 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); 1227 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret);
1228 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}",
1229 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale);
1196 } 1230 }
1197 return ret; 1231 return ret;
1198 } 1232 }
@@ -1308,6 +1342,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1308 private float ClampInRange(float low, float val, float high) 1342 private float ClampInRange(float low, float val, float high)
1309 { 1343 {
1310 return Math.Max(low, Math.Min(val, high)); 1344 return Math.Max(low, Math.Min(val, high));
1345 // return Utils.Clamp(val, low, high);
1311 } 1346 }
1312 1347
1313 // Invoke the detailed logger and output something if it's enabled. 1348 // Invoke the detailed logger and output something if it's enabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index e0faf4e..34a87c6 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -29,13 +29,14 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Framework;
32 33
33namespace OpenSim.Region.Physics.BulletSPlugin 34namespace OpenSim.Region.Physics.BulletSPlugin
34{ 35{
35public abstract class BSMotor 36public abstract class BSMotor
36{ 37{
37 // Timescales and other things can be turned off by setting them to 'infinite'. 38 // Timescales and other things can be turned off by setting them to 'infinite'.
38 public const float Infinite = 12345f; 39 public const float Infinite = 12345.6f;
39 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite); 40 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
40 41
41 public BSMotor(string useName) 42 public BSMotor(string useName)
@@ -45,6 +46,7 @@ public abstract class BSMotor
45 } 46 }
46 public virtual void Reset() { } 47 public virtual void Reset() { }
47 public virtual void Zero() { } 48 public virtual void Zero() { }
49 public virtual void GenerateTestOutput(float timeStep) { }
48 50
49 // A name passed at motor creation for easily identifyable debugging messages. 51 // A name passed at motor creation for easily identifyable debugging messages.
50 public string UseName { get; private set; } 52 public string UseName { get; private set; }
@@ -62,12 +64,16 @@ public abstract class BSMotor
62 } 64 }
63 } 65 }
64} 66}
65// Can all the incremental stepping be replaced with motor classes?
66 67
67// Motor which moves CurrentValue to TargetValue over TimeScale seconds. 68// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
68// The TargetValue decays in TargetValueDecayTimeScale and 69// The TargetValue decays in TargetValueDecayTimeScale and
69// the CurrentValue will be held back by FrictionTimeScale. 70// the CurrentValue will be held back by FrictionTimeScale.
70// TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay. 71// This motor will "zero itself" over time in that the targetValue will
72// decay to zero and the currentValue will follow it to that zero.
73// The overall effect is for the returned correction value to go from large
74// values (the total difference between current and target minus friction)
75// to small and eventually zero values.
76// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay.
71 77
72// For instance, if something is moving at speed X and the desired speed is Y, 78// For instance, if something is moving at speed X and the desired speed is Y,
73// CurrentValue is X and TargetValue is Y. As the motor is stepped, new 79// CurrentValue is X and TargetValue is Y. As the motor is stepped, new
@@ -81,13 +87,16 @@ public class BSVMotor : BSMotor
81 // public Vector3 FrameOfReference { get; set; } 87 // public Vector3 FrameOfReference { get; set; }
82 // public Vector3 Offset { get; set; } 88 // public Vector3 Offset { get; set; }
83 89
84 public float TimeScale { get; set; } 90 public virtual float TimeScale { get; set; }
85 public float TargetValueDecayTimeScale { get; set; } 91 public virtual float TargetValueDecayTimeScale { get; set; }
86 public Vector3 FrictionTimescale { get; set; } 92 public virtual Vector3 FrictionTimescale { get; set; }
87 public float Efficiency { get; set; } 93 public virtual float Efficiency { get; set; }
94
95 public virtual float ErrorZeroThreshold { get; set; }
88 96
89 public Vector3 TargetValue { get; private set; } 97 public virtual Vector3 TargetValue { get; protected set; }
90 public Vector3 CurrentValue { get; private set; } 98 public virtual Vector3 CurrentValue { get; protected set; }
99 public virtual Vector3 LastError { get; protected set; }
91 100
92 public BSVMotor(string useName) 101 public BSVMotor(string useName)
93 : base(useName) 102 : base(useName)
@@ -96,6 +105,7 @@ public class BSVMotor : BSMotor
96 Efficiency = 1f; 105 Efficiency = 1f;
97 FrictionTimescale = BSMotor.InfiniteVector; 106 FrictionTimescale = BSMotor.InfiniteVector;
98 CurrentValue = TargetValue = Vector3.Zero; 107 CurrentValue = TargetValue = Vector3.Zero;
108 ErrorZeroThreshold = 0.01f;
99 } 109 }
100 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 110 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
101 : this(useName) 111 : this(useName)
@@ -114,25 +124,25 @@ public class BSVMotor : BSMotor
114 { 124 {
115 TargetValue = target; 125 TargetValue = target;
116 } 126 }
117 127 public override void Zero()
118 // A form of stepping that does not take the time quantum into account.
119 // The caller must do the right thing later.
120 public Vector3 Step()
121 { 128 {
122 return Step(1f); 129 base.Zero();
130 CurrentValue = TargetValue = Vector3.Zero;
123 } 131 }
124 132
125 public Vector3 Step(float timeStep) 133 // Compute the next step and return the new current value
134 public virtual Vector3 Step(float timeStep)
126 { 135 {
127 Vector3 returnCurrent = Vector3.Zero; 136 Vector3 origTarget = TargetValue; // DEBUG
128 if (!CurrentValue.ApproxEquals(TargetValue, 0.01f)) 137 Vector3 origCurrVal = CurrentValue; // DEBUG
138
139 Vector3 correction = Vector3.Zero;
140 Vector3 error = TargetValue - CurrentValue;
141 if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
129 { 142 {
130 Vector3 origTarget = TargetValue; // DEBUG 143 correction = Step(timeStep, error);
131 Vector3 origCurrVal = CurrentValue; // DEBUG
132 144
133 // Addition = (desiredVector - currentAppliedVector) / secondsItShouldTakeToComplete 145 CurrentValue += correction;
134 Vector3 addAmount = (TargetValue - CurrentValue)/TimeScale * timeStep;
135 CurrentValue += addAmount;
136 146
137 // The desired value reduces to zero which also reduces the difference with current. 147 // The desired value reduces to zero which also reduces the difference with current.
138 // If the decay time is infinite, don't decay at all. 148 // If the decay time is infinite, don't decay at all.
@@ -143,40 +153,80 @@ public class BSVMotor : BSMotor
143 TargetValue *= (1f - decayFactor); 153 TargetValue *= (1f - decayFactor);
144 } 154 }
145 155
156 // The amount we can correct the error is reduced by the friction
146 Vector3 frictionFactor = Vector3.Zero; 157 Vector3 frictionFactor = Vector3.Zero;
147 if (FrictionTimescale != BSMotor.InfiniteVector) 158 if (FrictionTimescale != BSMotor.InfiniteVector)
148 { 159 {
149 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; 160 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
150 // Individual friction components can be 'infinite' so compute each separately. 161 // Individual friction components can be 'infinite' so compute each separately.
151 frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep; 162 frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X);
152 frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep; 163 frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y);
153 frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep; 164 frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z);
165 frictionFactor *= timeStep;
154 CurrentValue *= (Vector3.One - frictionFactor); 166 CurrentValue *= (Vector3.One - frictionFactor);
155 } 167 }
156 168
157 returnCurrent = CurrentValue; 169 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
158
159 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
160 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, 170 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
161 timeStep, TimeScale, addAmount, 171 timeStep, error, correction);
162 TargetValueDecayTimeScale, decayFactor, 172 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}",
163 FrictionTimescale, frictionFactor); 173 BSScene.DetailLogZero, UseName,
164 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}", 174 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
165 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, 175 TargetValue, CurrentValue);
166 addAmount, decayFactor, frictionFactor, returnCurrent);
167 } 176 }
168 else 177 else
169 { 178 {
170 // Difference between what we have and target is small. Motor is done. 179 // Difference between what we have and target is small. Motor is done.
171 CurrentValue = Vector3.Zero; 180 CurrentValue = TargetValue;
172 TargetValue = Vector3.Zero; 181 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={2}",
182 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue);
183 }
184
185 return CurrentValue;
186 }
187 public virtual Vector3 Step(float timeStep, Vector3 error)
188 {
189 LastError = error;
190 Vector3 returnCorrection = Vector3.Zero;
191 if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
192 {
193 // correction = error / secondsItShouldTakeToCorrect
194 Vector3 correctionAmount;
195 if (TimeScale == 0f || TimeScale == BSMotor.Infinite)
196 correctionAmount = error * timeStep;
197 else
198 correctionAmount = error / TimeScale * timeStep;
173 199
174 MDetailLog("{0}, BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}", 200 returnCorrection = correctionAmount;
175 BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent); 201 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},timeStep={2},timeScale={3},err={4},corr={5}",
202 BSScene.DetailLogZero, UseName, timeStep, TimeScale, error, correctionAmount);
203 }
204 return returnCorrection;
205 }
176 206
207 // The user sets all the parameters and calls this which outputs values until error is zero.
208 public override void GenerateTestOutput(float timeStep)
209 {
210 // maximum number of outputs to generate.
211 int maxOutput = 50;
212 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName);
213 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}",
214 BSScene.DetailLogZero, UseName,
215 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency,
216 CurrentValue, TargetValue);
217
218 LastError = BSMotor.InfiniteVector;
219 while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
220 {
221 Vector3 lastStep = Step(timeStep);
222 MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}",
223 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep);
177 } 224 }
178 return returnCurrent; 225 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName);
226
227
179 } 228 }
229
180 public override string ToString() 230 public override string ToString()
181 { 231 {
182 return String.Format("<{0},curr={1},targ={2},decayTS={3},frictTS={4}>", 232 return String.Format("<{0},curr={1},targ={2},decayTS={3},frictTS={4}>",
@@ -204,17 +254,74 @@ public class BSFMotor : BSMotor
204 public void SetTarget(float target) 254 public void SetTarget(float target)
205 { 255 {
206 } 256 }
207 public float Step(float timeStep) 257 public virtual float Step(float timeStep)
208 { 258 {
209 return 0f; 259 return 0f;
210 } 260 }
211} 261}
212public class BSPIDMotor : BSMotor 262
263// Proportional, Integral, Derivitive Motor
264// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors.
265public class BSPIDVMotor : BSVMotor
213{ 266{
214 // TODO: write and use this one 267 // Larger makes more overshoot, smaller means converge quicker. Range of 0.1 to 10.
215 public BSPIDMotor(string useName) 268 public Vector3 proportionFactor { get; set; }
269 public Vector3 integralFactor { get; set; }
270 public Vector3 derivFactor { get; set; }
271 // Arbritrary factor range.
272 // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct.
273 public float EfficiencyHigh = 0.4f;
274 public float EfficiencyLow = 4.0f;
275
276 Vector3 IntegralFactor { get; set; }
277
278 public BSPIDVMotor(string useName)
216 : base(useName) 279 : base(useName)
217 { 280 {
281 proportionFactor = new Vector3(1.00f, 1.00f, 1.00f);
282 integralFactor = new Vector3(1.00f, 1.00f, 1.00f);
283 derivFactor = new Vector3(1.00f, 1.00f, 1.00f);
284 IntegralFactor = Vector3.Zero;
285 LastError = Vector3.Zero;
286 }
287
288 public override void Zero()
289 {
290 base.Zero();
291 }
292
293 public override float Efficiency
294 {
295 get { return base.Efficiency; }
296 set
297 {
298 base.Efficiency = Util.Clamp(value, 0f, 1f);
299 // Compute factors based on efficiency.
300 // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot.
301 // If efficiency is low (0f), use a factor value that overcorrects.
302 // TODO: might want to vary contribution of different factor depending on efficiency.
303 float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f;
304 // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow;
305 proportionFactor = new Vector3(factor, factor, factor);
306 integralFactor = new Vector3(factor, factor, factor);
307 derivFactor = new Vector3(factor, factor, factor);
308 }
309 }
310
311 // Ignore Current and Target Values and just advance the PID computation on this error.
312 public override Vector3 Step(float timeStep, Vector3 error)
313 {
314 // Add up the error so we can integrate over the accumulated errors
315 IntegralFactor += error * timeStep;
316
317 // A simple derivitive is the rate of change from the last error.
318 Vector3 derivFactor = (error - LastError) * timeStep;
319 LastError = error;
320
321 // Correction = -(proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError)
322 Vector3 ret = -(error * proportionFactor + IntegralFactor * integralFactor + derivFactor * derivFactor);
323
324 return ret;
218 } 325 }
219} 326}
220} 327}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 758d92b..68a0db6 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -100,10 +100,15 @@ public sealed class BSPrim : BSPhysObject
100 BaseShape = pbs; 100 BaseShape = pbs;
101 _isPhysical = pisPhysical; 101 _isPhysical = pisPhysical;
102 _isVolumeDetect = false; 102 _isVolumeDetect = false;
103 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material 103
104 _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material 104 // Someday set default attributes based on the material but, for now, we don't know the prim material yet.
105 // MaterialAttributes primMat = BSMaterials.GetAttributes(Material, pisPhysical);
106 _density = PhysicsScene.Params.defaultDensity;
107 _friction = PhysicsScene.Params.defaultFriction;
105 _restitution = PhysicsScene.Params.defaultRestitution; 108 _restitution = PhysicsScene.Params.defaultRestitution;
109
106 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness 110 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
111
107 _mass = CalculateMass(); 112 _mass = CalculateMass();
108 113
109 // No body or shape yet 114 // No body or shape yet
@@ -527,16 +532,18 @@ public sealed class BSPrim : BSPhysObject
527 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 532 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
528 { 533 {
529 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 534 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
530 if (PhysBody.HasPhysicalBody) 535 ForceVelocity = _velocity;
531 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
532 }); 536 });
533 } 537 }
534 } 538 }
535 public override OMV.Vector3 ForceVelocity { 539 public override OMV.Vector3 ForceVelocity {
536 get { return _velocity; } 540 get { return _velocity; }
537 set { 541 set {
542 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity");
543
538 _velocity = value; 544 _velocity = value;
539 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); 545 if (PhysBody.HasPhysicalBody)
546 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
540 } 547 }
541 } 548 }
542 public override OMV.Vector3 Torque { 549 public override OMV.Vector3 Torque {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 069cb0d..2ca4912 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -96,6 +96,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
96 public long SimulationStep { get { return m_simulationStep; } } 96 public long SimulationStep { get { return m_simulationStep; } }
97 private int m_taintsToProcessPerStep; 97 private int m_taintsToProcessPerStep;
98 98
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
99 public delegate void PreStepAction(float timeStep); 109 public delegate void PreStepAction(float timeStep);
100 public event PreStepAction BeforeStep; 110 public event PreStepAction BeforeStep;
101 111
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 0d9a156..c084ab4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,15 +1,16 @@
1CURRENT PRIORITIES 1CURRENT PRIORITIES
2================================================= 2=================================================
3Eliminate all crashes (DONEish) 3Smooth avatar movement with motor
4 Editing/deleting physical linkset (DONE) 4 Should motor update be all at taint-time?
5 Border crossing of physical linkset (DONE)
6Enable vehicle border crossings (at least as poorly as ODE) 5Enable vehicle border crossings (at least as poorly as ODE)
6 Terrain skirts
7 Avatar created in previous region and not new region when crossing border 7 Avatar created in previous region and not new region when crossing border
8 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) 8 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
9Calibrate turning radius 9Vehicle movement on terrain smoothness
10Vehicle script tuning/debugging
11 Avanti speed script
12 Weapon shooter script
10limitMotorUp calibration (more down?) 13limitMotorUp calibration (more down?)
11study PID motors (include 'efficiency' implementation
12 Add to avatar movement
13 14
14CRASHES 15CRASHES
15================================================= 16=================================================
@@ -25,7 +26,6 @@ CRASHES
25VEHICLES TODO LIST: 26VEHICLES TODO LIST:
26================================================= 27=================================================
27Border crossing with linked vehicle causes crash 28Border crossing with linked vehicle causes crash
28Neb vehicle taking > 25ms of physics time!!
29Vehicles (Move smoothly) 29Vehicles (Move smoothly)
30Add vehicle collisions so IsColliding is properly reported. 30Add vehicle collisions so IsColliding is properly reported.
31 Needed for banking, limitMotorUp, movementLimiting, ... 31 Needed for banking, limitMotorUp, movementLimiting, ...
@@ -34,28 +34,25 @@ Cannot edit/move a vehicle being ridden: it jumps back to the origional position
34Neb car jiggling left and right 34Neb car jiggling left and right
35 Happens on terrain and any other mesh object. Flat cubes are much smoother. 35 Happens on terrain and any other mesh object. Flat cubes are much smoother.
36 This has been reduced but not eliminated. 36 This has been reduced but not eliminated.
37Light cycle falling over when driving
38Implement referenceFrame for all the motion routines. 37Implement referenceFrame for all the motion routines.
39Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. 38Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
40 Verify that angular motion specified around Z moves in the vehicle coordinates. 39 Verify that angular motion specified around Z moves in the vehicle coordinates.
41Verify llGetVel() is returning a smooth and good value for vehicle movement. 40Verify llGetVel() is returning a smooth and good value for vehicle movement.
42llGetVel() should return the root's velocity if requested in a child prim. 41llGetVel() should return the root's velocity if requested in a child prim.
43Implement function efficiency for lineaar and angular motion. 42Implement function efficiency for lineaar and angular motion.
44Should vehicle angular/linear movement friction happen after all the components
45 or does it only apply to the basic movement?
46After getting off a vehicle, the root prim is phantom (can be walked through) 43After getting off a vehicle, the root prim is phantom (can be walked through)
47 Need to force a position update for the root prim after compound shape destruction 44 Need to force a position update for the root prim after compound shape destruction
48Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) 45Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
49For limitMotorUp, use raycast down to find if vehicle is in the air. 46For limitMotorUp, use raycast down to find if vehicle is in the air.
50Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). 47Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
51 A kludge that isn't fixing the real problem of Bullet adding extra motion. 48 A kludge that isn't fixing the real problem of Bullet adding extra motion.
49Incorporate inter-relationship of angular corrections. For instance, angularDeflection
50 and angularMotorUp will compute same X or Y correction. When added together
51 creates over-correction and over-shoot and wabbling.
52 52
53BULLETSIM TODO LIST: 53BULLETSIM TODO LIST:
54================================================= 54=================================================
55Revisit CollisionMargin. Builders notice the 0.04 spacing between prims. 55Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
56Avatar height off after unsitting (floats off ground)
57 Editting appearance then moving restores.
58 Must not be initializing height when recreating capsule after unsit.
59Duplicating a physical prim causes old prim to jump away 56Duplicating a physical prim causes old prim to jump away
60 Dup a phys prim and the original become unselected and thus interacts w/ selected prim. 57 Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
61Scenes with hundred of thousands of static objects take a lot of physics CPU time. 58Scenes with hundred of thousands of static objects take a lot of physics CPU time.
@@ -82,6 +79,9 @@ Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
82 Also osGetPhysicsEngineVerion() maybe. 79 Also osGetPhysicsEngineVerion() maybe.
83Linkset.Position and Linkset.Orientation requre rewrite to properly return 80Linkset.Position and Linkset.Orientation requre rewrite to properly return
84 child position. LinksetConstraint acts like it's at taint time!! 81 child position. LinksetConstraint acts like it's at taint time!!
82Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F)
83Should the different PID factors have non-equal contributions for different
84 values of Efficiency?
85 85
86LINKSETS 86LINKSETS
87====================================================== 87======================================================
@@ -99,17 +99,16 @@ Disable activity of passive linkset children.
99 Since the linkset is a compound object, the old prims are left lying 99 Since the linkset is a compound object, the old prims are left lying
100 around and need to be phantomized so they don't collide, ... 100 around and need to be phantomized so they don't collide, ...
101Speed up creation of large physical linksets 101Speed up creation of large physical linksets
102 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical 102 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical.
103 REALLY bad for very large physical linksets (freezes the sim for many seconds).
103Eliminate collisions between objects in a linkset. (LinksetConstraint) 104Eliminate collisions between objects in a linkset. (LinksetConstraint)
104 Have UserPointer point to struct with localID and linksetID? 105 Have UserPointer point to struct with localID and linksetID?
105 Objects in original linkset still collide with each other? 106 Objects in original linkset still collide with each other?
106 107
107MORE 108MORE
108====================================================== 109======================================================
109Find/remove avatar collision with ID=0.
110Test avatar walking up stairs. How does compare with SL. 110Test avatar walking up stairs. How does compare with SL.
111 Radius of the capsule affects ability to climb edges. 111 Radius of the capsule affects ability to climb edges.
112Tune terrain/object friction to be closer to SL.
113Debounce avatar contact so legs don't keep folding up when standing. 112Debounce avatar contact so legs don't keep folding up when standing.
114Implement LSL physics controls. Like STATUS_ROTATE_X. 113Implement LSL physics controls. Like STATUS_ROTATE_X.
115Add border extensions to terrain to help region crossings and objects leaving region. 114Add border extensions to terrain to help region crossings and objects leaving region.
@@ -140,6 +139,8 @@ Consider moving prim/character body and shape destruction in destroy()
140 to postTimeTime rather than protecting all the potential sets that 139 to postTimeTime rather than protecting all the potential sets that
141 might have been queued up. 140 might have been queued up.
142Remove unused fields from ShapeData (not used in API2) 141Remove unused fields from ShapeData (not used in API2)
142Remove unused fields from pinned memory shared parameter block
143 Create parameter variables in BSScene to replace same.
143Breakout code for mesh/hull/compound/native into separate BSShape* classes 144Breakout code for mesh/hull/compound/native into separate BSShape* classes
144 Standardize access to building and reference code. 145 Standardize access to building and reference code.
145 The skeleton classes are in the sources but are not complete or linked in. 146 The skeleton classes are in the sources but are not complete or linked in.
@@ -202,3 +203,16 @@ Single prim vehicles don't seem to properly vehiclize.
202Add material type linkage and input all the material property definitions. 203Add material type linkage and input all the material property definitions.
203 Skeleton classes and table are in the sources but are not filled or used. 204 Skeleton classes and table are in the sources but are not filled or used.
204 (Resolution: 205 (Resolution:
206Neb vehicle taking > 25ms of physics time!!
207 (Resolution: compound linksets were being rebuild WAY too often)
208Avatar height off after unsitting (floats off ground)
209 Editting appearance then moving restores.
210 Must not be initializing height when recreating capsule after unsit.
211 (Resolution: confusion of scale vs size for native objects removed)
212Light cycle falling over when driving (Resolution: implemented angularMotorUp)
213Should vehicle angular/linear movement friction happen after all the components
214 or does it only apply to the basic movement?
215 (Resolution: friction added before returning newly computed motor value.
216 What is expected by some vehicles (turning up friction to moderate speed))
217Tune terrain/object friction to be closer to SL.
218 (Resolution: added material type with friction and resolution)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 3a9d0ff..30bacc6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -1483,19 +1483,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1483 return 0; 1483 return 0;
1484 1484
1485 case ScriptBaseClass.STATUS_ROTATE_X: 1485 case ScriptBaseClass.STATUS_ROTATE_X:
1486 if (m_host.GetAxisRotation(2) == 2) 1486 // if (m_host.GetAxisRotation(2) != 0)
1487 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
1487 return 1; 1488 return 1;
1488 else 1489 else
1489 return 0; 1490 return 0;
1490 1491
1491 case ScriptBaseClass.STATUS_ROTATE_Y: 1492 case ScriptBaseClass.STATUS_ROTATE_Y:
1492 if (m_host.GetAxisRotation(4) == 4) 1493 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
1493 return 1; 1494 return 1;
1494 else 1495 else
1495 return 0; 1496 return 0;
1496 1497
1497 case ScriptBaseClass.STATUS_ROTATE_Z: 1498 case ScriptBaseClass.STATUS_ROTATE_Z:
1498 if (m_host.GetAxisRotation(8) == 8) 1499 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
1499 return 1; 1500 return 1;
1500 else 1501 else
1501 return 0; 1502 return 0;