aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs635
1 files changed, 404 insertions, 231 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 65df741..f0d17d3 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -40,13 +40,14 @@ using OpenSim.Region.Physics.Manager;
40 40
41namespace OpenSim.Region.Physics.BulletSPlugin 41namespace OpenSim.Region.Physics.BulletSPlugin
42{ 42{
43 public sealed class BSDynamics 43 public sealed class BSDynamics : BSActor
44 { 44 {
45 private static string LogHeader = "[BULLETSIM VEHICLE]"; 45 private static string LogHeader = "[BULLETSIM VEHICLE]";
46 46
47 private BSScene PhysicsScene { get; set; }
48 // the prim this dynamic controller belongs to 47 // the prim this dynamic controller belongs to
49 private BSPrim Prim { get; set; } 48 private BSPrimLinkable ControllingPrim { get; set; }
49
50 private bool m_haveRegisteredForSceneEvents;
50 51
51 // mass of the vehicle fetched each time we're calles 52 // mass of the vehicle fetched each time we're calles
52 private float m_vehicleMass; 53 private float m_vehicleMass;
@@ -124,38 +125,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 static readonly float PIOverFour = ((float)Math.PI) / 4f; 125 static readonly float PIOverFour = ((float)Math.PI) / 4f;
125 static readonly float PIOverTwo = ((float)Math.PI) / 2f; 126 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
126 127
127 // For debugging, flags to turn on and off individual corrections. 128 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName)
128 public bool enableAngularVerticalAttraction; 129 : base(myScene, myPrim, actorName)
129 public bool enableAngularDeflection;
130 public bool enableAngularBanking;
131
132 public BSDynamics(BSScene myScene, BSPrim myPrim)
133 { 130 {
134 PhysicsScene = myScene;
135 Prim = myPrim;
136 Type = Vehicle.TYPE_NONE; 131 Type = Vehicle.TYPE_NONE;
137 SetupVehicleDebugging(); 132 m_haveRegisteredForSceneEvents = false;
138 }
139 133
140 // Stopgap debugging enablement. Allows source level debugging but still checking 134 ControllingPrim = myPrim as BSPrimLinkable;
141 // in changes by making enablement of debugging flags from INI file. 135 if (ControllingPrim == null)
142 public void SetupVehicleDebugging()
143 {
144 enableAngularVerticalAttraction = true;
145 enableAngularDeflection = false;
146 enableAngularBanking = true;
147 if (BSParam.VehicleDebuggingEnabled)
148 { 136 {
149 enableAngularVerticalAttraction = true; 137 // THIS CANNOT HAPPEN!!
150 enableAngularDeflection = false;
151 enableAngularBanking = false;
152 } 138 }
139 VDetailLog("{0},Creation", ControllingPrim.LocalID);
153 } 140 }
154 141
155 // Return 'true' if this vehicle is doing vehicle things 142 // Return 'true' if this vehicle is doing vehicle things
156 public bool IsActive 143 public bool IsActive
157 { 144 {
158 get { return (Type != Vehicle.TYPE_NONE && Prim.IsPhysicallyActive); } 145 get { return (Type != Vehicle.TYPE_NONE && ControllingPrim.IsPhysicallyActive); }
159 } 146 }
160 147
161 // Return 'true' if this a vehicle that should be sitting on the ground 148 // Return 'true' if this a vehicle that should be sitting on the ground
@@ -167,11 +154,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
167 #region Vehicle parameter setting 154 #region Vehicle parameter setting
168 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue) 155 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
169 { 156 {
170 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); 157 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue);
171 switch (pParam) 158 switch (pParam)
172 { 159 {
173 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 160 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
174 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); 161 m_angularDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
175 break; 162 break;
176 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 163 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
177 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 164 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -195,7 +182,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
195 break; 182 break;
196 case Vehicle.BUOYANCY: 183 case Vehicle.BUOYANCY:
197 m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); 184 m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
198 m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy); 185 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy);
199 break; 186 break;
200 case Vehicle.HOVER_EFFICIENCY: 187 case Vehicle.HOVER_EFFICIENCY:
201 m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); 188 m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
@@ -207,7 +194,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
207 m_VhoverTimescale = Math.Max(pValue, 0.01f); 194 m_VhoverTimescale = Math.Max(pValue, 0.01f);
208 break; 195 break;
209 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 196 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
210 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); 197 m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
211 break; 198 break;
212 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 199 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
213 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 200 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -233,7 +220,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
233 // set all of the components to the same value 220 // set all of the components to the same value
234 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 221 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
235 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); 222 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
236 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
237 break; 223 break;
238 case Vehicle.ANGULAR_MOTOR_DIRECTION: 224 case Vehicle.ANGULAR_MOTOR_DIRECTION:
239 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 225 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -242,7 +228,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
242 break; 228 break;
243 case Vehicle.LINEAR_FRICTION_TIMESCALE: 229 case Vehicle.LINEAR_FRICTION_TIMESCALE:
244 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 230 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
245 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
246 break; 231 break;
247 case Vehicle.LINEAR_MOTOR_DIRECTION: 232 case Vehicle.LINEAR_MOTOR_DIRECTION:
248 m_linearMotorDirection = new Vector3(pValue, pValue, pValue); 233 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -258,12 +243,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
258 243
259 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) 244 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
260 { 245 {
261 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); 246 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue);
262 switch (pParam) 247 switch (pParam)
263 { 248 {
264 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 249 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
265 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 250 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
266 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
267 break; 251 break;
268 case Vehicle.ANGULAR_MOTOR_DIRECTION: 252 case Vehicle.ANGULAR_MOTOR_DIRECTION:
269 // Limit requested angular speed to 2 rps= 4 pi rads/sec 253 // Limit requested angular speed to 2 rps= 4 pi rads/sec
@@ -276,7 +260,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
276 break; 260 break;
277 case Vehicle.LINEAR_FRICTION_TIMESCALE: 261 case Vehicle.LINEAR_FRICTION_TIMESCALE:
278 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 262 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
279 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
280 break; 263 break;
281 case Vehicle.LINEAR_MOTOR_DIRECTION: 264 case Vehicle.LINEAR_MOTOR_DIRECTION:
282 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 265 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -294,7 +277,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
294 277
295 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 278 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
296 { 279 {
297 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); 280 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue);
298 switch (pParam) 281 switch (pParam)
299 { 282 {
300 case Vehicle.REFERENCE_FRAME: 283 case Vehicle.REFERENCE_FRAME:
@@ -308,7 +291,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
308 291
309 internal void ProcessVehicleFlags(int pParam, bool remove) 292 internal void ProcessVehicleFlags(int pParam, bool remove)
310 { 293 {
311 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); 294 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", ControllingPrim.LocalID, pParam, remove);
312 VehicleFlag parm = (VehicleFlag)pParam; 295 VehicleFlag parm = (VehicleFlag)pParam;
313 if (pParam == -1) 296 if (pParam == -1)
314 m_flags = (VehicleFlag)0; 297 m_flags = (VehicleFlag)0;
@@ -323,7 +306,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
323 306
324 public void ProcessTypeChange(Vehicle pType) 307 public void ProcessTypeChange(Vehicle pType)
325 { 308 {
326 VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); 309 VDetailLog("{0},ProcessTypeChange,type={1}", ControllingPrim.LocalID, pType);
327 // Set Defaults For Type 310 // Set Defaults For Type
328 Type = pType; 311 Type = pType;
329 switch (pType) 312 switch (pType)
@@ -557,34 +540,40 @@ namespace OpenSim.Region.Physics.BulletSPlugin
557 break; 540 break;
558 } 541 }
559 542
560 // Update any physical parameters based on this type. 543 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
561 Refresh(); 544 // m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
562 545
563 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, 546 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
564 m_linearMotorDecayTimescale, m_linearFrictionTimescale, 547 // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
565 1f);
566 m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
567
568 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale,
569 m_angularMotorDecayTimescale, m_angularFrictionTimescale,
570 1f);
571 m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
572 548
573 /* Not implemented 549 /* Not implemented
574 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, 550 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
575 BSMotor.Infinite, BSMotor.InfiniteVector, 551 BSMotor.Infinite, BSMotor.InfiniteVector,
576 m_verticalAttractionEfficiency); 552 m_verticalAttractionEfficiency);
577 // Z goes away and we keep X and Y 553 // Z goes away and we keep X and Y
578 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
579 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 554 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
580 */ 555 */
556
557 if (this.Type == Vehicle.TYPE_NONE)
558 {
559 UnregisterForSceneEvents();
560 }
561 else
562 {
563 RegisterForSceneEvents();
564 }
565
566 // Update any physical parameters based on this type.
567 Refresh();
581 } 568 }
582 #endregion // Vehicle parameter setting 569 #endregion // Vehicle parameter setting
583 570
584 public void Refresh() 571 // BSActor.Refresh()
572 public override void Refresh()
585 { 573 {
586 // If asking for a refresh, reset the physical parameters before the next simulation step. 574 // If asking for a refresh, reset the physical parameters before the next simulation step.
587 PhysicsScene.PostTaintObject("BSDynamics.Refresh", Prim.LocalID, delegate() 575 // Called whether active or not since the active state may be updated before the next step.
576 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate()
588 { 577 {
589 SetPhysicalParameters(); 578 SetPhysicalParameters();
590 }); 579 });
@@ -597,49 +586,98 @@ namespace OpenSim.Region.Physics.BulletSPlugin
597 if (IsActive) 586 if (IsActive)
598 { 587 {
599 // Remember the mass so we don't have to fetch it every step 588 // Remember the mass so we don't have to fetch it every step
600 m_vehicleMass = Prim.TotalMass; 589 m_vehicleMass = ControllingPrim.TotalMass;
601 590
602 // Friction affects are handled by this vehicle code 591 // Friction affects are handled by this vehicle code
603 PhysicsScene.PE.SetFriction(Prim.PhysBody, BSParam.VehicleFriction); 592 // m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction);
604 PhysicsScene.PE.SetRestitution(Prim.PhysBody, BSParam.VehicleRestitution); 593 // m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution);
594 ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction);
595 ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution);
605 596
606 // Moderate angular movement introduced by Bullet. 597 // Moderate angular movement introduced by Bullet.
607 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. 598 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
608 // Maybe compute linear and angular factor and damping from params. 599 // Maybe compute linear and angular factor and damping from params.
609 PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping); 600 m_physicsScene.PE.SetAngularDamping(ControllingPrim.PhysBody, BSParam.VehicleAngularDamping);
610 PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactor); 601 m_physicsScene.PE.SetLinearFactor(ControllingPrim.PhysBody, BSParam.VehicleLinearFactor);
611 PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactor); 602 m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor);
612 603
613 // Vehicles report collision events so we know when it's on the ground 604 // Vehicles report collision events so we know when it's on the ground
614 PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 605 // m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
606 ControllingPrim.Linkset.AddToPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
615 607
616 Prim.Inertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass); 608 // Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
617 PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, Prim.Inertia); 609 // ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
618 PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody); 610 // m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
611 // m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
612 ControllingPrim.Linkset.ComputeAndSetLocalInertia(BSParam.VehicleInertiaFactor, m_vehicleMass);
619 613
620 // Set the gravity for the vehicle depending on the buoyancy 614 // Set the gravity for the vehicle depending on the buoyancy
621 // TODO: what should be done if prim and vehicle buoyancy differ? 615 // TODO: what should be done if prim and vehicle buoyancy differ?
622 m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy); 616 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy);
623 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. 617 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
624 PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero); 618 // m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero);
619 ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero);
625 620
626 VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", 621 VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}",
627 Prim.LocalID, m_vehicleMass, Prim.Inertia, m_VehicleGravity, 622 ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity,
628 BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution, 623 BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution,
629 BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor 624 BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor
630 ); 625 );
631 } 626 }
632 else 627 else
633 { 628 {
634 if (Prim.PhysBody.HasPhysicalBody) 629 if (ControllingPrim.PhysBody.HasPhysicalBody)
635 PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 630 m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
631 // ControllingPrim.Linkset.RemoveFromPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
636 } 632 }
637 } 633 }
638 634
639 public bool RemoveBodyDependencies(BSPhysObject prim) 635 // BSActor.RemoveBodyDependencies
636 public override void RemoveDependencies()
640 { 637 {
641 Refresh(); 638 Refresh();
642 return IsActive; 639 }
640
641 // BSActor.Release()
642 public override void Dispose()
643 {
644 VDetailLog("{0},Dispose", ControllingPrim.LocalID);
645 UnregisterForSceneEvents();
646 Type = Vehicle.TYPE_NONE;
647 Enabled = false;
648 return;
649 }
650
651 private void RegisterForSceneEvents()
652 {
653 if (!m_haveRegisteredForSceneEvents)
654 {
655 m_physicsScene.BeforeStep += this.Step;
656 m_physicsScene.AfterStep += this.PostStep;
657 ControllingPrim.OnPreUpdateProperty += this.PreUpdateProperty;
658 m_haveRegisteredForSceneEvents = true;
659 }
660 }
661
662 private void UnregisterForSceneEvents()
663 {
664 if (m_haveRegisteredForSceneEvents)
665 {
666 m_physicsScene.BeforeStep -= this.Step;
667 m_physicsScene.AfterStep -= this.PostStep;
668 ControllingPrim.OnPreUpdateProperty -= this.PreUpdateProperty;
669 m_haveRegisteredForSceneEvents = false;
670 }
671 }
672
673 private void PreUpdateProperty(ref EntityProperties entprop)
674 {
675 // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
676 // TODO: handle physics introduced by Bullet with computed vehicle physics.
677 if (IsActive)
678 {
679 entprop.RotationalVelocity = Vector3.Zero;
680 }
643 } 681 }
644 682
645 #region Known vehicle value functions 683 #region Known vehicle value functions
@@ -661,7 +699,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
661 private Vector3 m_knownRotationalVelocity; 699 private Vector3 m_knownRotationalVelocity;
662 private Vector3 m_knownRotationalForce; 700 private Vector3 m_knownRotationalForce;
663 private Vector3 m_knownRotationalImpulse; 701 private Vector3 m_knownRotationalImpulse;
664 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
665 702
666 private const int m_knownChangedPosition = 1 << 0; 703 private const int m_knownChangedPosition = 1 << 0;
667 private const int m_knownChangedVelocity = 1 << 1; 704 private const int m_knownChangedVelocity = 1 << 1;
@@ -673,7 +710,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
673 private const int m_knownChangedRotationalImpulse = 1 << 7; 710 private const int m_knownChangedRotationalImpulse = 1 << 7;
674 private const int m_knownChangedTerrainHeight = 1 << 8; 711 private const int m_knownChangedTerrainHeight = 1 << 8;
675 private const int m_knownChangedWaterLevel = 1 << 9; 712 private const int m_knownChangedWaterLevel = 1 << 9;
676 private const int m_knownChangedForwardVelocity = 1 <<10;
677 713
678 public void ForgetKnownVehicleProperties() 714 public void ForgetKnownVehicleProperties()
679 { 715 {
@@ -686,14 +722,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
686 if (m_knownChanged != 0) 722 if (m_knownChanged != 0)
687 { 723 {
688 if ((m_knownChanged & m_knownChangedPosition) != 0) 724 if ((m_knownChanged & m_knownChangedPosition) != 0)
689 Prim.ForcePosition = m_knownPosition; 725 ControllingPrim.ForcePosition = m_knownPosition;
690 726
691 if ((m_knownChanged & m_knownChangedOrientation) != 0) 727 if ((m_knownChanged & m_knownChangedOrientation) != 0)
692 Prim.ForceOrientation = m_knownOrientation; 728 ControllingPrim.ForceOrientation = m_knownOrientation;
693 729
694 if ((m_knownChanged & m_knownChangedVelocity) != 0) 730 if ((m_knownChanged & m_knownChangedVelocity) != 0)
695 { 731 {
696 Prim.ForceVelocity = m_knownVelocity; 732 ControllingPrim.ForceVelocity = m_knownVelocity;
697 // Fake out Bullet by making it think the velocity is the same as last time. 733 // Fake out Bullet by making it think the velocity is the same as last time.
698 // Bullet does a bunch of smoothing for changing parameters. 734 // Bullet does a bunch of smoothing for changing parameters.
699 // Since the vehicle is demanding this setting, we override Bullet's smoothing 735 // Since the vehicle is demanding this setting, we override Bullet's smoothing
@@ -702,41 +738,41 @@ namespace OpenSim.Region.Physics.BulletSPlugin
702 } 738 }
703 739
704 if ((m_knownChanged & m_knownChangedForce) != 0) 740 if ((m_knownChanged & m_knownChangedForce) != 0)
705 Prim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/); 741 ControllingPrim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/);
706 742
707 if ((m_knownChanged & m_knownChangedForceImpulse) != 0) 743 if ((m_knownChanged & m_knownChangedForceImpulse) != 0)
708 Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/); 744 ControllingPrim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/);
709 745
710 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) 746 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
711 { 747 {
712 Prim.ForceRotationalVelocity = m_knownRotationalVelocity; 748 ControllingPrim.ForceRotationalVelocity = m_knownRotationalVelocity;
713 // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); 749 // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity);
714 } 750 }
715 751
716 if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0) 752 if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0)
717 Prim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/); 753 ControllingPrim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/);
718 754
719 if ((m_knownChanged & m_knownChangedRotationalForce) != 0) 755 if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
720 { 756 {
721 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/); 757 ControllingPrim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/);
722 } 758 }
723 759
724 // If we set one of the values (ie, the physics engine didn't do it) we must force 760 // If we set one of the values (ie, the physics engine didn't do it) we must force
725 // an UpdateProperties event to send the changes up to the simulator. 761 // an UpdateProperties event to send the changes up to the simulator.
726 PhysicsScene.PE.PushUpdate(Prim.PhysBody); 762 m_physicsScene.PE.PushUpdate(ControllingPrim.PhysBody);
727 } 763 }
728 m_knownChanged = 0; 764 m_knownChanged = 0;
729 } 765 }
730 766
731 // Since the computation of terrain height can be a little involved, this routine 767 // Since the computation of terrain height can be a little involved, this routine
732 // is used to fetch the height only once for each vehicle simulation step. 768 // is used to fetch the height only once for each vehicle simulation step.
733 Vector3 lastRememberedHeightPos; 769 Vector3 lastRememberedHeightPos = new Vector3(-1, -1, -1);
734 private float GetTerrainHeight(Vector3 pos) 770 private float GetTerrainHeight(Vector3 pos)
735 { 771 {
736 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) 772 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
737 { 773 {
738 lastRememberedHeightPos = pos; 774 lastRememberedHeightPos = pos;
739 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 775 m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
740 m_knownHas |= m_knownChangedTerrainHeight; 776 m_knownHas |= m_knownChangedTerrainHeight;
741 } 777 }
742 return m_knownTerrainHeight; 778 return m_knownTerrainHeight;
@@ -744,14 +780,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
744 780
745 // Since the computation of water level can be a little involved, this routine 781 // Since the computation of water level can be a little involved, this routine
746 // is used ot fetch the level only once for each vehicle simulation step. 782 // is used ot fetch the level only once for each vehicle simulation step.
783 Vector3 lastRememberedWaterHeightPos = new Vector3(-1, -1, -1);
747 private float GetWaterLevel(Vector3 pos) 784 private float GetWaterLevel(Vector3 pos)
748 { 785 {
749 if ((m_knownHas & m_knownChangedWaterLevel) == 0) 786 if ((m_knownHas & m_knownChangedWaterLevel) == 0 || pos != lastRememberedWaterHeightPos)
750 { 787 {
751 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 788 lastRememberedWaterHeightPos = pos;
789 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos);
752 m_knownHas |= m_knownChangedWaterLevel; 790 m_knownHas |= m_knownChangedWaterLevel;
753 } 791 }
754 return (float)m_knownWaterLevel; 792 return m_knownWaterLevel;
755 } 793 }
756 794
757 private Vector3 VehiclePosition 795 private Vector3 VehiclePosition
@@ -760,7 +798,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
760 { 798 {
761 if ((m_knownHas & m_knownChangedPosition) == 0) 799 if ((m_knownHas & m_knownChangedPosition) == 0)
762 { 800 {
763 m_knownPosition = Prim.ForcePosition; 801 m_knownPosition = ControllingPrim.ForcePosition;
764 m_knownHas |= m_knownChangedPosition; 802 m_knownHas |= m_knownChangedPosition;
765 } 803 }
766 return m_knownPosition; 804 return m_knownPosition;
@@ -779,7 +817,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
779 { 817 {
780 if ((m_knownHas & m_knownChangedOrientation) == 0) 818 if ((m_knownHas & m_knownChangedOrientation) == 0)
781 { 819 {
782 m_knownOrientation = Prim.ForceOrientation; 820 m_knownOrientation = ControllingPrim.ForceOrientation;
783 m_knownHas |= m_knownChangedOrientation; 821 m_knownHas |= m_knownChangedOrientation;
784 } 822 }
785 return m_knownOrientation; 823 return m_knownOrientation;
@@ -798,7 +836,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
798 { 836 {
799 if ((m_knownHas & m_knownChangedVelocity) == 0) 837 if ((m_knownHas & m_knownChangedVelocity) == 0)
800 { 838 {
801 m_knownVelocity = Prim.ForceVelocity; 839 m_knownVelocity = ControllingPrim.ForceVelocity;
802 m_knownHas |= m_knownChangedVelocity; 840 m_knownHas |= m_knownChangedVelocity;
803 } 841 }
804 return m_knownVelocity; 842 return m_knownVelocity;
@@ -839,7 +877,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
839 { 877 {
840 if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) 878 if ((m_knownHas & m_knownChangedRotationalVelocity) == 0)
841 { 879 {
842 m_knownRotationalVelocity = Prim.ForceRotationalVelocity; 880 m_knownRotationalVelocity = ControllingPrim.ForceRotationalVelocity;
843 m_knownHas |= m_knownChangedRotationalVelocity; 881 m_knownHas |= m_knownChangedRotationalVelocity;
844 } 882 }
845 return (Vector3)m_knownRotationalVelocity; 883 return (Vector3)m_knownRotationalVelocity;
@@ -877,14 +915,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
877 { 915 {
878 get 916 get
879 { 917 {
880 if ((m_knownHas & m_knownChangedForwardVelocity) == 0) 918 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
881 {
882 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
883 m_knownHas |= m_knownChangedForwardVelocity;
884 }
885 return m_knownForwardVelocity;
886 } 919 }
887 } 920 }
921
888 private float VehicleForwardSpeed 922 private float VehicleForwardSpeed
889 { 923 {
890 get 924 get
@@ -914,11 +948,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
914 // for the physics engine to note the changes so an UpdateProperties event will happen. 948 // for the physics engine to note the changes so an UpdateProperties event will happen.
915 PushKnownChanged(); 949 PushKnownChanged();
916 950
917 if (PhysicsScene.VehiclePhysicalLoggingEnabled) 951 if (m_physicsScene.VehiclePhysicalLoggingEnabled)
918 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); 952 m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody);
919 953
920 VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}", 954 VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}",
921 Prim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity); 955 ControllingPrim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity);
922 } 956 }
923 957
924 // Called after the simulation step 958 // Called after the simulation step
@@ -926,8 +960,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
926 { 960 {
927 if (!IsActive) return; 961 if (!IsActive) return;
928 962
929 if (PhysicsScene.VehiclePhysicalLoggingEnabled) 963 if (m_physicsScene.VehiclePhysicalLoggingEnabled)
930 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); 964 m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody);
931 } 965 }
932 966
933 // Apply the effect of the linear motor and other linear motions (like hover and float). 967 // Apply the effect of the linear motor and other linear motions (like hover and float).
@@ -935,6 +969,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
935 { 969 {
936 ComputeLinearVelocity(pTimestep); 970 ComputeLinearVelocity(pTimestep);
937 971
972 ComputeLinearDeflection(pTimestep);
973
938 ComputeLinearTerrainHeightCorrection(pTimestep); 974 ComputeLinearTerrainHeightCorrection(pTimestep);
939 975
940 ComputeLinearHover(pTimestep); 976 ComputeLinearHover(pTimestep);
@@ -950,11 +986,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
950 { 986 {
951 Vector3 vel = VehicleVelocity; 987 Vector3 vel = VehicleVelocity;
952 if ((m_flags & (VehicleFlag.NO_X)) != 0) 988 if ((m_flags & (VehicleFlag.NO_X)) != 0)
989 {
953 vel.X = 0; 990 vel.X = 0;
991 }
954 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 992 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
993 {
955 vel.Y = 0; 994 vel.Y = 0;
995 }
956 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 996 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
997 {
957 vel.Z = 0; 998 vel.Z = 0;
999 }
958 VehicleVelocity = vel; 1000 VehicleVelocity = vel;
959 } 1001 }
960 1002
@@ -966,13 +1008,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
966 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG 1008 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
967 VehicleVelocity /= VehicleVelocity.Length(); 1009 VehicleVelocity /= VehicleVelocity.Length();
968 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; 1010 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
969 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", 1011 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}",
970 Prim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); 1012 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity);
971 } 1013 }
972 else if (newVelocityLengthSq < 0.001f) 1014 else if (newVelocityLengthSq < 0.001f)
973 VehicleVelocity = Vector3.Zero; 1015 VehicleVelocity = Vector3.Zero;
974 1016
975 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", Prim.LocalID, Prim.IsColliding, VehicleVelocity ); 1017 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, VehicleVelocity );
976 1018
977 } // end MoveLinear() 1019 } // end MoveLinear()
978 1020
@@ -980,9 +1022,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
980 { 1022 {
981 // Step the motor from the current value. Get the correction needed this step. 1023 // Step the motor from the current value. Get the correction needed this step.
982 Vector3 origVelW = VehicleVelocity; // DEBUG 1024 Vector3 origVelW = VehicleVelocity; // DEBUG
983 Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); 1025 Vector3 currentVelV = VehicleForwardVelocity;
984 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); 1026 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
985 1027
1028 // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
1029 Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
1030 linearMotorCorrectionV -= (currentVelV * frictionFactorV);
1031
986 // Motor is vehicle coordinates. Rotate it to world coordinates 1032 // Motor is vehicle coordinates. Rotate it to world coordinates
987 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; 1033 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
988 1034
@@ -996,8 +1042,49 @@ namespace OpenSim.Region.Physics.BulletSPlugin
996 // Add this correction to the velocity to make it faster/slower. 1042 // Add this correction to the velocity to make it faster/slower.
997 VehicleVelocity += linearMotorVelocityW; 1043 VehicleVelocity += linearMotorVelocityW;
998 1044
999 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}", 1045 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},tgt={3},correctV={4},correctW={5},newVelW={6},fricFact={7}",
1000 Prim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity); 1046 ControllingPrim.LocalID, origVelW, currentVelV, m_linearMotor.TargetValue, linearMotorCorrectionV,
1047 linearMotorVelocityW, VehicleVelocity, frictionFactorV);
1048 }
1049
1050 //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis
1051 //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity
1052 private void ComputeLinearDeflection(float pTimestep)
1053 {
1054 Vector3 linearDeflectionV = Vector3.Zero;
1055 Vector3 velocityV = VehicleForwardVelocity;
1056
1057 if (BSParam.VehicleEnableLinearDeflection)
1058 {
1059 // Velocity in Y and Z dimensions is movement to the side or turning.
1060 // Compute deflection factor from the to the side and rotational velocity
1061 linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y);
1062 linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z);
1063
1064 // Velocity to the side and around is corrected and moved into the forward direction
1065 linearDeflectionV.X += Math.Abs(linearDeflectionV.Y);
1066 linearDeflectionV.X += Math.Abs(linearDeflectionV.Z);
1067
1068 // Scale the deflection to the fractional simulation time
1069 linearDeflectionV *= pTimestep;
1070
1071 // Subtract the sideways and rotational velocity deflection factors while adding the correction forward
1072 linearDeflectionV *= new Vector3(1, -1, -1);
1073
1074 // Correction is vehicle relative. Convert to world coordinates.
1075 Vector3 linearDeflectionW = linearDeflectionV * VehicleOrientation;
1076
1077 // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall.
1078 if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.HasSomeCollision)
1079 {
1080 linearDeflectionW.Z = 0f;
1081 }
1082
1083 VehicleVelocity += linearDeflectionW;
1084
1085 VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}",
1086 ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV);
1087 }
1001 } 1088 }
1002 1089
1003 public void ComputeLinearTerrainHeightCorrection(float pTimestep) 1090 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@@ -1011,7 +1098,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1011 newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; 1098 newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f;
1012 VehiclePosition = newPosition; 1099 VehiclePosition = newPosition;
1013 VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", 1100 VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}",
1014 Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); 1101 ControllingPrim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
1015 } 1102 }
1016 } 1103 }
1017 1104
@@ -1034,14 +1121,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1034 { 1121 {
1035 m_VhoverTargetHeight = m_VhoverHeight; 1122 m_VhoverTargetHeight = m_VhoverHeight;
1036 } 1123 }
1037
1038 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) 1124 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
1039 { 1125 {
1040 // If body is already heigher, use its height as target height 1126 // If body is already heigher, use its height as target height
1041 if (VehiclePosition.Z > m_VhoverTargetHeight) 1127 if (VehiclePosition.Z > m_VhoverTargetHeight)
1042 m_VhoverTargetHeight = VehiclePosition.Z; 1128 m_VhoverTargetHeight = VehiclePosition.Z;
1043 } 1129 }
1044 1130
1045 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1131 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
1046 { 1132 {
1047 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) 1133 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
@@ -1050,7 +1136,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1050 pos.Z = m_VhoverTargetHeight; 1136 pos.Z = m_VhoverTargetHeight;
1051 VehiclePosition = pos; 1137 VehiclePosition = pos;
1052 1138
1053 VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", Prim.LocalID, pos); 1139 VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", ControllingPrim.LocalID, pos);
1054 } 1140 }
1055 } 1141 }
1056 else 1142 else
@@ -1079,11 +1165,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1079 */ 1165 */
1080 1166
1081 VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}", 1167 VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}",
1082 Prim.LocalID, VehiclePosition, m_VhoverEfficiency, 1168 ControllingPrim.LocalID, VehiclePosition, m_VhoverEfficiency,
1083 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, 1169 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
1084 verticalError, verticalCorrection); 1170 verticalError, verticalCorrection);
1085 } 1171 }
1086
1087 } 1172 }
1088 } 1173 }
1089 1174
@@ -1124,7 +1209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1124 { 1209 {
1125 VehiclePosition = pos; 1210 VehiclePosition = pos;
1126 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", 1211 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
1127 Prim.LocalID, m_BlockingEndPoint, posChange, pos); 1212 ControllingPrim.LocalID, m_BlockingEndPoint, posChange, pos);
1128 } 1213 }
1129 } 1214 }
1130 return changed; 1215 return changed;
@@ -1135,7 +1220,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1135 // used with conjunction with banking: the strength of the banking will decay when the 1220 // used with conjunction with banking: the strength of the banking will decay when the
1136 // vehicle no longer experiences collisions. The decay timescale is the same as 1221 // vehicle no longer experiences collisions. The decay timescale is the same as
1137 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 1222 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1138 // when they are in mid jump. 1223 // when they are in mid jump.
1139 // TODO: this code is wrong. Also, what should it do for boats (height from water)? 1224 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1140 // This is just using the ground and a general collision check. Should really be using 1225 // This is just using the ground and a general collision check. Should really be using
1141 // a downward raycast to find what is below. 1226 // a downward raycast to find what is below.
@@ -1148,7 +1233,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1148 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); 1233 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
1149 distanceAboveGround = VehiclePosition.Z - targetHeight; 1234 distanceAboveGround = VehiclePosition.Z - targetHeight;
1150 // Not colliding if the vehicle is off the ground 1235 // Not colliding if the vehicle is off the ground
1151 if (!Prim.IsColliding) 1236 if (!Prim.HasSomeCollision)
1152 { 1237 {
1153 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1238 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1154 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); 1239 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
@@ -1159,12 +1244,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1159 // be computed with a motor. 1244 // be computed with a motor.
1160 // TODO: add interaction with banking. 1245 // TODO: add interaction with banking.
1161 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", 1246 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1162 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); 1247 Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret);
1163 */ 1248 */
1164 1249
1165 // Another approach is to measure if we're going up. If going up and not colliding, 1250 // Another approach is to measure if we're going up. If going up and not colliding,
1166 // the vehicle is in the air. Fix that by pushing down. 1251 // the vehicle is in the air. Fix that by pushing down.
1167 if (!Prim.IsColliding && VehicleVelocity.Z > 0.1) 1252 if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1)
1168 { 1253 {
1169 // Get rid of any of the velocity vector that is pushing us up. 1254 // Get rid of any of the velocity vector that is pushing us up.
1170 float upVelocity = VehicleVelocity.Z; 1255 float upVelocity = VehicleVelocity.Z;
@@ -1186,7 +1271,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1186 } 1271 }
1187 */ 1272 */
1188 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", 1273 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}",
1189 Prim.LocalID, Prim.IsColliding, upVelocity, VehicleVelocity); 1274 ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity);
1190 } 1275 }
1191 } 1276 }
1192 } 1277 }
@@ -1196,14 +1281,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1196 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; 1281 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
1197 1282
1198 // Hack to reduce downward force if the vehicle is probably sitting on the ground 1283 // Hack to reduce downward force if the vehicle is probably sitting on the ground
1199 if (Prim.IsColliding && IsGroundVehicle) 1284 if (ControllingPrim.HasSomeCollision && IsGroundVehicle)
1200 appliedGravity *= BSParam.VehicleGroundGravityFudge; 1285 appliedGravity *= BSParam.VehicleGroundGravityFudge;
1201 1286
1202 VehicleAddForce(appliedGravity); 1287 VehicleAddForce(appliedGravity);
1203 1288
1204 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", 1289 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}",
1205 Prim.LocalID, m_VehicleGravity, 1290 ControllingPrim.LocalID, m_VehicleGravity,
1206 Prim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); 1291 ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
1207 } 1292 }
1208 1293
1209 // ======================================================================= 1294 // =======================================================================
@@ -1227,11 +1312,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1227 { 1312 {
1228 // The vehicle is not adding anything angular wise. 1313 // The vehicle is not adding anything angular wise.
1229 VehicleRotationalVelocity = Vector3.Zero; 1314 VehicleRotationalVelocity = Vector3.Zero;
1230 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); 1315 VDetailLog("{0}, MoveAngular,done,zero", ControllingPrim.LocalID);
1231 } 1316 }
1232 else 1317 else
1233 { 1318 {
1234 VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", Prim.LocalID, VehicleRotationalVelocity); 1319 VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", ControllingPrim.LocalID, VehicleRotationalVelocity);
1235 } 1320 }
1236 1321
1237 // ================================================================== 1322 // ==================================================================
@@ -1262,7 +1347,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1262 torqueFromOffset.Z = 0; 1347 torqueFromOffset.Z = 0;
1263 1348
1264 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); 1349 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass);
1265 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); 1350 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", ControllingPrim.LocalID, torqueFromOffset);
1266 } 1351 }
1267 1352
1268 } 1353 }
@@ -1270,6 +1355,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1270 private void ComputeAngularTurning(float pTimestep) 1355 private void ComputeAngularTurning(float pTimestep)
1271 { 1356 {
1272 // The user wants this many radians per second angular change? 1357 // The user wants this many radians per second angular change?
1358 Vector3 origVehicleRotationalVelocity = VehicleRotationalVelocity; // DEBUG DEBUG
1273 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); 1359 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
1274 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); 1360 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
1275 1361
@@ -1277,18 +1363,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1277 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 1363 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1278 // This flag prevents linear deflection parallel to world z-axis. This is useful 1364 // This flag prevents linear deflection parallel to world z-axis. This is useful
1279 // for preventing ground vehicles with large linear deflection, like bumper cars, 1365 // for preventing ground vehicles with large linear deflection, like bumper cars,
1280 // from climbing their linear deflection into the sky. 1366 // from climbing their linear deflection into the sky.
1281 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement 1367 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1282 // TODO: This is here because this is where ODE put it but documentation says it 1368 // TODO: This is here because this is where ODE put it but documentation says it
1283 // is a linear effect. Where should this check go? 1369 // is a linear effect. Where should this check go?
1284 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1370 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1285 // { 1371 // {
1286 // angularMotorContributionV.X = 0f; 1372 // angularMotorContributionV.X = 0f;
1287 // angularMotorContributionV.Y = 0f; 1373 // angularMotorContributionV.Y = 0f;
1288 // } 1374 // }
1289 1375
1290 VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; 1376 // Reduce any velocity by friction.
1291 VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); 1377 Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep);
1378 angularMotorContributionV -= (currentAngularV * frictionFactorW);
1379
1380 Vector3 angularMotorContributionW = angularMotorContributionV * VehicleOrientation;
1381 VehicleRotationalVelocity += angularMotorContributionW;
1382
1383 VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}",
1384 ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW);
1292 } 1385 }
1293 1386
1294 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: 1387 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
@@ -1303,86 +1396,136 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1303 { 1396 {
1304 1397
1305 // If vertical attaction timescale is reasonable 1398 // If vertical attaction timescale is reasonable
1306 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1399 if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1307 { 1400 {
1308 // Possible solution derived from a discussion at: 1401 Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1309 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no 1402 switch (BSParam.VehicleAngularVerticalAttractionAlgorithm)
1310
1311 // Create a rotation that is only the vehicle's rotation around Z
1312 Vector3 currentEuler = Vector3.Zero;
1313 VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
1314 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
1315
1316 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1317 Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1318 // Compute the angle between those to vectors.
1319 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1320 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1321
1322 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1323 // TODO: add 'efficiency'.
1324 differenceAngle /= m_verticalAttractionTimescale;
1325
1326 // Create the quaterian representing the correction angle
1327 Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
1328
1329 // Turn that quaternion into Euler values to make it into velocities to apply.
1330 Vector3 vertContributionV = Vector3.Zero;
1331 correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
1332 vertContributionV *= -1f;
1333
1334 VehicleRotationalVelocity += vertContributionV;
1335
1336 VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
1337 Prim.LocalID,
1338 differenceAxis,
1339 differenceAngle,
1340 correctionRotation,
1341 vertContributionV);
1342
1343 // ===================================================================
1344 /*
1345 Vector3 vertContributionV = Vector3.Zero;
1346 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1347
1348 // Take a vector pointing up and convert it from world to vehicle relative coords.
1349 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1350
1351 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1352 // is now:
1353 // leaning to one side: rotated around the X axis with the Y value going
1354 // from zero (nearly straight up) to one (completely to the side)) or
1355 // leaning front-to-back: rotated around the Y axis with the value of X being between
1356 // zero and one.
1357 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1358
1359 // Y error means needed rotation around X axis and visa versa.
1360 // Since the error goes from zero to one, the asin is the corresponding angle.
1361 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1362 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1363 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1364
1365 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1366 if (verticalError.Z < 0f)
1367 { 1403 {
1368 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; 1404 case 0:
1369 // vertContribution.Y -= PIOverFour; 1405 {
1406 //Another formula to try got from :
1407 //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
1408
1409 // Flipping what was originally a timescale into a speed variable and then multiplying it by 2
1410 // since only computing half the distance between the angles.
1411 float verticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
1412
1413 // Make a prediction of where the up axis will be when this is applied rather then where it is now as
1414 // this makes for a smoother adjustment and less fighting between the various forces.
1415 Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1416
1417 // This is only half the distance to the target so it will take 2 seconds to complete the turn.
1418 Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
1419
1420 // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
1421 Vector3 vertContributionV = torqueVector * verticalAttractionSpeed * verticalAttractionSpeed;
1422
1423 VehicleRotationalVelocity += vertContributionV;
1424
1425 VDetailLog("{0}, MoveAngular,verticalAttraction,vertAttrSpeed={1},upAxis={2},PredictedUp={3},torqueVector={4},contrib={5}",
1426 ControllingPrim.LocalID,
1427 verticalAttractionSpeed,
1428 vehicleUpAxis,
1429 predictedUp,
1430 torqueVector,
1431 vertContributionV);
1432 break;
1433 }
1434 case 1:
1435 {
1436 // Possible solution derived from a discussion at:
1437 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1438
1439 // Create a rotation that is only the vehicle's rotation around Z
1440 Vector3 currentEulerW = Vector3.Zero;
1441 VehicleOrientation.GetEulerAngles(out currentEulerW.X, out currentEulerW.Y, out currentEulerW.Z);
1442 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEulerW.Z);
1443
1444 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1445 Vector3 differenceAxisW = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1446 // Compute the angle between those to vectors.
1447 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1448 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1449
1450 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1451 // TODO: add 'efficiency'.
1452 // differenceAngle /= m_verticalAttractionTimescale;
1453
1454 // Create the quaterian representing the correction angle
1455 Quaternion correctionRotationW = Quaternion.CreateFromAxisAngle(differenceAxisW, (float)differenceAngle);
1456
1457 // Turn that quaternion into Euler values to make it into velocities to apply.
1458 Vector3 vertContributionW = Vector3.Zero;
1459 correctionRotationW.GetEulerAngles(out vertContributionW.X, out vertContributionW.Y, out vertContributionW.Z);
1460 vertContributionW *= -1f;
1461 vertContributionW /= m_verticalAttractionTimescale;
1462
1463 VehicleRotationalVelocity += vertContributionW;
1464
1465 VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
1466 ControllingPrim.LocalID,
1467 vehicleUpAxis,
1468 differenceAxisW,
1469 differenceAngle,
1470 correctionRotationW,
1471 vertContributionW);
1472 break;
1473 }
1474 case 2:
1475 {
1476 Vector3 vertContributionV = Vector3.Zero;
1477 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1478
1479 // Take a vector pointing up and convert it from world to vehicle relative coords.
1480 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1481
1482 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1483 // is now:
1484 // leaning to one side: rotated around the X axis with the Y value going
1485 // from zero (nearly straight up) to one (completely to the side)) or
1486 // leaning front-to-back: rotated around the Y axis with the value of X being between
1487 // zero and one.
1488 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1489
1490 // Y error means needed rotation around X axis and visa versa.
1491 // Since the error goes from zero to one, the asin is the corresponding angle.
1492 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1493 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1494 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1495
1496 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1497 if (verticalError.Z < 0f)
1498 {
1499 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour;
1500 // vertContribution.Y -= PIOverFour;
1501 }
1502
1503 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1504 // Correction happens over a number of seconds.
1505 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1506
1507 // The correction happens over the user's time period
1508 vertContributionV /= m_verticalAttractionTimescale;
1509
1510 // Rotate the vehicle rotation to the world coordinates.
1511 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1512
1513 VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}",
1514 ControllingPrim.LocalID,
1515 vehicleUpAxis,
1516 origRotVelW,
1517 verticalError,
1518 unscaledContribVerticalErrorV,
1519 m_verticalAttractionEfficiency,
1520 m_verticalAttractionTimescale,
1521 vertContributionV);
1522 break;
1523 }
1524 default:
1525 {
1526 break;
1527 }
1370 } 1528 }
1371
1372 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1373 // Correction happens over a number of seconds.
1374 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1375
1376 // The correction happens over the user's time period
1377 vertContributionV /= m_verticalAttractionTimescale;
1378
1379 // Rotate the vehicle rotation to the world coordinates.
1380 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1381
1382 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1383 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1384 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1385 */
1386 } 1529 }
1387 } 1530 }
1388 1531
@@ -1392,13 +1535,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1392 // in that direction. 1535 // in that direction.
1393 // TODO: implement reference frame. 1536 // TODO: implement reference frame.
1394 public void ComputeAngularDeflection() 1537 public void ComputeAngularDeflection()
1395 { 1538 {
1396 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1397 // approximately the same X or Y correction. When added together (when contributions are combined)
1398 // this creates an over-correction and then wabbling as the target is overshot.
1399 // TODO: rethink how the different correction computations inter-relate.
1400 1539
1401 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) 1540 if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1402 { 1541 {
1403 Vector3 deflectContributionV = Vector3.Zero; 1542 Vector3 deflectContributionV = Vector3.Zero;
1404 1543
@@ -1411,10 +1550,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1411 1550
1412 // The direction the vehicle is pointing 1551 // The direction the vehicle is pointing
1413 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1552 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1414 pointingDirection.Normalize(); 1553 //Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep
1554 // from overshooting and allow this correction to merge with the Vertical Attraction peacefully.
1555 Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1556 predictedPointingDirection.Normalize();
1415 1557
1416 // The difference between what is and what should be. 1558 // The difference between what is and what should be.
1417 Vector3 deflectionError = movingDirection - pointingDirection; 1559 // Vector3 deflectionError = movingDirection - predictedPointingDirection;
1560 Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection);
1418 1561
1419 // Don't try to correct very large errors (not our job) 1562 // Don't try to correct very large errors (not our job)
1420 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); 1563 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
@@ -1427,15 +1570,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1427 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); 1570 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1428 1571
1429 // Scale the correction by recovery timescale and efficiency 1572 // Scale the correction by recovery timescale and efficiency
1430 deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; 1573 // Not modeling a spring so clamp the scale to no more then the arc
1431 deflectContributionV /= m_angularDeflectionTimescale; 1574 deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f);
1432 1575 //deflectContributionV /= m_angularDeflectionTimescale;
1433 VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1434 1576
1577 // VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1578 VehicleRotationalVelocity += deflectContributionV;
1435 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1579 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1436 Prim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); 1580 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
1437 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", 1581 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}",
1438 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); 1582 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection);
1439 } 1583 }
1440 } 1584 }
1441 1585
@@ -1447,13 +1591,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1447 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude 1591 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1448 // of the yaw effect will be proportional to the 1592 // of the yaw effect will be proportional to the
1449 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's 1593 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1450 // velocity along its preferred axis of motion. 1594 // velocity along its preferred axis of motion.
1451 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any 1595 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1452 // positive rotation (by the right-hand rule) about the roll-axis will effect a 1596 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1453 // (negative) torque around the yaw-axis, making it turn to the right--that is the 1597 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1454 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. 1598 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1455 // Negating the banking coefficient will make it so that the vehicle leans to the 1599 // Negating the banking coefficient will make it so that the vehicle leans to the
1456 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). 1600 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1457 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making 1601 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1458 // banking vehicles do what you want rather than what the laws of physics allow. 1602 // banking vehicles do what you want rather than what the laws of physics allow.
1459 // For example, consider a real motorcycle...it must be moving forward in order for 1603 // For example, consider a real motorcycle...it must be moving forward in order for
@@ -1465,14 +1609,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1465 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the 1609 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1466 // banking effect depends only on the vehicle's rotation about its roll-axis compared 1610 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1467 // to "dynamic" where the banking is also proportional to its velocity along its 1611 // to "dynamic" where the banking is also proportional to its velocity along its
1468 // roll-axis. Finding the best value of the "mixture" will probably require trial and error. 1612 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1469 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the 1613 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1470 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to 1614 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1471 // bank quickly then give it a banking timescale of about a second or less, otherwise you can 1615 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1472 // make a sluggish vehicle by giving it a timescale of several seconds. 1616 // make a sluggish vehicle by giving it a timescale of several seconds.
1473 public void ComputeAngularBanking() 1617 public void ComputeAngularBanking()
1474 { 1618 {
1475 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1619 if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1476 { 1620 {
1477 Vector3 bankingContributionV = Vector3.Zero; 1621 Vector3 bankingContributionV = Vector3.Zero;
1478 1622
@@ -1498,10 +1642,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1498 1642
1499 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; 1643 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1500 VehicleRotationalVelocity += bankingContributionV; 1644 VehicleRotationalVelocity += bankingContributionV;
1501 1645
1502 1646
1503 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", 1647 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
1504 Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); 1648 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
1505 } 1649 }
1506 } 1650 }
1507 1651
@@ -1540,8 +1684,37 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1540 if (rotq != m_rot) 1684 if (rotq != m_rot)
1541 { 1685 {
1542 VehicleOrientation = m_rot; 1686 VehicleOrientation = m_rot;
1543 VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); 1687 VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", ControllingPrim.LocalID, rotq, m_rot);
1688 }
1689
1690 }
1691
1692 // Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce
1693 // some value by to apply this friction.
1694 private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep)
1695 {
1696 Vector3 frictionFactor = Vector3.Zero;
1697 if (friction != BSMotor.InfiniteVector)
1698 {
1699 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
1700 // Individual friction components can be 'infinite' so compute each separately.
1701 frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X);
1702 frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y);
1703 frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z);
1704 frictionFactor *= pTimestep;
1705 }
1706 return frictionFactor;
1707 }
1708
1709 private float SortedClampInRange(float clampa, float val, float clampb)
1710 {
1711 if (clampa > clampb)
1712 {
1713 float temp = clampa;
1714 clampa = clampb;
1715 clampb = temp;
1544 } 1716 }
1717 return ClampInRange(clampa, val, clampb);
1545 1718
1546 } 1719 }
1547 1720
@@ -1554,8 +1727,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1554 // Invoke the detailed logger and output something if it's enabled. 1727 // Invoke the detailed logger and output something if it's enabled.
1555 private void VDetailLog(string msg, params Object[] args) 1728 private void VDetailLog(string msg, params Object[] args)
1556 { 1729 {
1557 if (Prim.PhysicsScene.VehicleLoggingEnabled) 1730 if (ControllingPrim.PhysScene.VehicleLoggingEnabled)
1558 Prim.PhysicsScene.DetailLog(msg, args); 1731 ControllingPrim.PhysScene.DetailLog(msg, args);
1559 } 1732 }
1560 } 1733 }
1561} 1734}