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.cs346
1 files changed, 182 insertions, 164 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index aa247dd..0204967 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -125,33 +125,12 @@ 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; 131 ControllingPrim = myPrim;
137 Type = Vehicle.TYPE_NONE; 132 Type = Vehicle.TYPE_NONE;
138 m_haveRegisteredForSceneEvents = false; 133 m_haveRegisteredForSceneEvents = false;
139 SetupVehicleDebugging();
140 }
141
142 // Stopgap debugging enablement. Allows source level debugging but still checking
143 // in changes by making enablement of debugging flags from INI file.
144 public void SetupVehicleDebugging()
145 {
146 enableAngularVerticalAttraction = true;
147 enableAngularDeflection = false;
148 enableAngularBanking = true;
149 if (BSParam.VehicleDebuggingEnable)
150 {
151 enableAngularVerticalAttraction = true;
152 enableAngularDeflection = false;
153 enableAngularBanking = false;
154 }
155 } 134 }
156 135
157 // Return 'true' if this vehicle is doing vehicle things 136 // Return 'true' if this vehicle is doing vehicle things
@@ -173,7 +152,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
173 switch (pParam) 152 switch (pParam)
174 { 153 {
175 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 154 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
176 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); 155 m_angularDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
177 break; 156 break;
178 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 157 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
179 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 158 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -556,10 +535,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
556 } 535 }
557 536
558 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f); 537 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
559 m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 538 // m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
560 539
561 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f); 540 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
562 m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 541 // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
563 542
564 /* Not implemented 543 /* Not implemented
565 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, 544 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
@@ -774,7 +753,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
774 753
775 // Since the computation of terrain height can be a little involved, this routine 754 // Since the computation of terrain height can be a little involved, this routine
776 // is used to fetch the height only once for each vehicle simulation step. 755 // is used to fetch the height only once for each vehicle simulation step.
777 Vector3 lastRememberedHeightPos; 756 Vector3 lastRememberedHeightPos = new Vector3(-1, -1, -1);
778 private float GetTerrainHeight(Vector3 pos) 757 private float GetTerrainHeight(Vector3 pos)
779 { 758 {
780 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) 759 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
@@ -788,14 +767,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
788 767
789 // Since the computation of water level can be a little involved, this routine 768 // Since the computation of water level can be a little involved, this routine
790 // is used ot fetch the level only once for each vehicle simulation step. 769 // is used ot fetch the level only once for each vehicle simulation step.
770 Vector3 lastRememberedWaterHeightPos = new Vector3(-1, -1, -1);
791 private float GetWaterLevel(Vector3 pos) 771 private float GetWaterLevel(Vector3 pos)
792 { 772 {
793 if ((m_knownHas & m_knownChangedWaterLevel) == 0) 773 if ((m_knownHas & m_knownChangedWaterLevel) == 0 || pos != lastRememberedWaterHeightPos)
794 { 774 {
775 lastRememberedWaterHeightPos = pos;
795 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos); 776 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos);
796 m_knownHas |= m_knownChangedWaterLevel; 777 m_knownHas |= m_knownChangedWaterLevel;
797 } 778 }
798 return (float)m_knownWaterLevel; 779 return m_knownWaterLevel;
799 } 780 }
800 781
801 private Vector3 VehiclePosition 782 private Vector3 VehiclePosition
@@ -924,6 +905,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
924 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); 905 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
925 } 906 }
926 } 907 }
908
927 private float VehicleForwardSpeed 909 private float VehicleForwardSpeed
928 { 910 {
929 get 911 get
@@ -991,11 +973,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
991 { 973 {
992 Vector3 vel = VehicleVelocity; 974 Vector3 vel = VehicleVelocity;
993 if ((m_flags & (VehicleFlag.NO_X)) != 0) 975 if ((m_flags & (VehicleFlag.NO_X)) != 0)
976 {
994 vel.X = 0; 977 vel.X = 0;
978 }
995 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 979 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
980 {
996 vel.Y = 0; 981 vel.Y = 0;
982 }
997 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 983 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
984 {
998 vel.Z = 0; 985 vel.Z = 0;
986 }
999 VehicleVelocity = vel; 987 VehicleVelocity = vel;
1000 } 988 }
1001 989
@@ -1053,26 +1041,37 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1053 Vector3 linearDeflectionV = Vector3.Zero; 1041 Vector3 linearDeflectionV = Vector3.Zero;
1054 Vector3 velocityV = VehicleForwardVelocity; 1042 Vector3 velocityV = VehicleForwardVelocity;
1055 1043
1056 // Velocity in Y and Z dimensions is movement to the side or turning. 1044 if (BSParam.VehicleEnableLinearDeflection)
1057 // Compute deflection factor from the to the side and rotational velocity 1045 {
1058 linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y); 1046 // Velocity in Y and Z dimensions is movement to the side or turning.
1059 linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z); 1047 // Compute deflection factor from the to the side and rotational velocity
1048 linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y);
1049 linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z);
1060 1050
1061 // Velocity to the side and around is corrected and moved into the forward direction 1051 // Velocity to the side and around is corrected and moved into the forward direction
1062 linearDeflectionV.X += Math.Abs(linearDeflectionV.Y); 1052 linearDeflectionV.X += Math.Abs(linearDeflectionV.Y);
1063 linearDeflectionV.X += Math.Abs(linearDeflectionV.Z); 1053 linearDeflectionV.X += Math.Abs(linearDeflectionV.Z);
1064 1054
1065 // Scale the deflection to the fractional simulation time 1055 // Scale the deflection to the fractional simulation time
1066 linearDeflectionV *= pTimestep; 1056 linearDeflectionV *= pTimestep;
1067 1057
1068 // Subtract the sideways and rotational velocity deflection factors while adding the correction forward 1058 // Subtract the sideways and rotational velocity deflection factors while adding the correction forward
1069 linearDeflectionV *= new Vector3(1,-1,-1); 1059 linearDeflectionV *= new Vector3(1, -1, -1);
1060
1061 // Correction is vehicle relative. Convert to world coordinates.
1062 Vector3 linearDeflectionW = linearDeflectionV * VehicleOrientation;
1063
1064 // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall.
1065 if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.IsColliding)
1066 {
1067 linearDeflectionW.Z = 0f;
1068 }
1070 1069
1071 // Correciont is vehicle relative. Convert to world coordinates and add to the velocity 1070 VehicleVelocity += linearDeflectionW;
1072 VehicleVelocity += linearDeflectionV * VehicleOrientation;
1073 1071
1074 VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}", 1072 VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}",
1075 ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV); 1073 ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV);
1074 }
1076 } 1075 }
1077 1076
1078 public void ComputeLinearTerrainHeightCorrection(float pTimestep) 1077 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@@ -1385,116 +1384,134 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1385 { 1384 {
1386 1385
1387 // If vertical attaction timescale is reasonable 1386 // If vertical attaction timescale is reasonable
1388 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1387 if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1389 { 1388 {
1390 //Another formula to try got from : 1389 Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1391 //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html 1390 switch (BSParam.VehicleAngularVerticalAttractionAlgorithm)
1392
1393 Vector3 VehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1394
1395 // Flipping what was originally a timescale into a speed variable and then multiplying it by 2
1396 // since only computing half the distance between the angles.
1397 float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
1398
1399 // Make a prediction of where the up axis will be when this is applied rather then where it is now as
1400 // this makes for a smoother adjustment and less fighting between the various forces.
1401 Vector3 predictedUp = VehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1402
1403 // This is only half the distance to the target so it will take 2 seconds to complete the turn.
1404 Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
1405
1406 // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
1407 Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
1408
1409 VehicleRotationalVelocity += vertContributionV;
1410
1411 VDetailLog("{0}, MoveAngular,verticalAttraction,UpAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
1412 ControllingPrim.LocalID,
1413 VehicleUpAxis,
1414 predictedUp,
1415 torqueVector,
1416 vertContributionV);
1417 //=====================================================================
1418 /*
1419 // Possible solution derived from a discussion at:
1420 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1421
1422 // Create a rotation that is only the vehicle's rotation around Z
1423 Vector3 currentEuler = Vector3.Zero;
1424 VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
1425 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
1426
1427 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1428 Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1429 // Compute the angle between those to vectors.
1430 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1431 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1432
1433 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1434 // TODO: add 'efficiency'.
1435 differenceAngle /= m_verticalAttractionTimescale;
1436
1437 // Create the quaterian representing the correction angle
1438 Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
1439
1440 // Turn that quaternion into Euler values to make it into velocities to apply.
1441 Vector3 vertContributionV = Vector3.Zero;
1442 correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
1443 vertContributionV *= -1f;
1444
1445 VehicleRotationalVelocity += vertContributionV;
1446
1447 VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
1448 ControllingPrim.LocalID,
1449 differenceAxis,
1450 differenceAngle,
1451 correctionRotation,
1452 vertContributionV);
1453 */
1454
1455 // ===================================================================
1456 /*
1457 Vector3 vertContributionV = Vector3.Zero;
1458 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1459
1460 // Take a vector pointing up and convert it from world to vehicle relative coords.
1461 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1462
1463 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1464 // is now:
1465 // leaning to one side: rotated around the X axis with the Y value going
1466 // from zero (nearly straight up) to one (completely to the side)) or
1467 // leaning front-to-back: rotated around the Y axis with the value of X being between
1468 // zero and one.
1469 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1470
1471 // Y error means needed rotation around X axis and visa versa.
1472 // Since the error goes from zero to one, the asin is the corresponding angle.
1473 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1474 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1475 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1476
1477 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1478 if (verticalError.Z < 0f)
1479 { 1391 {
1480 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; 1392 case 0:
1481 // vertContribution.Y -= PIOverFour; 1393 {
1394 //Another formula to try got from :
1395 //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
1396
1397 // Flipping what was originally a timescale into a speed variable and then multiplying it by 2
1398 // since only computing half the distance between the angles.
1399 float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
1400
1401 // Make a prediction of where the up axis will be when this is applied rather then where it is now as
1402 // this makes for a smoother adjustment and less fighting between the various forces.
1403 Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1404
1405 // This is only half the distance to the target so it will take 2 seconds to complete the turn.
1406 Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
1407
1408 // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
1409 Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed;
1410
1411 VehicleRotationalVelocity += vertContributionV;
1412
1413 VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},PredictedUp={2},torqueVector={3},contrib={4}",
1414 ControllingPrim.LocalID,
1415 vehicleUpAxis,
1416 predictedUp,
1417 torqueVector,
1418 vertContributionV);
1419 break;
1420 }
1421 case 1:
1422 {
1423 // Possible solution derived from a discussion at:
1424 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1425
1426 // Create a rotation that is only the vehicle's rotation around Z
1427 Vector3 currentEuler = Vector3.Zero;
1428 VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
1429 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
1430
1431 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1432 Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1433 // Compute the angle between those to vectors.
1434 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1435 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1436
1437 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1438 // TODO: add 'efficiency'.
1439 differenceAngle /= m_verticalAttractionTimescale;
1440
1441 // Create the quaterian representing the correction angle
1442 Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
1443
1444 // Turn that quaternion into Euler values to make it into velocities to apply.
1445 Vector3 vertContributionV = Vector3.Zero;
1446 correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
1447 vertContributionV *= -1f;
1448
1449 VehicleRotationalVelocity += vertContributionV;
1450
1451 VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
1452 ControllingPrim.LocalID,
1453 vehicleUpAxis,
1454 differenceAxis,
1455 differenceAngle,
1456 correctionRotation,
1457 vertContributionV);
1458 break;
1459 }
1460 case 2:
1461 {
1462 Vector3 vertContributionV = Vector3.Zero;
1463 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1464
1465 // Take a vector pointing up and convert it from world to vehicle relative coords.
1466 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1467
1468 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1469 // is now:
1470 // leaning to one side: rotated around the X axis with the Y value going
1471 // from zero (nearly straight up) to one (completely to the side)) or
1472 // leaning front-to-back: rotated around the Y axis with the value of X being between
1473 // zero and one.
1474 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1475
1476 // Y error means needed rotation around X axis and visa versa.
1477 // Since the error goes from zero to one, the asin is the corresponding angle.
1478 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1479 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1480 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1481
1482 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1483 if (verticalError.Z < 0f)
1484 {
1485 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour;
1486 // vertContribution.Y -= PIOverFour;
1487 }
1488
1489 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1490 // Correction happens over a number of seconds.
1491 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1492
1493 // The correction happens over the user's time period
1494 vertContributionV /= m_verticalAttractionTimescale;
1495
1496 // Rotate the vehicle rotation to the world coordinates.
1497 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1498
1499 VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}",
1500 ControllingPrim.LocalID,
1501 vehicleUpAxis,
1502 origRotVelW,
1503 verticalError,
1504 unscaledContribVerticalErrorV,
1505 m_verticalAttractionEfficiency,
1506 m_verticalAttractionTimescale,
1507 vertContributionV);
1508 break;
1509 }
1510 default:
1511 {
1512 break;
1513 }
1482 } 1514 }
1483
1484 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1485 // Correction happens over a number of seconds.
1486 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1487
1488 // The correction happens over the user's time period
1489 vertContributionV /= m_verticalAttractionTimescale;
1490
1491 // Rotate the vehicle rotation to the world coordinates.
1492 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1493
1494 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1495 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1496 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1497 */
1498 } 1515 }
1499 } 1516 }
1500 1517
@@ -1504,13 +1521,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1504 // in that direction. 1521 // in that direction.
1505 // TODO: implement reference frame. 1522 // TODO: implement reference frame.
1506 public void ComputeAngularDeflection() 1523 public void ComputeAngularDeflection()
1507 { 1524 {
1508 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1509 // approximately the same X or Y correction. When added together (when contributions are combined)
1510 // this creates an over-correction and then wabbling as the target is overshot.
1511 // TODO: rethink how the different correction computations inter-relate.
1512 1525
1513 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) 1526 if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1514 { 1527 {
1515 Vector3 deflectContributionV = Vector3.Zero; 1528 Vector3 deflectContributionV = Vector3.Zero;
1516 1529
@@ -1523,10 +1536,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1523 1536
1524 // The direction the vehicle is pointing 1537 // The direction the vehicle is pointing
1525 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1538 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1526 pointingDirection.Normalize(); 1539 //Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep
1540 // from overshooting and allow this correction to merge with the Vertical Attraction peacefully.
1541 Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1542 predictedPointingDirection.Normalize();
1527 1543
1528 // The difference between what is and what should be. 1544 // The difference between what is and what should be.
1529 Vector3 deflectionError = movingDirection - pointingDirection; 1545 // Vector3 deflectionError = movingDirection - predictedPointingDirection;
1546 Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection);
1530 1547
1531 // Don't try to correct very large errors (not our job) 1548 // Don't try to correct very large errors (not our job)
1532 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); 1549 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
@@ -1539,15 +1556,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1539 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); 1556 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1540 1557
1541 // Scale the correction by recovery timescale and efficiency 1558 // Scale the correction by recovery timescale and efficiency
1542 deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; 1559 // Not modeling a spring so clamp the scale to no more then the arc
1543 deflectContributionV /= m_angularDeflectionTimescale; 1560 deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f);
1544 1561 //deflectContributionV /= m_angularDeflectionTimescale;
1545 VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1546 1562
1563 // VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1564 VehicleRotationalVelocity += deflectContributionV;
1547 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1565 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1548 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); 1566 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
1549 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", 1567 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}",
1550 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); 1568 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection);
1551 } 1569 }
1552 } 1570 }
1553 1571
@@ -1584,7 +1602,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1584 // make a sluggish vehicle by giving it a timescale of several seconds. 1602 // make a sluggish vehicle by giving it a timescale of several seconds.
1585 public void ComputeAngularBanking() 1603 public void ComputeAngularBanking()
1586 { 1604 {
1587 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1605 if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1588 { 1606 {
1589 Vector3 bankingContributionV = Vector3.Zero; 1607 Vector3 bankingContributionV = Vector3.Zero;
1590 1608