aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs145
1 files changed, 90 insertions, 55 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 5887249..a5acd86 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -91,6 +91,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
91 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body 91 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
92 92
93 //Deflection properties 93 //Deflection properties
94 private BSVMotor m_angularDeflectionMotor = new BSVMotor("AngularDeflection");
94 private float m_angularDeflectionEfficiency = 0; 95 private float m_angularDeflectionEfficiency = 0;
95 private float m_angularDeflectionTimescale = 0; 96 private float m_angularDeflectionTimescale = 0;
96 private float m_linearDeflectionEfficiency = 0; 97 private float m_linearDeflectionEfficiency = 0;
@@ -102,6 +103,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
102 private float m_bankingTimescale = 0; 103 private float m_bankingTimescale = 0;
103 104
104 //Hover and Buoyancy properties 105 //Hover and Buoyancy properties
106 private BSVMotor m_hoverMotor = new BSVMotor("Hover");
105 private float m_VhoverHeight = 0f; 107 private float m_VhoverHeight = 0f;
106 private float m_VhoverEfficiency = 0f; 108 private float m_VhoverEfficiency = 0f;
107 private float m_VhoverTimescale = 0f; 109 private float m_VhoverTimescale = 0f;
@@ -118,6 +120,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
118 // Timescale > cutoff means no vert attractor. 120 // Timescale > cutoff means no vert attractor.
119 private float m_verticalAttractionTimescale = 510f; 121 private float m_verticalAttractionTimescale = 510f;
120 122
123 // Just some recomputed constants:
124 static readonly float PIOverFour = ((float)Math.PI) / 4f;
125 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
126
121 public BSDynamics(BSScene myScene, BSPrim myPrim) 127 public BSDynamics(BSScene myScene, BSPrim myPrim)
122 { 128 {
123 PhysicsScene = myScene; 129 PhysicsScene = myScene;
@@ -563,9 +569,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
563 // Vehicles report collision events so we know when it's on the ground 569 // Vehicles report collision events so we know when it's on the ground
564 BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS); 570 BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
565 571
566 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
567 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
568 // Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
569 Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass); 572 Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass);
570 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); 573 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
571 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); 574 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
@@ -599,21 +602,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
599 602
600 #region Known vehicle value functions 603 #region Known vehicle value functions
601 // Vehicle physical parameters that we buffer from constant getting and setting. 604 // Vehicle physical parameters that we buffer from constant getting and setting.
602 // The "m_known*" variables are initialized to 'null', fetched only if referenced 605 // The "m_known*" values are unknown until they are fetched and the m_knownHas flag is set.
603 // and stored back into the physics engine only if updated. 606 // Changing is remembered and the parameter is stored back into the physics engine only if updated.
604 // This does two things: 1) saves continuious calls into unmanaged code, and 607 // This does two things: 1) saves continuious calls into unmanaged code, and
605 // 2) signals when a physics property update must happen back to the simulator 608 // 2) signals when a physics property update must happen back to the simulator
606 // to update values modified for the vehicle. 609 // to update values modified for the vehicle.
607 private int m_knownChanged; 610 private int m_knownChanged;
608 private float? m_knownTerrainHeight; 611 private int m_knownHas;
609 private float? m_knownWaterLevel; 612 private float m_knownTerrainHeight;
610 private Vector3? m_knownPosition; 613 private float m_knownWaterLevel;
611 private Vector3? m_knownVelocity; 614 private Vector3 m_knownPosition;
615 private Vector3 m_knownVelocity;
612 private Vector3 m_knownForce; 616 private Vector3 m_knownForce;
613 private Quaternion? m_knownOrientation; 617 private Quaternion m_knownOrientation;
614 private Vector3? m_knownRotationalVelocity; 618 private Vector3 m_knownRotationalVelocity;
615 private Vector3 m_knownRotationalForce; 619 private Vector3 m_knownRotationalForce;
616 private float? m_knownForwardSpeed; 620 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
617 621
618 private const int m_knownChangedPosition = 1 << 0; 622 private const int m_knownChangedPosition = 1 << 0;
619 private const int m_knownChangedVelocity = 1 << 1; 623 private const int m_knownChangedVelocity = 1 << 1;
@@ -621,18 +625,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
621 private const int m_knownChangedOrientation = 1 << 3; 625 private const int m_knownChangedOrientation = 1 << 3;
622 private const int m_knownChangedRotationalVelocity = 1 << 4; 626 private const int m_knownChangedRotationalVelocity = 1 << 4;
623 private const int m_knownChangedRotationalForce = 1 << 5; 627 private const int m_knownChangedRotationalForce = 1 << 5;
628 private const int m_knownChangedTerrainHeight = 1 << 6;
629 private const int m_knownChangedWaterLevel = 1 << 7;
630 private const int m_knownChangedForwardVelocity = 1 << 8;
624 631
625 private void ForgetKnownVehicleProperties() 632 private void ForgetKnownVehicleProperties()
626 { 633 {
627 m_knownTerrainHeight = null; 634 m_knownHas = 0;
628 m_knownWaterLevel = null;
629 m_knownPosition = null;
630 m_knownVelocity = null;
631 m_knownForce = Vector3.Zero;
632 m_knownOrientation = null;
633 m_knownRotationalVelocity = null;
634 m_knownRotationalForce = Vector3.Zero;
635 m_knownForwardSpeed = null;
636 m_knownChanged = 0; 635 m_knownChanged = 0;
637 } 636 }
638 private void PushKnownChanged() 637 private void PushKnownChanged()
@@ -671,17 +670,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
671 // is used ot fetch the height only once for each vehicle simulation step. 670 // is used ot fetch the height only once for each vehicle simulation step.
672 private float GetTerrainHeight(Vector3 pos) 671 private float GetTerrainHeight(Vector3 pos)
673 { 672 {
674 if (m_knownTerrainHeight == null) 673 if ((m_knownHas & m_knownChangedTerrainHeight) == 0)
674 {
675 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 675 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
676 return (float)m_knownTerrainHeight; 676 m_knownHas |= m_knownChangedTerrainHeight;
677 }
678 return m_knownTerrainHeight;
677 } 679 }
678 680
679 // Since the computation of water level can be a little involved, this routine 681 // Since the computation of water level can be a little involved, this routine
680 // is used ot fetch the level only once for each vehicle simulation step. 682 // is used ot fetch the level only once for each vehicle simulation step.
681 private float GetWaterLevel(Vector3 pos) 683 private float GetWaterLevel(Vector3 pos)
682 { 684 {
683 if (m_knownWaterLevel == null) 685 if ((m_knownHas & m_knownChangedWaterLevel) == 0)
686 {
684 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 687 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos);
688 m_knownHas |= m_knownChangedWaterLevel;
689 }
685 return (float)m_knownWaterLevel; 690 return (float)m_knownWaterLevel;
686 } 691 }
687 692
@@ -689,8 +694,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
689 { 694 {
690 get 695 get
691 { 696 {
692 if (m_knownPosition == null) 697 if ((m_knownHas & m_knownChangedPosition) == 0)
698 {
693 m_knownPosition = Prim.ForcePosition; 699 m_knownPosition = Prim.ForcePosition;
700 m_knownHas |= m_knownChangedPosition;
701 }
694 return (Vector3)m_knownPosition; 702 return (Vector3)m_knownPosition;
695 } 703 }
696 set 704 set
@@ -704,8 +712,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
704 { 712 {
705 get 713 get
706 { 714 {
707 if (m_knownOrientation == null) 715 if ((m_knownHas & m_knownChangedOrientation) == 0)
716 {
708 m_knownOrientation = Prim.ForceOrientation; 717 m_knownOrientation = Prim.ForceOrientation;
718 m_knownHas |= m_knownChangedOrientation;
719 }
709 return (Quaternion)m_knownOrientation; 720 return (Quaternion)m_knownOrientation;
710 } 721 }
711 set 722 set
@@ -719,8 +730,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
719 { 730 {
720 get 731 get
721 { 732 {
722 if (m_knownVelocity == null) 733 if ((m_knownHas & m_knownChangedVelocity) == 0)
734 {
723 m_knownVelocity = Prim.ForceVelocity; 735 m_knownVelocity = Prim.ForceVelocity;
736 m_knownHas |= m_knownChangedVelocity;
737 }
724 return (Vector3)m_knownVelocity; 738 return (Vector3)m_knownVelocity;
725 } 739 }
726 set 740 set
@@ -740,8 +754,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
740 { 754 {
741 get 755 get
742 { 756 {
743 if (m_knownRotationalVelocity == null) 757 if ((m_knownHas & m_knownChangedRotationalVelocity) == 0)
758 {
744 m_knownRotationalVelocity = Prim.ForceRotationalVelocity; 759 m_knownRotationalVelocity = Prim.ForceRotationalVelocity;
760 m_knownHas |= m_knownChangedRotationalVelocity;
761 }
745 return (Vector3)m_knownRotationalVelocity; 762 return (Vector3)m_knownRotationalVelocity;
746 } 763 }
747 set 764 set
@@ -755,13 +772,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
755 m_knownRotationalForce += aForce; 772 m_knownRotationalForce += aForce;
756 m_knownChanged |= m_knownChangedRotationalForce; 773 m_knownChanged |= m_knownChangedRotationalForce;
757 } 774 }
775 // Vehicle relative forward velocity
776 private Vector3 VehicleForwardVelocity
777 {
778 get
779 {
780 if ((m_knownHas & m_knownChangedForwardVelocity) == 0)
781 {
782 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
783 m_knownHas |= m_knownChangedForwardVelocity;
784 }
785 return (Vector3)m_knownForwardVelocity;
786 }
787 }
758 private float VehicleForwardSpeed 788 private float VehicleForwardSpeed
759 { 789 {
760 get 790 get
761 { 791 {
762 if (m_knownForwardSpeed == null) 792 return VehicleForwardVelocity.X;
763 m_knownForwardSpeed = (VehicleVelocity * Quaternion.Inverse(VehicleOrientation)).X;
764 return (float)m_knownForwardSpeed;
765 } 793 }
766 } 794 }
767 795
@@ -832,13 +860,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
832 // ================================================================== 860 // ==================================================================
833 // Clamp high or low velocities 861 // Clamp high or low velocities
834 float newVelocityLengthSq = newVelocity.LengthSquared(); 862 float newVelocityLengthSq = newVelocity.LengthSquared();
835 // if (newVelocityLengthSq > 1e6f)
836 if (newVelocityLengthSq > 1000f) 863 if (newVelocityLengthSq > 1000f)
837 { 864 {
838 newVelocity /= newVelocity.Length(); 865 newVelocity /= newVelocity.Length();
839 newVelocity *= 1000f; 866 newVelocity *= 1000f;
840 } 867 }
841 // else if (newVelocityLengthSq < 1e-6f)
842 else if (newVelocityLengthSq < 0.001f) 868 else if (newVelocityLengthSq < 0.001f)
843 newVelocity = Vector3.Zero; 869 newVelocity = Vector3.Zero;
844 870
@@ -1003,7 +1029,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1003 // Not colliding if the vehicle is off the ground 1029 // Not colliding if the vehicle is off the ground
1004 if (!Prim.IsColliding) 1030 if (!Prim.IsColliding)
1005 { 1031 {
1006 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
1007 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1032 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1008 ret = new Vector3(0, 0, -distanceAboveGround); 1033 ret = new Vector3(0, 0, -distanceAboveGround);
1009 } 1034 }
@@ -1026,7 +1051,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1026 // set directly on the vehicle. 1051 // set directly on the vehicle.
1027 private void MoveAngular(float pTimestep) 1052 private void MoveAngular(float pTimestep)
1028 { 1053 {
1029 // The user wants how many radians per second angular change? 1054 // The user wants this many radians per second angular change?
1030 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); 1055 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
1031 1056
1032 // ================================================================== 1057 // ==================================================================
@@ -1135,31 +1160,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1135 // zero and one. 1160 // zero and one.
1136 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. 1161 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1137 1162
1163 // Y error means needed rotation around X axis and visa versa.
1164 // Since the error goes from zero to one, the asin is the corresponding angle.
1165 ret.X = (float)Math.Asin(verticalError.Y);
1166 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1167 ret.Y = -(float)Math.Asin(verticalError.X);
1168
1138 // If verticalError.Z is negative, the vehicle is upside down. Add additional push. 1169 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1139 if (verticalError.Z < 0f) 1170 if (verticalError.Z < 0f)
1140 { 1171 {
1141 verticalError.X = 2f - verticalError.X; 1172 ret.X += PIOverFour;
1142 verticalError.Y = 2f - verticalError.Y; 1173 ret.Y += PIOverFour;
1143 } 1174 }
1144 1175
1145 // Y error means needed rotation around X axis and visa versa. 1176 // 'ret' is now the necessary velocity to correct tilt in one second.
1146 ret.X = verticalError.Y; 1177 // Correction happens over a number of seconds.
1147 ret.Y = - verticalError.X;
1148 ret.Z = 0f;
1149
1150 // Scale the correction force by how far we're off from vertical.
1151 // Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over.
1152 float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f);
1153 float vertForce = 1f / clampedSqrZError;
1154
1155 ret *= vertForce;
1156
1157 // Correction happens over a number of seconds.
1158 Vector3 unscaledContrib = ret; 1178 Vector3 unscaledContrib = ret;
1159 ret /= m_verticalAttractionTimescale; 1179 ret /= m_verticalAttractionTimescale;
1160 1180
1161 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},vertForce={3},eff={4},vertAttr={5}", 1181 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}",
1162 Prim.LocalID, verticalError, unscaledContrib, vertForce, m_verticalAttractionEfficiency, ret); 1182 Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret);
1163 } 1183 }
1164 return ret; 1184 return ret;
1165 } 1185 }
@@ -1172,7 +1192,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1172 public Vector3 ComputeAngularDeflection() 1192 public Vector3 ComputeAngularDeflection()
1173 { 1193 {
1174 Vector3 ret = Vector3.Zero; 1194 Vector3 ret = Vector3.Zero;
1175 return ret; // DEBUG DEBUG DEBUG debug one force at a time 1195 return ret; // DEBUG DEBUG DEBUG
1196 // Disable angular deflection for the moment.
1197 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1198 // approximately the same X or Y correction. When added together (when contributions are combined)
1199 // this creates an over-correction and then wabbling as the target is overshot.
1200 // TODO: rethink how the different correction computations inter-relate.
1176 1201
1177 if (m_angularDeflectionEfficiency != 0) 1202 if (m_angularDeflectionEfficiency != 0)
1178 { 1203 {
@@ -1184,15 +1209,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1184 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1209 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1185 pointingDirection.Normalize(); 1210 pointingDirection.Normalize();
1186 1211
1187 // The difference between what is and what should be 1212 // The difference between what is and what should be.
1188 Vector3 deflectionError = movingDirection - pointingDirection; 1213 Vector3 deflectionError = movingDirection - pointingDirection;
1189 1214
1215 // Don't try to correct very large errors (not our job)
1216 if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f;
1217 if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f;
1218 if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f;
1219
1220 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1221
1190 // Scale the correction by recovery timescale and efficiency 1222 // Scale the correction by recovery timescale and efficiency
1191 ret = (-deflectionError * VehicleForwardSpeed) * m_angularDeflectionEfficiency; 1223 ret = (-deflectionError) * m_angularDeflectionEfficiency;
1192 ret /= m_angularDeflectionTimescale; 1224 ret /= m_angularDeflectionTimescale;
1193 1225
1194 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1226 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1195 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); 1227 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret);
1228 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}",
1229 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale);
1196 } 1230 }
1197 return ret; 1231 return ret;
1198 } 1232 }
@@ -1308,6 +1342,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1308 private float ClampInRange(float low, float val, float high) 1342 private float ClampInRange(float low, float val, float high)
1309 { 1343 {
1310 return Math.Max(low, Math.Min(val, high)); 1344 return Math.Max(low, Math.Min(val, high));
1345 // return Utils.Clamp(val, low, high);
1311 } 1346 }
1312 1347
1313 // Invoke the detailed logger and output something if it's enabled. 1348 // Invoke the detailed logger and output something if it's enabled.