diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 212 |
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 | ||
44 | using System; | 33 | using 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 | ||