aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorRobert Adams2012-12-06 09:24:24 -0800
committerRobert Adams2012-12-06 09:31:12 -0800
commit7fd8202ae3fbe5627396f34dfc03e3571f4f9fe4 (patch)
treeb8f76f88c8b5e9eb6710ccc3f79f57743cef5efc
parentBulletSim: update and add to the TODO list. (diff)
downloadopensim-SC_OLD-7fd8202ae3fbe5627396f34dfc03e3571f4f9fe4.zip
opensim-SC_OLD-7fd8202ae3fbe5627396f34dfc03e3571f4f9fe4.tar.gz
opensim-SC_OLD-7fd8202ae3fbe5627396f34dfc03e3571f4f9fe4.tar.bz2
opensim-SC_OLD-7fd8202ae3fbe5627396f34dfc03e3571f4f9fe4.tar.xz
BulletSim: rewrite and improve vehicle angularDeflection, verticalAttraction,
linearMotorUp and related vehicle forces. Fixed problems with downward vehicle position correction forces being too large. Add vehicle collision flag so can sense whether vehicle is on the ground.
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs212
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs1
2 files changed, 130 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
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index a5acfd1..2671995 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -360,6 +360,7 @@ public enum CollisionFlags : uint
360 // Following used by BulletSim to control collisions and updates 360 // Following used by BulletSim to control collisions and updates
361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
362 BS_FLOATS_ON_WATER = 1 << 11, 362 BS_FLOATS_ON_WATER = 1 << 11,
363 BS_VEHICLE_COLLISIONS = 1 << 12,
363 BS_NONE = 0, 364 BS_NONE = 0,
364 BS_ALL = 0xFFFFFFFF, 365 BS_ALL = 0xFFFFFFFF,
365 366