diff options
author | Robert Adams | 2012-12-06 09:24:24 -0800 |
---|---|---|
committer | Robert Adams | 2012-12-06 09:31:12 -0800 |
commit | 7fd8202ae3fbe5627396f34dfc03e3571f4f9fe4 (patch) | |
tree | b8f76f88c8b5e9eb6710ccc3f79f57743cef5efc /OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |
parent | BulletSim: update and add to the TODO list. (diff) | |
download | opensim-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.
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 | ||