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.cs490
1 files changed, 311 insertions, 179 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 0fd1f73..7b98f9d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
45 private static string LogHeader = "[BULLETSIM VEHICLE]"; 45 private static string LogHeader = "[BULLETSIM VEHICLE]";
46 46
47 // the prim this dynamic controller belongs to 47 // the prim this dynamic controller belongs to
48 private BSPrim ControllingPrim { get; set; } 48 private BSPrimLinkable ControllingPrim { get; set; }
49 49
50 private bool m_haveRegisteredForSceneEvents; 50 private bool m_haveRegisteredForSceneEvents;
51 51
@@ -125,33 +125,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
125 static readonly float PIOverFour = ((float)Math.PI) / 4f; 125 static readonly float PIOverFour = ((float)Math.PI) / 4f;
126 static readonly float PIOverTwo = ((float)Math.PI) / 2f; 126 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
127 127
128 // For debugging, flags to turn on and off individual corrections.
129 public bool enableAngularVerticalAttraction;
130 public bool enableAngularDeflection;
131 public bool enableAngularBanking;
132
133 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) 128 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName)
134 : base(myScene, myPrim, actorName) 129 : base(myScene, myPrim, actorName)
135 { 130 {
136 ControllingPrim = myPrim;
137 Type = Vehicle.TYPE_NONE; 131 Type = Vehicle.TYPE_NONE;
138 m_haveRegisteredForSceneEvents = false; 132 m_haveRegisteredForSceneEvents = false;
139 SetupVehicleDebugging();
140 }
141 133
142 // Stopgap debugging enablement. Allows source level debugging but still checking 134 ControllingPrim = myPrim as BSPrimLinkable;
143 // in changes by making enablement of debugging flags from INI file. 135 if (ControllingPrim == null)
144 public void SetupVehicleDebugging()
145 {
146 enableAngularVerticalAttraction = true;
147 enableAngularDeflection = false;
148 enableAngularBanking = true;
149 if (BSParam.VehicleDebuggingEnabled)
150 { 136 {
151 enableAngularVerticalAttraction = true; 137 // THIS CANNOT HAPPEN!!
152 enableAngularDeflection = false;
153 enableAngularBanking = false;
154 } 138 }
139 VDetailLog("{0},Creation", ControllingPrim.LocalID);
155 } 140 }
156 141
157 // Return 'true' if this vehicle is doing vehicle things 142 // Return 'true' if this vehicle is doing vehicle things
@@ -173,7 +158,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
173 switch (pParam) 158 switch (pParam)
174 { 159 {
175 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 160 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
176 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); 161 m_angularDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
177 break; 162 break;
178 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 163 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
179 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 164 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -209,7 +194,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
209 m_VhoverTimescale = Math.Max(pValue, 0.01f); 194 m_VhoverTimescale = Math.Max(pValue, 0.01f);
210 break; 195 break;
211 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 196 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
212 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); 197 m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
213 break; 198 break;
214 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 199 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
215 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 200 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -235,7 +220,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
235 // set all of the components to the same value 220 // set all of the components to the same value
236 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 221 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
237 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); 222 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
238 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
239 break; 223 break;
240 case Vehicle.ANGULAR_MOTOR_DIRECTION: 224 case Vehicle.ANGULAR_MOTOR_DIRECTION:
241 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 225 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -244,7 +228,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
244 break; 228 break;
245 case Vehicle.LINEAR_FRICTION_TIMESCALE: 229 case Vehicle.LINEAR_FRICTION_TIMESCALE:
246 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 230 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
247 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
248 break; 231 break;
249 case Vehicle.LINEAR_MOTOR_DIRECTION: 232 case Vehicle.LINEAR_MOTOR_DIRECTION:
250 m_linearMotorDirection = new Vector3(pValue, pValue, pValue); 233 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -265,7 +248,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
265 { 248 {
266 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 249 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
267 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 250 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
268 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
269 break; 251 break;
270 case Vehicle.ANGULAR_MOTOR_DIRECTION: 252 case Vehicle.ANGULAR_MOTOR_DIRECTION:
271 // Limit requested angular speed to 2 rps= 4 pi rads/sec 253 // Limit requested angular speed to 2 rps= 4 pi rads/sec
@@ -278,7 +260,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
278 break; 260 break;
279 case Vehicle.LINEAR_FRICTION_TIMESCALE: 261 case Vehicle.LINEAR_FRICTION_TIMESCALE:
280 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 262 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
281 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
282 break; 263 break;
283 case Vehicle.LINEAR_MOTOR_DIRECTION: 264 case Vehicle.LINEAR_MOTOR_DIRECTION:
284 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 265 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -559,25 +540,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
559 break; 540 break;
560 } 541 }
561 542
562 // Update any physical parameters based on this type. 543 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
563 Refresh(); 544 // m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
564
565 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
566 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
567 1f);
568 m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
569 545
570 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, 546 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
571 m_angularMotorDecayTimescale, m_angularFrictionTimescale, 547 // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
572 1f);
573 m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
574 548
575 /* Not implemented 549 /* Not implemented
576 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, 550 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
577 BSMotor.Infinite, BSMotor.InfiniteVector, 551 BSMotor.Infinite, BSMotor.InfiniteVector,
578 m_verticalAttractionEfficiency); 552 m_verticalAttractionEfficiency);
579 // Z goes away and we keep X and Y 553 // Z goes away and we keep X and Y
580 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
581 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 554 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
582 */ 555 */
583 556
@@ -589,6 +562,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
589 { 562 {
590 RegisterForSceneEvents(); 563 RegisterForSceneEvents();
591 } 564 }
565
566 // Update any physical parameters based on this type.
567 Refresh();
592 } 568 }
593 #endregion // Vehicle parameter setting 569 #endregion // Vehicle parameter setting
594 570
@@ -596,6 +572,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
596 public override void Refresh() 572 public override void Refresh()
597 { 573 {
598 // 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.
575 // Called whether active or not since the active state may be updated before the next step.
599 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() 576 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate()
600 { 577 {
601 SetPhysicalParameters(); 578 SetPhysicalParameters();
@@ -612,8 +589,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
612 m_vehicleMass = ControllingPrim.TotalMass; 589 m_vehicleMass = ControllingPrim.TotalMass;
613 590
614 // Friction affects are handled by this vehicle code 591 // Friction affects are handled by this vehicle code
615 m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); 592 // m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction);
616 m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); 593 // m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution);
594 ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction);
595 ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution);
617 596
618 // Moderate angular movement introduced by Bullet. 597 // Moderate angular movement introduced by Bullet.
619 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. 598 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
@@ -623,17 +602,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
623 m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor); 602 m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor);
624 603
625 // 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
626 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 605 // m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
606 ControllingPrim.Linkset.AddToPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
627 607
628 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass); 608 // Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
629 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); 609 // ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
630 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.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);
631 613
632 // Set the gravity for the vehicle depending on the buoyancy 614 // Set the gravity for the vehicle depending on the buoyancy
633 // TODO: what should be done if prim and vehicle buoyancy differ? 615 // TODO: what should be done if prim and vehicle buoyancy differ?
634 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); 616 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy);
635 // 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.
636 m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); 618 // m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero);
619 ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero);
637 620
638 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}",
639 ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, 622 ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity,
@@ -645,11 +628,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
645 { 628 {
646 if (ControllingPrim.PhysBody.HasPhysicalBody) 629 if (ControllingPrim.PhysBody.HasPhysicalBody)
647 m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 630 m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
631 // ControllingPrim.Linkset.RemoveFromPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
648 } 632 }
649 } 633 }
650 634
651 // BSActor.RemoveBodyDependencies 635 // BSActor.RemoveBodyDependencies
652 public override void RemoveBodyDependencies() 636 public override void RemoveDependencies()
653 { 637 {
654 Refresh(); 638 Refresh();
655 } 639 }
@@ -657,6 +641,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
657 // BSActor.Release() 641 // BSActor.Release()
658 public override void Dispose() 642 public override void Dispose()
659 { 643 {
644 VDetailLog("{0},Dispose", ControllingPrim.LocalID);
660 UnregisterForSceneEvents(); 645 UnregisterForSceneEvents();
661 Type = Vehicle.TYPE_NONE; 646 Type = Vehicle.TYPE_NONE;
662 Enabled = false; 647 Enabled = false;
@@ -714,7 +699,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
714 private Vector3 m_knownRotationalVelocity; 699 private Vector3 m_knownRotationalVelocity;
715 private Vector3 m_knownRotationalForce; 700 private Vector3 m_knownRotationalForce;
716 private Vector3 m_knownRotationalImpulse; 701 private Vector3 m_knownRotationalImpulse;
717 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
718 702
719 private const int m_knownChangedPosition = 1 << 0; 703 private const int m_knownChangedPosition = 1 << 0;
720 private const int m_knownChangedVelocity = 1 << 1; 704 private const int m_knownChangedVelocity = 1 << 1;
@@ -726,7 +710,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
726 private const int m_knownChangedRotationalImpulse = 1 << 7; 710 private const int m_knownChangedRotationalImpulse = 1 << 7;
727 private const int m_knownChangedTerrainHeight = 1 << 8; 711 private const int m_knownChangedTerrainHeight = 1 << 8;
728 private const int m_knownChangedWaterLevel = 1 << 9; 712 private const int m_knownChangedWaterLevel = 1 << 9;
729 private const int m_knownChangedForwardVelocity = 1 <<10;
730 713
731 public void ForgetKnownVehicleProperties() 714 public void ForgetKnownVehicleProperties()
732 { 715 {
@@ -783,13 +766,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
783 766
784 // 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
785 // 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.
786 Vector3 lastRememberedHeightPos; 769 Vector3 lastRememberedHeightPos = new Vector3(-1, -1, -1);
787 private float GetTerrainHeight(Vector3 pos) 770 private float GetTerrainHeight(Vector3 pos)
788 { 771 {
789 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) 772 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
790 { 773 {
791 lastRememberedHeightPos = pos; 774 lastRememberedHeightPos = pos;
792 m_knownTerrainHeight = ControllingPrim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 775 m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
793 m_knownHas |= m_knownChangedTerrainHeight; 776 m_knownHas |= m_knownChangedTerrainHeight;
794 } 777 }
795 return m_knownTerrainHeight; 778 return m_knownTerrainHeight;
@@ -797,14 +780,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
797 780
798 // 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
799 // 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);
800 private float GetWaterLevel(Vector3 pos) 784 private float GetWaterLevel(Vector3 pos)
801 { 785 {
802 if ((m_knownHas & m_knownChangedWaterLevel) == 0) 786 if ((m_knownHas & m_knownChangedWaterLevel) == 0 || pos != lastRememberedWaterHeightPos)
803 { 787 {
804 m_knownWaterLevel = ControllingPrim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 788 lastRememberedWaterHeightPos = pos;
789 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos);
805 m_knownHas |= m_knownChangedWaterLevel; 790 m_knownHas |= m_knownChangedWaterLevel;
806 } 791 }
807 return (float)m_knownWaterLevel; 792 return m_knownWaterLevel;
808 } 793 }
809 794
810 private Vector3 VehiclePosition 795 private Vector3 VehiclePosition
@@ -930,14 +915,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
930 { 915 {
931 get 916 get
932 { 917 {
933 if ((m_knownHas & m_knownChangedForwardVelocity) == 0) 918 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
934 {
935 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
936 m_knownHas |= m_knownChangedForwardVelocity;
937 }
938 return m_knownForwardVelocity;
939 } 919 }
940 } 920 }
921
941 private float VehicleForwardSpeed 922 private float VehicleForwardSpeed
942 { 923 {
943 get 924 get
@@ -988,6 +969,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
988 { 969 {
989 ComputeLinearVelocity(pTimestep); 970 ComputeLinearVelocity(pTimestep);
990 971
972 ComputeLinearDeflection(pTimestep);
973
991 ComputeLinearTerrainHeightCorrection(pTimestep); 974 ComputeLinearTerrainHeightCorrection(pTimestep);
992 975
993 ComputeLinearHover(pTimestep); 976 ComputeLinearHover(pTimestep);
@@ -1003,11 +986,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1003 { 986 {
1004 Vector3 vel = VehicleVelocity; 987 Vector3 vel = VehicleVelocity;
1005 if ((m_flags & (VehicleFlag.NO_X)) != 0) 988 if ((m_flags & (VehicleFlag.NO_X)) != 0)
989 {
1006 vel.X = 0; 990 vel.X = 0;
991 }
1007 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 992 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
993 {
1008 vel.Y = 0; 994 vel.Y = 0;
995 }
1009 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 996 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
997 {
1010 vel.Z = 0; 998 vel.Z = 0;
999 }
1011 VehicleVelocity = vel; 1000 VehicleVelocity = vel;
1012 } 1001 }
1013 1002
@@ -1019,13 +1008,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1019 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG 1008 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
1020 VehicleVelocity /= VehicleVelocity.Length(); 1009 VehicleVelocity /= VehicleVelocity.Length();
1021 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; 1010 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
1022 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}",
1023 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); 1012 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity);
1024 } 1013 }
1025 else if (newVelocityLengthSq < 0.001f) 1014 else if (newVelocityLengthSq < 0.001f)
1026 VehicleVelocity = Vector3.Zero; 1015 VehicleVelocity = Vector3.Zero;
1027 1016
1028 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.IsColliding, VehicleVelocity ); 1017 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, VehicleVelocity );
1029 1018
1030 } // end MoveLinear() 1019 } // end MoveLinear()
1031 1020
@@ -1033,9 +1022,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1033 { 1022 {
1034 // 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.
1035 Vector3 origVelW = VehicleVelocity; // DEBUG 1024 Vector3 origVelW = VehicleVelocity; // DEBUG
1036 Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); 1025 Vector3 currentVelV = VehicleForwardVelocity;
1037 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); 1026 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
1038 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
1039 // Motor is vehicle coordinates. Rotate it to world coordinates 1032 // Motor is vehicle coordinates. Rotate it to world coordinates
1040 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; 1033 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
1041 1034
@@ -1049,8 +1042,49 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1049 // Add this correction to the velocity to make it faster/slower. 1042 // Add this correction to the velocity to make it faster/slower.
1050 VehicleVelocity += linearMotorVelocityW; 1043 VehicleVelocity += linearMotorVelocityW;
1051 1044
1052 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}",
1053 ControllingPrim.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 }
1054 } 1088 }
1055 1089
1056 public void ComputeLinearTerrainHeightCorrection(float pTimestep) 1090 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@@ -1087,14 +1121,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1087 { 1121 {
1088 m_VhoverTargetHeight = m_VhoverHeight; 1122 m_VhoverTargetHeight = m_VhoverHeight;
1089 } 1123 }
1090
1091 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) 1124 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
1092 { 1125 {
1093 // If body is already heigher, use its height as target height 1126 // If body is already heigher, use its height as target height
1094 if (VehiclePosition.Z > m_VhoverTargetHeight) 1127 if (VehiclePosition.Z > m_VhoverTargetHeight)
1128 {
1095 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 }
1096 } 1141 }
1097 1142
1098 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1143 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
1099 { 1144 {
1100 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) 1145 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
@@ -1136,7 +1181,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1136 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, 1181 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
1137 verticalError, verticalCorrection); 1182 verticalError, verticalCorrection);
1138 } 1183 }
1139
1140 } 1184 }
1141 } 1185 }
1142 1186
@@ -1188,7 +1232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1188 // 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
1189 // 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
1190 // 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
1191 // when they are in mid jump. 1235 // when they are in mid jump.
1192 // 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)?
1193 // 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
1194 // a downward raycast to find what is below. 1238 // a downward raycast to find what is below.
@@ -1201,7 +1245,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1201 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); 1245 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
1202 distanceAboveGround = VehiclePosition.Z - targetHeight; 1246 distanceAboveGround = VehiclePosition.Z - targetHeight;
1203 // Not colliding if the vehicle is off the ground 1247 // Not colliding if the vehicle is off the ground
1204 if (!Prim.IsColliding) 1248 if (!Prim.HasSomeCollision)
1205 { 1249 {
1206 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1250 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1207 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); 1251 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
@@ -1212,12 +1256,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1212 // be computed with a motor. 1256 // be computed with a motor.
1213 // TODO: add interaction with banking. 1257 // TODO: add interaction with banking.
1214 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", 1258 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1215 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); 1259 Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret);
1216 */ 1260 */
1217 1261
1218 // 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,
1219 // the vehicle is in the air. Fix that by pushing down. 1263 // the vehicle is in the air. Fix that by pushing down.
1220 if (!ControllingPrim.IsColliding && VehicleVelocity.Z > 0.1) 1264 if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1)
1221 { 1265 {
1222 // 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.
1223 float upVelocity = VehicleVelocity.Z; 1267 float upVelocity = VehicleVelocity.Z;
@@ -1239,7 +1283,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1239 } 1283 }
1240 */ 1284 */
1241 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", 1285 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}",
1242 ControllingPrim.LocalID, ControllingPrim.IsColliding, upVelocity, VehicleVelocity); 1286 ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity);
1243 } 1287 }
1244 } 1288 }
1245 } 1289 }
@@ -1249,14 +1293,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1249 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; 1293 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
1250 1294
1251 // 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
1252 if (ControllingPrim.IsColliding && IsGroundVehicle) 1296 if (ControllingPrim.HasSomeCollision && IsGroundVehicle)
1253 appliedGravity *= BSParam.VehicleGroundGravityFudge; 1297 appliedGravity *= BSParam.VehicleGroundGravityFudge;
1254 1298
1255 VehicleAddForce(appliedGravity); 1299 VehicleAddForce(appliedGravity);
1256 1300
1257 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}",
1258 ControllingPrim.LocalID, m_VehicleGravity, 1302 ControllingPrim.LocalID, m_VehicleGravity,
1259 ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); 1303 ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
1260 } 1304 }
1261 1305
1262 // ======================================================================= 1306 // =======================================================================
@@ -1323,6 +1367,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1323 private void ComputeAngularTurning(float pTimestep) 1367 private void ComputeAngularTurning(float pTimestep)
1324 { 1368 {
1325 // 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
1326 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); 1371 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
1327 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); 1372 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
1328 1373
@@ -1330,18 +1375,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1330 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 1375 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1331 // 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
1332 // for preventing ground vehicles with large linear deflection, like bumper cars, 1377 // for preventing ground vehicles with large linear deflection, like bumper cars,
1333 // from climbing their linear deflection into the sky. 1378 // from climbing their linear deflection into the sky.
1334 // 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
1335 // 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
1336 // is a linear effect. Where should this check go? 1381 // is a linear effect. Where should this check go?
1337 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1382 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1338 // { 1383 // {
1339 // angularMotorContributionV.X = 0f; 1384 // angularMotorContributionV.X = 0f;
1340 // angularMotorContributionV.Y = 0f; 1385 // angularMotorContributionV.Y = 0f;
1341 // } 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;
1342 1394
1343 VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; 1395 VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}",
1344 VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", ControllingPrim.LocalID, angularMotorContributionV); 1396 ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW);
1345 } 1397 }
1346 1398
1347 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: 1399 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
@@ -1356,86 +1408,136 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1356 { 1408 {
1357 1409
1358 // If vertical attaction timescale is reasonable 1410 // If vertical attaction timescale is reasonable
1359 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1411 if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1360 { 1412 {
1361 // Possible solution derived from a discussion at: 1413 Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1362 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no 1414 switch (BSParam.VehicleAngularVerticalAttractionAlgorithm)
1363
1364 // Create a rotation that is only the vehicle's rotation around Z
1365 Vector3 currentEuler = Vector3.Zero;
1366 VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
1367 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
1368
1369 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1370 Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1371 // Compute the angle between those to vectors.
1372 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1373 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1374
1375 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1376 // TODO: add 'efficiency'.
1377 differenceAngle /= m_verticalAttractionTimescale;
1378
1379 // Create the quaterian representing the correction angle
1380 Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
1381
1382 // Turn that quaternion into Euler values to make it into velocities to apply.
1383 Vector3 vertContributionV = Vector3.Zero;
1384 correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
1385 vertContributionV *= -1f;
1386
1387 VehicleRotationalVelocity += vertContributionV;
1388
1389 VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
1390 ControllingPrim.LocalID,
1391 differenceAxis,
1392 differenceAngle,
1393 correctionRotation,
1394 vertContributionV);
1395
1396 // ===================================================================
1397 /*
1398 Vector3 vertContributionV = Vector3.Zero;
1399 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1400
1401 // Take a vector pointing up and convert it from world to vehicle relative coords.
1402 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1403
1404 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1405 // is now:
1406 // leaning to one side: rotated around the X axis with the Y value going
1407 // from zero (nearly straight up) to one (completely to the side)) or
1408 // leaning front-to-back: rotated around the Y axis with the value of X being between
1409 // zero and one.
1410 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1411
1412 // Y error means needed rotation around X axis and visa versa.
1413 // Since the error goes from zero to one, the asin is the corresponding angle.
1414 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1415 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1416 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1417
1418 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1419 if (verticalError.Z < 0f)
1420 { 1415 {
1421 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; 1416 case 0:
1422 // 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 }
1423 } 1540 }
1424
1425 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1426 // Correction happens over a number of seconds.
1427 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1428
1429 // The correction happens over the user's time period
1430 vertContributionV /= m_verticalAttractionTimescale;
1431
1432 // Rotate the vehicle rotation to the world coordinates.
1433 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1434
1435 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1436 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1437 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1438 */
1439 } 1541 }
1440 } 1542 }
1441 1543
@@ -1445,13 +1547,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1445 // in that direction. 1547 // in that direction.
1446 // TODO: implement reference frame. 1548 // TODO: implement reference frame.
1447 public void ComputeAngularDeflection() 1549 public void ComputeAngularDeflection()
1448 { 1550 {
1449 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1450 // approximately the same X or Y correction. When added together (when contributions are combined)
1451 // this creates an over-correction and then wabbling as the target is overshot.
1452 // TODO: rethink how the different correction computations inter-relate.
1453 1551
1454 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) 1552 if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1455 { 1553 {
1456 Vector3 deflectContributionV = Vector3.Zero; 1554 Vector3 deflectContributionV = Vector3.Zero;
1457 1555
@@ -1464,10 +1562,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1464 1562
1465 // The direction the vehicle is pointing 1563 // The direction the vehicle is pointing
1466 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1564 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1467 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();
1468 1569
1469 // The difference between what is and what should be. 1570 // The difference between what is and what should be.
1470 Vector3 deflectionError = movingDirection - pointingDirection; 1571 // Vector3 deflectionError = movingDirection - predictedPointingDirection;
1572 Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection);
1471 1573
1472 // Don't try to correct very large errors (not our job) 1574 // Don't try to correct very large errors (not our job)
1473 // 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);
@@ -1480,15 +1582,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1480 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); 1582 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1481 1583
1482 // Scale the correction by recovery timescale and efficiency 1584 // Scale the correction by recovery timescale and efficiency
1483 deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; 1585 // Not modeling a spring so clamp the scale to no more then the arc
1484 deflectContributionV /= m_angularDeflectionTimescale; 1586 deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f);
1485 1587 //deflectContributionV /= m_angularDeflectionTimescale;
1486 VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1487 1588
1589 // VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1590 VehicleRotationalVelocity += deflectContributionV;
1488 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}",
1489 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); 1592 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
1490 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", 1593 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}",
1491 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); 1594 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection);
1492 } 1595 }
1493 } 1596 }
1494 1597
@@ -1500,13 +1603,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1500 // 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
1501 // of the yaw effect will be proportional to the 1604 // of the yaw effect will be proportional to the
1502 // 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
1503 // velocity along its preferred axis of motion. 1606 // velocity along its preferred axis of motion.
1504 // 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
1505 // 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
1506 // (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
1507 // 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.
1508 // 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
1509 // 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?).
1510 // 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
1511 // 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.
1512 // 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
@@ -1518,14 +1621,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1518 // 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
1519 // 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
1520 // 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
1521 // 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.
1522 // 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
1523 // 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
1524 // 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
1525 // 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.
1526 public void ComputeAngularBanking() 1629 public void ComputeAngularBanking()
1527 { 1630 {
1528 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1631 if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1529 { 1632 {
1530 Vector3 bankingContributionV = Vector3.Zero; 1633 Vector3 bankingContributionV = Vector3.Zero;
1531 1634
@@ -1551,7 +1654,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1551 1654
1552 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; 1655 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1553 VehicleRotationalVelocity += bankingContributionV; 1656 VehicleRotationalVelocity += bankingContributionV;
1554 1657
1555 1658
1556 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}",
1557 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); 1660 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
@@ -1598,6 +1701,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1598 1701
1599 } 1702 }
1600 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;
1728 }
1729 return ClampInRange(clampa, val, clampb);
1730
1731 }
1732
1601 private float ClampInRange(float low, float val, float high) 1733 private float ClampInRange(float low, float val, float high)
1602 { 1734 {
1603 return Math.Max(low, Math.Min(val, high)); 1735 return Math.Max(low, Math.Min(val, high));
@@ -1607,8 +1739,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1607 // Invoke the detailed logger and output something if it's enabled. 1739 // Invoke the detailed logger and output something if it's enabled.
1608 private void VDetailLog(string msg, params Object[] args) 1740 private void VDetailLog(string msg, params Object[] args)
1609 { 1741 {
1610 if (ControllingPrim.PhysicsScene.VehicleLoggingEnabled) 1742 if (ControllingPrim.PhysScene.VehicleLoggingEnabled)
1611 ControllingPrim.PhysicsScene.DetailLog(msg, args); 1743 ControllingPrim.PhysScene.DetailLog(msg, args);
1612 } 1744 }
1613 } 1745 }
1614} 1746}