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.cs212
1 files changed, 129 insertions, 83 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 09aee17..fa3110c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -24,21 +24,10 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * 26 *
27 27 * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to 28 * are Copyright (c) 2009 Linden Research, Inc and are used under their license
29 * call the BulletSim system. 29 * of Creative Commons Attribution-Share Alike 3.0
30 */ 30 * (http://creativecommons.org/licenses/by-sa/3.0/).
31/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
32 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
33 * ODEPrim.cs contains methods dealing with Prim editing, Prim
34 * characteristics and Kinetic motion.
35 * ODEDynamics.cs contains methods dealing with Prim Physical motion
36 * (dynamics) and the associated settings. Old Linear and angular
37 * motors for dynamic motion have been replace with MoveLinear()
38 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
39 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
40 * switch between 'VEHICLE' parameter use and general dynamics
41 * settings use.
42 */ 31 */
43 32
44using System; 33using System;
@@ -111,7 +100,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
111 private float m_bankingEfficiency = 0; 100 private float m_bankingEfficiency = 0;
112 private float m_bankingMix = 0; 101 private float m_bankingMix = 0;
113 private float m_bankingTimescale = 0; 102 private float m_bankingTimescale = 0;
114 private Vector3 m_lastBanking = Vector3.Zero;
115 103
116 //Hover and Buoyancy properties 104 //Hover and Buoyancy properties
117 private float m_VhoverHeight = 0f; 105 private float m_VhoverHeight = 0f;
@@ -125,8 +113,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
125 113
126 //Attractor properties 114 //Attractor properties
127 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); 115 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
128 private float m_verticalAttractionEfficiency = 1.0f; // damped 116 private float m_verticalAttractionEfficiency = 1.0f; // damped
129 private float m_verticalAttractionTimescale = 600f; // Timescale > 500 means no vert attractor. 117 private float m_verticalAttractionCutoff = 500f; // per the documentation
118 // Timescale > cutoff means no vert attractor.
119 private float m_verticalAttractionTimescale = 510f;
130 120
131 public BSDynamics(BSScene myScene, BSPrim myPrim) 121 public BSDynamics(BSScene myScene, BSPrim myPrim)
132 { 122 {
@@ -329,7 +319,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
329 m_bankingEfficiency = 0; 319 m_bankingEfficiency = 0;
330 m_bankingTimescale = 1000; 320 m_bankingTimescale = 1000;
331 m_bankingMix = 1; 321 m_bankingMix = 1;
332 m_lastBanking = Vector3.Zero;
333 322
334 m_referenceFrame = Quaternion.Identity; 323 m_referenceFrame = Quaternion.Identity;
335 m_flags = (VehicleFlag)0; 324 m_flags = (VehicleFlag)0;
@@ -364,7 +353,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
364 m_bankingEfficiency = 0; 353 m_bankingEfficiency = 0;
365 m_bankingTimescale = 10; 354 m_bankingTimescale = 10;
366 m_bankingMix = 1; 355 m_bankingMix = 1;
367 m_lastBanking = Vector3.Zero;
368 356
369 m_referenceFrame = Quaternion.Identity; 357 m_referenceFrame = Quaternion.Identity;
370 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 358 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -374,6 +362,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
374 m_flags |= (VehicleFlag.NO_DEFLECTION_UP 362 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
375 | VehicleFlag.LIMIT_ROLL_ONLY 363 | VehicleFlag.LIMIT_ROLL_ONLY
376 | VehicleFlag.LIMIT_MOTOR_UP); 364 | VehicleFlag.LIMIT_MOTOR_UP);
365
377 break; 366 break;
378 case Vehicle.TYPE_CAR: 367 case Vehicle.TYPE_CAR:
379 m_linearMotorDirection = Vector3.Zero; 368 m_linearMotorDirection = Vector3.Zero;
@@ -403,7 +392,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
403 m_bankingEfficiency = -0.2f; 392 m_bankingEfficiency = -0.2f;
404 m_bankingMix = 1; 393 m_bankingMix = 1;
405 m_bankingTimescale = 1; 394 m_bankingTimescale = 1;
406 m_lastBanking = Vector3.Zero;
407 395
408 m_referenceFrame = Quaternion.Identity; 396 m_referenceFrame = Quaternion.Identity;
409 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 397 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -442,7 +430,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
442 m_bankingEfficiency = -0.3f; 430 m_bankingEfficiency = -0.3f;
443 m_bankingMix = 0.8f; 431 m_bankingMix = 0.8f;
444 m_bankingTimescale = 1; 432 m_bankingTimescale = 1;
445 m_lastBanking = Vector3.Zero;
446 433
447 m_referenceFrame = Quaternion.Identity; 434 m_referenceFrame = Quaternion.Identity;
448 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY 435 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
@@ -481,7 +468,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
481 m_bankingEfficiency = 1; 468 m_bankingEfficiency = 1;
482 m_bankingMix = 0.7f; 469 m_bankingMix = 0.7f;
483 m_bankingTimescale = 2; 470 m_bankingTimescale = 2;
484 m_lastBanking = Vector3.Zero;
485 471
486 m_referenceFrame = Quaternion.Identity; 472 m_referenceFrame = Quaternion.Identity;
487 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 473 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -520,7 +506,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
520 m_bankingEfficiency = 0; 506 m_bankingEfficiency = 0;
521 m_bankingMix = 0.7f; 507 m_bankingMix = 0.7f;
522 m_bankingTimescale = 5; 508 m_bankingTimescale = 5;
523 m_lastBanking = Vector3.Zero;
524 509
525 m_referenceFrame = Quaternion.Identity; 510 m_referenceFrame = Quaternion.Identity;
526 511
@@ -554,8 +539,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
554 // Z goes away and we keep X and Y 539 // Z goes away and we keep X and Y
555 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); 540 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
556 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 541 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
557
558 // m_bankingMotor = new BSVMotor("BankingMotor", ...);
559 } 542 }
560 543
561 // Some of the properties of this prim may have changed. 544 // Some of the properties of this prim may have changed.
@@ -577,15 +560,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
577 float angularDamping = PhysicsScene.Params.vehicleAngularDamping; 560 float angularDamping = PhysicsScene.Params.vehicleAngularDamping;
578 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); 561 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
579 562
563 // Vehicles report collision events so we know when it's on the ground
564 BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
565
580 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet 566 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
581 // Vector3 localInertia = new Vector3(1f, 1f, 1f); 567 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
582 Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass); 568 // Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
569 Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass);
583 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); 570 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
584 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); 571 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
585 572
586 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", 573 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
587 Prim.LocalID, friction, localInertia, angularDamping); 574 Prim.LocalID, friction, localInertia, angularDamping);
588 } 575 }
576 else
577 {
578 BulletSimAPI.RemoveFromCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS);
579 }
589 } 580 }
590 581
591 public bool RemoveBodyDependencies(BSPhysObject prim) 582 public bool RemoveBodyDependencies(BSPhysObject prim)
@@ -618,10 +609,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
618 private float? m_knownWaterLevel; 609 private float? m_knownWaterLevel;
619 private Vector3? m_knownPosition; 610 private Vector3? m_knownPosition;
620 private Vector3? m_knownVelocity; 611 private Vector3? m_knownVelocity;
621 private Vector3? m_knownForce; 612 private Vector3 m_knownForce;
622 private Quaternion? m_knownOrientation; 613 private Quaternion? m_knownOrientation;
623 private Vector3? m_knownRotationalVelocity; 614 private Vector3? m_knownRotationalVelocity;
624 private Vector3? m_knownRotationalForce; 615 private Vector3 m_knownRotationalForce;
616 private float? m_knownForwardSpeed;
625 617
626 private const int m_knownChangedPosition = 1 << 0; 618 private const int m_knownChangedPosition = 1 << 0;
627 private const int m_knownChangedVelocity = 1 << 1; 619 private const int m_knownChangedVelocity = 1 << 1;
@@ -636,10 +628,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
636 m_knownWaterLevel = null; 628 m_knownWaterLevel = null;
637 m_knownPosition = null; 629 m_knownPosition = null;
638 m_knownVelocity = null; 630 m_knownVelocity = null;
639 m_knownForce = null; 631 m_knownForce = Vector3.Zero;
640 m_knownOrientation = null; 632 m_knownOrientation = null;
641 m_knownRotationalVelocity = null; 633 m_knownRotationalVelocity = null;
642 m_knownRotationalForce = null; 634 m_knownRotationalForce = Vector3.Zero;
635 m_knownForwardSpeed = null;
643 m_knownChanged = 0; 636 m_knownChanged = 0;
644 } 637 }
645 private void PushKnownChanged() 638 private void PushKnownChanged()
@@ -761,6 +754,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
761 m_knownRotationalForce += aForce; 754 m_knownRotationalForce += aForce;
762 m_knownChanged |= m_knownChangedRotationalForce; 755 m_knownChanged |= m_knownChangedRotationalForce;
763 } 756 }
757 private float VehicleForwardSpeed
758 {
759 get
760 {
761 if (m_knownForwardSpeed == null)
762 m_knownForwardSpeed = (VehicleVelocity * Quaternion.Inverse(VehicleOrientation)).X;
763 return (float)m_knownForwardSpeed;
764 }
765 }
766
764 #endregion // Known vehicle value functions 767 #endregion // Known vehicle value functions
765 768
766 // One step of the vehicle properties for the next 'pTimestep' seconds. 769 // One step of the vehicle properties for the next 'pTimestep' seconds.
@@ -798,7 +801,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
798 // ================================================================== 801 // ==================================================================
799 // Buoyancy: force to overcome gravity. 802 // Buoyancy: force to overcome gravity.
800 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 803 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
801 Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * (m_VehicleBuoyancy - 1f); 804 // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity.
805 Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy;
802 806
803 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); 807 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
804 808
@@ -847,8 +851,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
847 VehicleAddForce(totalDownForce); 851 VehicleAddForce(totalDownForce);
848 } 852 }
849 853
850 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},linContrib={3},terrContrib={4},hoverContrib={5},limitContrib={6},buoyContrib={7}", 854 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}",
851 Prim.LocalID, newVelocity, totalDownForce, 855 Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding);
856 VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}",
857 Prim.LocalID,
852 linearMotorContribution, terrainHeightContribution, hoverContribution, 858 linearMotorContribution, terrainHeightContribution, hoverContribution,
853 limitMotorUpContribution, buoyancyContribution 859 limitMotorUpContribution, buoyancyContribution
854 ); 860 );
@@ -971,21 +977,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
971 } 977 }
972 978
973 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 979 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
974 // Prevent ground vehicles from motoring into the sky.This flag has a subtle effect when 980 // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when
975 // used with conjunction with banking: the strength of the banking will decay when the 981 // used with conjunction with banking: the strength of the banking will decay when the
976 // vehicle no longer experiences collisions. The decay timescale is the same as 982 // vehicle no longer experiences collisions. The decay timescale is the same as
977 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 983 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
978 // when they are in mid jump. 984 // when they are in mid jump.
979 // TODO: this code is wrong. Also, what should it do for boats? 985 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
986 // This is just using the ground and a general collision check. Should really be using
987 // a downward raycast to find what is below.
980 public Vector3 ComputeLinearMotorUp(float pTimestep) 988 public Vector3 ComputeLinearMotorUp(float pTimestep)
981 { 989 {
982 Vector3 ret = Vector3.Zero; 990 Vector3 ret = Vector3.Zero;
991
983 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 992 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
984 { 993 {
985 // If the vehicle is motoring into the sky, get it going back down. 994 // If the vehicle is motoring into the sky, get it going back down.
986 // float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos));
987 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition); 995 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
988 if (distanceAboveGround > 1f) 996 // Not colliding if the vehicle is off the ground
997 if (!Prim.IsColliding)
989 { 998 {
990 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); 999 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
991 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1000 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
@@ -1006,8 +1015,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1006 // ======================================================================= 1015 // =======================================================================
1007 // Apply the effect of the angular motor. 1016 // Apply the effect of the angular motor.
1008 // The 'contribution' is how much angular correction velocity each function wants. 1017 // The 'contribution' is how much angular correction velocity each function wants.
1009 // All the contributions are added together and the orientation of the vehicle 1018 // All the contributions are added together and the resulting velocity is
1010 // is changed by all the contributed corrections. 1019 // set directly on the vehicle.
1011 private void MoveAngular(float pTimestep) 1020 private void MoveAngular(float pTimestep)
1012 { 1021 {
1013 // The user wants how many radians per second angular change? 1022 // The user wants how many radians per second angular change?
@@ -1030,7 +1039,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1030 1039
1031 Vector3 deflectionContribution = ComputeAngularDeflection(); 1040 Vector3 deflectionContribution = ComputeAngularDeflection();
1032 1041
1033 Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z); 1042 Vector3 bankingContribution = ComputeAngularBanking();
1034 1043
1035 // ================================================================== 1044 // ==================================================================
1036 m_lastVertAttractor = verticalAttractionContribution; 1045 m_lastVertAttractor = verticalAttractionContribution;
@@ -1095,13 +1104,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1095 } 1104 }
1096 1105
1097 } 1106 }
1098 1107 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1108 // Some vehicles, like boats, should always keep their up-side up. This can be done by
1109 // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to
1110 // the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the
1111 // VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency,
1112 // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An
1113 // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an
1114 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
1099 public Vector3 ComputeAngularVerticalAttraction() 1115 public Vector3 ComputeAngularVerticalAttraction()
1100 { 1116 {
1101 Vector3 ret = Vector3.Zero; 1117 Vector3 ret = Vector3.Zero;
1102 1118
1103 // If vertical attaction timescale is reasonable and we applied an angular force last time... 1119 // If vertical attaction timescale is reasonable and we applied an angular force last time...
1104 if (m_verticalAttractionTimescale < 500) 1120 if (m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1105 { 1121 {
1106 // Take a vector pointing up and convert it from world to vehicle relative coords. 1122 // Take a vector pointing up and convert it from world to vehicle relative coords.
1107 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; 1123 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
@@ -1128,9 +1144,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1128 1144
1129 // Scale the correction force by how far we're off from vertical. 1145 // Scale the correction force by how far we're off from vertical.
1130 // Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over. 1146 // Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over.
1131 // float clampedZError = ClampInRange(0.1f, Math.Abs(verticalError.Z), 1f);
1132 float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f); 1147 float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f);
1133 // float vertForce = 1f / clampedSqrZError * m_verticalAttractionEfficiency;
1134 float vertForce = 1f / clampedSqrZError; 1148 float vertForce = 1f / clampedSqrZError;
1135 1149
1136 ret *= vertForce; 1150 ret *= vertForce;
@@ -1147,70 +1161,102 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1147 1161
1148 // Return the angular correction to correct the direction the vehicle is pointing to be 1162 // Return the angular correction to correct the direction the vehicle is pointing to be
1149 // the direction is should want to be pointing. 1163 // the direction is should want to be pointing.
1164 // The vehicle is moving in some direction and correct its orientation to it is pointing
1165 // in that direction.
1166 // TODO: implement reference frame.
1150 public Vector3 ComputeAngularDeflection() 1167 public Vector3 ComputeAngularDeflection()
1151 { 1168 {
1152 Vector3 ret = Vector3.Zero; 1169 Vector3 ret = Vector3.Zero;
1153 return ret; // DEBUG DEBUG DEBUG debug the other contributors first 1170 return ret; // DEBUG DEBUG DEBUG debug one force at a time
1154 1171
1155 if (m_angularDeflectionEfficiency != 0) 1172 if (m_angularDeflectionEfficiency != 0)
1156 { 1173 {
1157 // Where the vehicle should want to point relative to the vehicle 1174 // The direction the vehicle is moving
1158 Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame; 1175 Vector3 movingDirection = VehicleVelocity;
1176 movingDirection.Normalize();
1159 1177
1160 // Where the vehicle is pointing relative to the vehicle. 1178 // The direction the vehicle is pointing
1161 Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame); 1179 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1180 pointingDirection.Normalize();
1162 1181
1163 // Difference between where vehicle is pointing and where it should wish to point 1182 // The difference between what is and what should be
1164 Vector3 directionCorrection = preferredDirection - currentDirection; 1183 Vector3 deflectionError = movingDirection - pointingDirection;
1165 1184
1166 // Scale the correction by recovery timescale and efficiency 1185 // Scale the correction by recovery timescale and efficiency
1167 ret = directionCorrection * m_angularDeflectionEfficiency / m_angularDeflectionTimescale; 1186 ret = (-deflectionError * VehicleForwardSpeed) * m_angularDeflectionEfficiency;
1187 ret /= m_angularDeflectionTimescale;
1168 1188
1169 VDetailLog("{0}, MoveAngular,Deflection,perfDir={1},currentDir={2},dirCorrection={3},ret={4}", 1189 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1170 Prim.LocalID, preferredDirection, currentDirection, directionCorrection, ret); 1190 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret);
1171 } 1191 }
1172 return ret; 1192 return ret;
1173 } 1193 }
1174 1194
1175 // Return an angular change to tip the vehicle (around X axis) when turning (turned around Z). 1195 // Return an angular change to rotate the vehicle around the Z axis when the vehicle
1176 // Remembers the last banking value calculated and returns the difference needed this tick. 1196 // is tipped around the X axis.
1177 // TurningFactor is rate going left or right (pos=left, neg=right, scale=0..1). 1197 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1178 public Vector3 ComputeAngularBanking(float turningFactor) 1198 // The vertical attractor feature must be enabled in order for the banking behavior to
1199 // function. The way banking works is this: a rotation around the vehicle's roll-axis will
1200 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1201 // of the yaw effect will be proportional to the
1202 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1203 // velocity along its preferred axis of motion.
1204 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1205 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1206 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1207 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1208 // Negating the banking coefficient will make it so that the vehicle leans to the
1209 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1210 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1211 // banking vehicles do what you want rather than what the laws of physics allow.
1212 // For example, consider a real motorcycle...it must be moving forward in order for
1213 // it to turn while banking, however video-game motorcycles are often configured
1214 // to turn in place when at a dead stop--because they are often easier to control
1215 // that way using the limited interface of the keyboard or game controller. The
1216 // VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic
1217 // banking by functioning as a slider between a banking that is correspondingly
1218 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1219 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1220 // to "dynamic" where the banking is also proportional to its velocity along its
1221 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1222 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1223 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1224 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1225 // make a sluggish vehicle by giving it a timescale of several seconds.
1226 public Vector3 ComputeAngularBanking()
1179 { 1227 {
1180 Vector3 ret = Vector3.Zero; 1228 Vector3 ret = Vector3.Zero;
1181 Vector3 computedBanking = Vector3.Zero;
1182 return ret; // DEBUG DEBUG DEBUG debug the other contributors first
1183 1229
1184 if (m_bankingEfficiency != 0) 1230 if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1185 { 1231 {
1186 Vector3 currentDirection = Vector3.UnitX * VehicleOrientation; 1232 // This works by rotating a unit vector to the orientation of the vehicle. The
1187 1233 // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt
1188 float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); 1234 // up to one for full over).
1235 Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation;
1189 1236
1190 //Use the square of the efficiency, as it looks much more how SL banking works 1237 // Figure out the yaw value for this much roll.
1191 float effSquared = (m_bankingEfficiency * m_bankingEfficiency); 1238 float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency;
1192 if (m_bankingEfficiency < 0) 1239 // Keep the sign
1193 effSquared *= -1; //Keep the negative! 1240 if (rollComponents.Y < 0f)
1241 turnComponent = -turnComponent;
1194 1242
1195 float mix = Math.Abs(m_bankingMix); 1243 // TODO: there must be a better computation of the banking force.
1196 // TODO: Must include reference frame. 1244 float bankingTurnForce = turnComponent;
1197 float forwardSpeed = VehicleVelocity.X;
1198 1245
1199 if (!Prim.IsColliding && forwardSpeed > mix) 1246 // actual error = static turn error + dynamic turn error
1200 { 1247 float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed;
1201 computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f); 1248 // TODO: the banking effect should not go to infinity but what to limit it to?
1202 } 1249 mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f);
1203 1250
1204 // 'computedBanking' is now how much banking that should be happening. 1251 // Build the force vector to change rotation from what it is to what it should be
1205 ret = computedBanking - m_lastBanking; 1252 ret.Z = -mixedBankingError;
1206 1253
1207 // Scale the correction by timescale and efficiency 1254 // Don't do it all at once.
1208 ret /= m_bankingTimescale * m_bankingEfficiency; 1255 ret /= m_bankingTimescale;
1209 1256
1210 VDetailLog("{0}, MoveAngular,Banking,computedB={1},lastB={2},bEff={3},effSq={4},mult={5},mix={6},banking={7}", 1257 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}",
1211 Prim.LocalID, computedBanking, m_lastBanking, m_bankingEfficiency, effSquared, mult, mix, ret); 1258 Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret);
1212 } 1259 }
1213 m_lastBanking = computedBanking;
1214 return ret; 1260 return ret;
1215 } 1261 }
1216 1262