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.cs647
1 files changed, 416 insertions, 231 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 65df741..7b98f9d 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
563 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
564 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
565 1f);
566 m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
567 545
568 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, 546 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
569 m_angularMotorDecayTimescale, m_angularFrictionTimescale, 547 // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
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,25 @@ 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)
1128 {
1042 m_VhoverTargetHeight = VehiclePosition.Z; 1129 m_VhoverTargetHeight = VehiclePosition.Z;
1130
1131 // A 'misfeature' of this flag is that if the vehicle is above it's hover height,
1132 // the vehicle's buoyancy goes away. This is an SL bug that got used by so many
1133 // scripts that it could not be changed.
1134 // So, if above the height, reapply gravity if buoyancy had it turned off.
1135 if (m_VehicleBuoyancy != 0)
1136 {
1137 Vector3 appliedGravity = ControllingPrim.ComputeGravity(ControllingPrim.Buoyancy) * m_vehicleMass;
1138 VehicleAddForce(appliedGravity);
1139 }
1140 }
1043 } 1141 }
1044 1142
1045 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1143 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
1046 { 1144 {
1047 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) 1145 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
@@ -1050,7 +1148,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1050 pos.Z = m_VhoverTargetHeight; 1148 pos.Z = m_VhoverTargetHeight;
1051 VehiclePosition = pos; 1149 VehiclePosition = pos;
1052 1150
1053 VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", Prim.LocalID, pos); 1151 VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", ControllingPrim.LocalID, pos);
1054 } 1152 }
1055 } 1153 }
1056 else 1154 else
@@ -1079,11 +1177,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1079 */ 1177 */
1080 1178
1081 VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}", 1179 VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}",
1082 Prim.LocalID, VehiclePosition, m_VhoverEfficiency, 1180 ControllingPrim.LocalID, VehiclePosition, m_VhoverEfficiency,
1083 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, 1181 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
1084 verticalError, verticalCorrection); 1182 verticalError, verticalCorrection);
1085 } 1183 }
1086
1087 } 1184 }
1088 } 1185 }
1089 1186
@@ -1124,7 +1221,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1124 { 1221 {
1125 VehiclePosition = pos; 1222 VehiclePosition = pos;
1126 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", 1223 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
1127 Prim.LocalID, m_BlockingEndPoint, posChange, pos); 1224 ControllingPrim.LocalID, m_BlockingEndPoint, posChange, pos);
1128 } 1225 }
1129 } 1226 }
1130 return changed; 1227 return changed;
@@ -1135,7 +1232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1135 // used with conjunction with banking: the strength of the banking will decay when the 1232 // 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 1233 // 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 1234 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1138 // when they are in mid jump. 1235 // when they are in mid jump.
1139 // TODO: this code is wrong. Also, what should it do for boats (height from water)? 1236 // 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 1237 // This is just using the ground and a general collision check. Should really be using
1141 // a downward raycast to find what is below. 1238 // a downward raycast to find what is below.
@@ -1148,7 +1245,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1148 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); 1245 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
1149 distanceAboveGround = VehiclePosition.Z - targetHeight; 1246 distanceAboveGround = VehiclePosition.Z - targetHeight;
1150 // Not colliding if the vehicle is off the ground 1247 // Not colliding if the vehicle is off the ground
1151 if (!Prim.IsColliding) 1248 if (!Prim.HasSomeCollision)
1152 { 1249 {
1153 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1250 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1154 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); 1251 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
@@ -1159,12 +1256,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1159 // be computed with a motor. 1256 // be computed with a motor.
1160 // TODO: add interaction with banking. 1257 // TODO: add interaction with banking.
1161 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", 1258 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1162 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); 1259 Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret);
1163 */ 1260 */
1164 1261
1165 // Another approach is to measure if we're going up. If going up and not colliding, 1262 // 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. 1263 // the vehicle is in the air. Fix that by pushing down.
1167 if (!Prim.IsColliding && VehicleVelocity.Z > 0.1) 1264 if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1)
1168 { 1265 {
1169 // Get rid of any of the velocity vector that is pushing us up. 1266 // Get rid of any of the velocity vector that is pushing us up.
1170 float upVelocity = VehicleVelocity.Z; 1267 float upVelocity = VehicleVelocity.Z;
@@ -1186,7 +1283,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1186 } 1283 }
1187 */ 1284 */
1188 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", 1285 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}",
1189 Prim.LocalID, Prim.IsColliding, upVelocity, VehicleVelocity); 1286 ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity);
1190 } 1287 }
1191 } 1288 }
1192 } 1289 }
@@ -1196,14 +1293,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1196 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; 1293 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
1197 1294
1198 // Hack to reduce downward force if the vehicle is probably sitting on the ground 1295 // Hack to reduce downward force if the vehicle is probably sitting on the ground
1199 if (Prim.IsColliding && IsGroundVehicle) 1296 if (ControllingPrim.HasSomeCollision && IsGroundVehicle)
1200 appliedGravity *= BSParam.VehicleGroundGravityFudge; 1297 appliedGravity *= BSParam.VehicleGroundGravityFudge;
1201 1298
1202 VehicleAddForce(appliedGravity); 1299 VehicleAddForce(appliedGravity);
1203 1300
1204 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", 1301 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}",
1205 Prim.LocalID, m_VehicleGravity, 1302 ControllingPrim.LocalID, m_VehicleGravity,
1206 Prim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); 1303 ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
1207 } 1304 }
1208 1305
1209 // ======================================================================= 1306 // =======================================================================
@@ -1227,11 +1324,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1227 { 1324 {
1228 // The vehicle is not adding anything angular wise. 1325 // The vehicle is not adding anything angular wise.
1229 VehicleRotationalVelocity = Vector3.Zero; 1326 VehicleRotationalVelocity = Vector3.Zero;
1230 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); 1327 VDetailLog("{0}, MoveAngular,done,zero", ControllingPrim.LocalID);
1231 } 1328 }
1232 else 1329 else
1233 { 1330 {
1234 VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", Prim.LocalID, VehicleRotationalVelocity); 1331 VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", ControllingPrim.LocalID, VehicleRotationalVelocity);
1235 } 1332 }
1236 1333
1237 // ================================================================== 1334 // ==================================================================
@@ -1262,7 +1359,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1262 torqueFromOffset.Z = 0; 1359 torqueFromOffset.Z = 0;
1263 1360
1264 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); 1361 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass);
1265 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); 1362 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", ControllingPrim.LocalID, torqueFromOffset);
1266 } 1363 }
1267 1364
1268 } 1365 }
@@ -1270,6 +1367,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1270 private void ComputeAngularTurning(float pTimestep) 1367 private void ComputeAngularTurning(float pTimestep)
1271 { 1368 {
1272 // The user wants this many radians per second angular change? 1369 // The user wants this many radians per second angular change?
1370 Vector3 origVehicleRotationalVelocity = VehicleRotationalVelocity; // DEBUG DEBUG
1273 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); 1371 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
1274 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); 1372 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
1275 1373
@@ -1277,18 +1375,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1277 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 1375 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1278 // This flag prevents linear deflection parallel to world z-axis. This is useful 1376 // 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, 1377 // for preventing ground vehicles with large linear deflection, like bumper cars,
1280 // from climbing their linear deflection into the sky. 1378 // 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 1379 // 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 1380 // 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? 1381 // is a linear effect. Where should this check go?
1284 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1382 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1285 // { 1383 // {
1286 // angularMotorContributionV.X = 0f; 1384 // angularMotorContributionV.X = 0f;
1287 // angularMotorContributionV.Y = 0f; 1385 // angularMotorContributionV.Y = 0f;
1288 // } 1386 // }
1387
1388 // Reduce any velocity by friction.
1389 Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep);
1390 angularMotorContributionV -= (currentAngularV * frictionFactorW);
1391
1392 Vector3 angularMotorContributionW = angularMotorContributionV * VehicleOrientation;
1393 VehicleRotationalVelocity += angularMotorContributionW;
1289 1394
1290 VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; 1395 VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}",
1291 VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); 1396 ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW);
1292 } 1397 }
1293 1398
1294 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: 1399 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
@@ -1303,86 +1408,136 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1303 { 1408 {
1304 1409
1305 // If vertical attaction timescale is reasonable 1410 // If vertical attaction timescale is reasonable
1306 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1411 if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1307 { 1412 {
1308 // Possible solution derived from a discussion at: 1413 Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1309 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no 1414 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 { 1415 {
1368 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; 1416 case 0:
1369 // vertContribution.Y -= PIOverFour; 1417 {
1418 //Another formula to try got from :
1419 //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
1420
1421 // Flipping what was originally a timescale into a speed variable and then multiplying it by 2
1422 // since only computing half the distance between the angles.
1423 float verticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
1424
1425 // Make a prediction of where the up axis will be when this is applied rather then where it is now as
1426 // this makes for a smoother adjustment and less fighting between the various forces.
1427 Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1428
1429 // This is only half the distance to the target so it will take 2 seconds to complete the turn.
1430 Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
1431
1432 // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
1433 Vector3 vertContributionV = torqueVector * verticalAttractionSpeed * verticalAttractionSpeed;
1434
1435 VehicleRotationalVelocity += vertContributionV;
1436
1437 VDetailLog("{0}, MoveAngular,verticalAttraction,vertAttrSpeed={1},upAxis={2},PredictedUp={3},torqueVector={4},contrib={5}",
1438 ControllingPrim.LocalID,
1439 verticalAttractionSpeed,
1440 vehicleUpAxis,
1441 predictedUp,
1442 torqueVector,
1443 vertContributionV);
1444 break;
1445 }
1446 case 1:
1447 {
1448 // Possible solution derived from a discussion at:
1449 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1450
1451 // Create a rotation that is only the vehicle's rotation around Z
1452 Vector3 currentEulerW = Vector3.Zero;
1453 VehicleOrientation.GetEulerAngles(out currentEulerW.X, out currentEulerW.Y, out currentEulerW.Z);
1454 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEulerW.Z);
1455
1456 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1457 Vector3 differenceAxisW = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1458 // Compute the angle between those to vectors.
1459 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1460 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1461
1462 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1463 // TODO: add 'efficiency'.
1464 // differenceAngle /= m_verticalAttractionTimescale;
1465
1466 // Create the quaterian representing the correction angle
1467 Quaternion correctionRotationW = Quaternion.CreateFromAxisAngle(differenceAxisW, (float)differenceAngle);
1468
1469 // Turn that quaternion into Euler values to make it into velocities to apply.
1470 Vector3 vertContributionW = Vector3.Zero;
1471 correctionRotationW.GetEulerAngles(out vertContributionW.X, out vertContributionW.Y, out vertContributionW.Z);
1472 vertContributionW *= -1f;
1473 vertContributionW /= m_verticalAttractionTimescale;
1474
1475 VehicleRotationalVelocity += vertContributionW;
1476
1477 VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
1478 ControllingPrim.LocalID,
1479 vehicleUpAxis,
1480 differenceAxisW,
1481 differenceAngle,
1482 correctionRotationW,
1483 vertContributionW);
1484 break;
1485 }
1486 case 2:
1487 {
1488 Vector3 vertContributionV = Vector3.Zero;
1489 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1490
1491 // Take a vector pointing up and convert it from world to vehicle relative coords.
1492 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1493
1494 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1495 // is now:
1496 // leaning to one side: rotated around the X axis with the Y value going
1497 // from zero (nearly straight up) to one (completely to the side)) or
1498 // leaning front-to-back: rotated around the Y axis with the value of X being between
1499 // zero and one.
1500 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1501
1502 // Y error means needed rotation around X axis and visa versa.
1503 // Since the error goes from zero to one, the asin is the corresponding angle.
1504 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1505 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1506 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1507
1508 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1509 if (verticalError.Z < 0f)
1510 {
1511 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour;
1512 // vertContribution.Y -= PIOverFour;
1513 }
1514
1515 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1516 // Correction happens over a number of seconds.
1517 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1518
1519 // The correction happens over the user's time period
1520 vertContributionV /= m_verticalAttractionTimescale;
1521
1522 // Rotate the vehicle rotation to the world coordinates.
1523 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1524
1525 VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}",
1526 ControllingPrim.LocalID,
1527 vehicleUpAxis,
1528 origRotVelW,
1529 verticalError,
1530 unscaledContribVerticalErrorV,
1531 m_verticalAttractionEfficiency,
1532 m_verticalAttractionTimescale,
1533 vertContributionV);
1534 break;
1535 }
1536 default:
1537 {
1538 break;
1539 }
1370 } 1540 }
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 } 1541 }
1387 } 1542 }
1388 1543
@@ -1392,13 +1547,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1392 // in that direction. 1547 // in that direction.
1393 // TODO: implement reference frame. 1548 // TODO: implement reference frame.
1394 public void ComputeAngularDeflection() 1549 public void ComputeAngularDeflection()
1395 { 1550 {
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 1551
1401 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) 1552 if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1402 { 1553 {
1403 Vector3 deflectContributionV = Vector3.Zero; 1554 Vector3 deflectContributionV = Vector3.Zero;
1404 1555
@@ -1411,10 +1562,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1411 1562
1412 // The direction the vehicle is pointing 1563 // The direction the vehicle is pointing
1413 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1564 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1414 pointingDirection.Normalize(); 1565 //Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep
1566 // from overshooting and allow this correction to merge with the Vertical Attraction peacefully.
1567 Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1568 predictedPointingDirection.Normalize();
1415 1569
1416 // The difference between what is and what should be. 1570 // The difference between what is and what should be.
1417 Vector3 deflectionError = movingDirection - pointingDirection; 1571 // Vector3 deflectionError = movingDirection - predictedPointingDirection;
1572 Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection);
1418 1573
1419 // Don't try to correct very large errors (not our job) 1574 // 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); 1575 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
@@ -1427,15 +1582,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1427 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); 1582 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1428 1583
1429 // Scale the correction by recovery timescale and efficiency 1584 // Scale the correction by recovery timescale and efficiency
1430 deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; 1585 // Not modeling a spring so clamp the scale to no more then the arc
1431 deflectContributionV /= m_angularDeflectionTimescale; 1586 deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f);
1432 1587 //deflectContributionV /= m_angularDeflectionTimescale;
1433 VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1434 1588
1589 // VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1590 VehicleRotationalVelocity += deflectContributionV;
1435 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1591 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1436 Prim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); 1592 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
1437 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", 1593 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}",
1438 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); 1594 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection);
1439 } 1595 }
1440 } 1596 }
1441 1597
@@ -1447,13 +1603,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1447 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude 1603 // 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 1604 // of the yaw effect will be proportional to the
1449 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's 1605 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1450 // velocity along its preferred axis of motion. 1606 // velocity along its preferred axis of motion.
1451 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any 1607 // 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 1608 // 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 1609 // (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. 1610 // 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 1611 // 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?). 1612 // 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 1613 // 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. 1614 // 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 1615 // For example, consider a real motorcycle...it must be moving forward in order for
@@ -1465,14 +1621,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1465 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the 1621 // 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 1622 // 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 1623 // 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. 1624 // 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 1625 // 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 1626 // 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 1627 // 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. 1628 // make a sluggish vehicle by giving it a timescale of several seconds.
1473 public void ComputeAngularBanking() 1629 public void ComputeAngularBanking()
1474 { 1630 {
1475 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1631 if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1476 { 1632 {
1477 Vector3 bankingContributionV = Vector3.Zero; 1633 Vector3 bankingContributionV = Vector3.Zero;
1478 1634
@@ -1498,10 +1654,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1498 1654
1499 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; 1655 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1500 VehicleRotationalVelocity += bankingContributionV; 1656 VehicleRotationalVelocity += bankingContributionV;
1501 1657
1502 1658
1503 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", 1659 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); 1660 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
1505 } 1661 }
1506 } 1662 }
1507 1663
@@ -1540,8 +1696,37 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1540 if (rotq != m_rot) 1696 if (rotq != m_rot)
1541 { 1697 {
1542 VehicleOrientation = m_rot; 1698 VehicleOrientation = m_rot;
1543 VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); 1699 VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", ControllingPrim.LocalID, rotq, m_rot);
1700 }
1701
1702 }
1703
1704 // Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce
1705 // some value by to apply this friction.
1706 private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep)
1707 {
1708 Vector3 frictionFactor = Vector3.Zero;
1709 if (friction != BSMotor.InfiniteVector)
1710 {
1711 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
1712 // Individual friction components can be 'infinite' so compute each separately.
1713 frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X);
1714 frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y);
1715 frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z);
1716 frictionFactor *= pTimestep;
1717 }
1718 return frictionFactor;
1719 }
1720
1721 private float SortedClampInRange(float clampa, float val, float clampb)
1722 {
1723 if (clampa > clampb)
1724 {
1725 float temp = clampa;
1726 clampa = clampb;
1727 clampb = temp;
1544 } 1728 }
1729 return ClampInRange(clampa, val, clampb);
1545 1730
1546 } 1731 }
1547 1732
@@ -1554,8 +1739,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1554 // Invoke the detailed logger and output something if it's enabled. 1739 // Invoke the detailed logger and output something if it's enabled.
1555 private void VDetailLog(string msg, params Object[] args) 1740 private void VDetailLog(string msg, params Object[] args)
1556 { 1741 {
1557 if (Prim.PhysicsScene.VehicleLoggingEnabled) 1742 if (ControllingPrim.PhysScene.VehicleLoggingEnabled)
1558 Prim.PhysicsScene.DetailLog(msg, args); 1743 ControllingPrim.PhysScene.DetailLog(msg, args);
1559 } 1744 }
1560 } 1745 }
1561} 1746}