diff options
author | Justin Clark-Casey (justincc) | 2012-12-07 00:53:47 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-12-07 00:53:47 +0000 |
commit | 4e622f6816b8ecc2d3ccba8ce69a2a65e2dc909b (patch) | |
tree | 1b6caf8b4ea59add539d889252953a0748675cc9 /OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |
parent | Use a thread abort safe version of OpenMetaverse.DoubleDictionary with the ai... (diff) | |
parent | BulletSim: update DLLs and SOs with vehicle collision event check (diff) | |
download | opensim-SC-4e622f6816b8ecc2d3ccba8ce69a2a65e2dc909b.zip opensim-SC-4e622f6816b8ecc2d3ccba8ce69a2a65e2dc909b.tar.gz opensim-SC-4e622f6816b8ecc2d3ccba8ce69a2a65e2dc909b.tar.bz2 opensim-SC-4e622f6816b8ecc2d3ccba8ce69a2a65e2dc909b.tar.xz |
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 287 |
1 files changed, 181 insertions, 106 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index be8a502..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,13 +609,18 @@ 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; |
612 | private Vector3 m_knownForce; | ||
621 | private Quaternion? m_knownOrientation; | 613 | private Quaternion? m_knownOrientation; |
622 | private Vector3? m_knownRotationalVelocity; | 614 | private Vector3? m_knownRotationalVelocity; |
615 | private Vector3 m_knownRotationalForce; | ||
616 | private float? m_knownForwardSpeed; | ||
623 | 617 | ||
624 | private const int m_knownChangedPosition = 1 << 0; | 618 | private const int m_knownChangedPosition = 1 << 0; |
625 | private const int m_knownChangedVelocity = 1 << 1; | 619 | private const int m_knownChangedVelocity = 1 << 1; |
626 | private const int m_knownChangedOrientation = 1 << 2; | 620 | private const int m_knownChangedForce = 1 << 2; |
627 | private const int m_knownChangedRotationalVelocity = 1 << 3; | 621 | private const int m_knownChangedOrientation = 1 << 3; |
622 | private const int m_knownChangedRotationalVelocity = 1 << 4; | ||
623 | private const int m_knownChangedRotationalForce = 1 << 5; | ||
628 | 624 | ||
629 | private void ForgetKnownVehicleProperties() | 625 | private void ForgetKnownVehicleProperties() |
630 | { | 626 | { |
@@ -632,8 +628,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
632 | m_knownWaterLevel = null; | 628 | m_knownWaterLevel = null; |
633 | m_knownPosition = null; | 629 | m_knownPosition = null; |
634 | m_knownVelocity = null; | 630 | m_knownVelocity = null; |
631 | m_knownForce = Vector3.Zero; | ||
635 | m_knownOrientation = null; | 632 | m_knownOrientation = null; |
636 | m_knownRotationalVelocity = null; | 633 | m_knownRotationalVelocity = null; |
634 | m_knownRotationalForce = Vector3.Zero; | ||
635 | m_knownForwardSpeed = null; | ||
637 | m_knownChanged = 0; | 636 | m_knownChanged = 0; |
638 | } | 637 | } |
639 | private void PushKnownChanged() | 638 | private void PushKnownChanged() |
@@ -645,12 +644,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
645 | if ((m_knownChanged & m_knownChangedOrientation) != 0) | 644 | if ((m_knownChanged & m_knownChangedOrientation) != 0) |
646 | Prim.ForceOrientation = VehicleOrientation; | 645 | Prim.ForceOrientation = VehicleOrientation; |
647 | if ((m_knownChanged & m_knownChangedVelocity) != 0) | 646 | if ((m_knownChanged & m_knownChangedVelocity) != 0) |
647 | { | ||
648 | Prim.ForceVelocity = VehicleVelocity; | 648 | Prim.ForceVelocity = VehicleVelocity; |
649 | BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity); | ||
650 | } | ||
651 | if ((m_knownChanged & m_knownChangedForce) != 0) | ||
652 | Prim.AddForce((Vector3)m_knownForce, false, true); | ||
653 | |||
649 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) | 654 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) |
650 | { | 655 | { |
651 | Prim.ForceRotationalVelocity = VehicleRotationalVelocity; | 656 | Prim.ForceRotationalVelocity = VehicleRotationalVelocity; |
657 | // Fake out Bullet by making it think the velocity is the same as last time. | ||
652 | BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity); | 658 | BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity); |
653 | } | 659 | } |
660 | if ((m_knownChanged & m_knownChangedRotationalForce) != 0) | ||
661 | Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); | ||
662 | |||
654 | // If we set one of the values (ie, the physics engine didn't do it) we must force | 663 | // If we set one of the values (ie, the physics engine didn't do it) we must force |
655 | // an UpdateProperties event to send the changes up to the simulator. | 664 | // an UpdateProperties event to send the changes up to the simulator. |
656 | BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); | 665 | BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); |
@@ -720,6 +729,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
720 | } | 729 | } |
721 | } | 730 | } |
722 | 731 | ||
732 | private void VehicleAddForce(Vector3 aForce) | ||
733 | { | ||
734 | m_knownForce += aForce; | ||
735 | m_knownChanged |= m_knownChangedForce; | ||
736 | } | ||
737 | |||
723 | private Vector3 VehicleRotationalVelocity | 738 | private Vector3 VehicleRotationalVelocity |
724 | { | 739 | { |
725 | get | 740 | get |
@@ -734,6 +749,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
734 | m_knownChanged |= m_knownChangedRotationalVelocity; | 749 | m_knownChanged |= m_knownChangedRotationalVelocity; |
735 | } | 750 | } |
736 | } | 751 | } |
752 | private void VehicleAddAngularForce(Vector3 aForce) | ||
753 | { | ||
754 | m_knownRotationalForce += aForce; | ||
755 | m_knownChanged |= m_knownChangedRotationalForce; | ||
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 | |||
737 | #endregion // Known vehicle value functions | 767 | #endregion // Known vehicle value functions |
738 | 768 | ||
739 | // One step of the vehicle properties for the next 'pTimestep' seconds. | 769 | // One step of the vehicle properties for the next 'pTimestep' seconds. |
@@ -769,10 +799,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
769 | linearMotorContribution *= VehicleOrientation; | 799 | linearMotorContribution *= VehicleOrientation; |
770 | 800 | ||
771 | // ================================================================== | 801 | // ================================================================== |
772 | // Gravity and Buoyancy | 802 | // Buoyancy: force to overcome gravity. |
773 | // There is some gravity, make a gravity force vector that is applied after object velocity. | ||
774 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 803 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
775 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); | 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; | ||
776 | 806 | ||
777 | Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); | 807 | Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); |
778 | 808 | ||
@@ -797,14 +827,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
797 | newVelocity.Z = 0; | 827 | newVelocity.Z = 0; |
798 | 828 | ||
799 | // ================================================================== | 829 | // ================================================================== |
800 | // Clamp REALLY high or low velocities | 830 | // Clamp high or low velocities |
801 | float newVelocityLengthSq = newVelocity.LengthSquared(); | 831 | float newVelocityLengthSq = newVelocity.LengthSquared(); |
802 | if (newVelocityLengthSq > 1e6f) | 832 | // if (newVelocityLengthSq > 1e6f) |
833 | if (newVelocityLengthSq > 1000f) | ||
803 | { | 834 | { |
804 | newVelocity /= newVelocity.Length(); | 835 | newVelocity /= newVelocity.Length(); |
805 | newVelocity *= 1000f; | 836 | newVelocity *= 1000f; |
806 | } | 837 | } |
807 | else if (newVelocityLengthSq < 1e-6f) | 838 | // else if (newVelocityLengthSq < 1e-6f) |
839 | else if (newVelocityLengthSq < 0.001f) | ||
808 | newVelocity = Vector3.Zero; | 840 | newVelocity = Vector3.Zero; |
809 | 841 | ||
810 | // ================================================================== | 842 | // ================================================================== |
@@ -813,15 +845,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
813 | VehicleVelocity = newVelocity; | 845 | VehicleVelocity = newVelocity; |
814 | 846 | ||
815 | // Other linear forces are applied as forces. | 847 | // Other linear forces are applied as forces. |
816 | Vector3 totalDownForce = grav * m_vehicleMass * pTimestep; | 848 | Vector3 totalDownForce = buoyancyContribution * m_vehicleMass; |
817 | if (totalDownForce != Vector3.Zero) | 849 | if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) |
818 | { | 850 | { |
819 | Prim.AddForce(totalDownForce, false); | 851 | VehicleAddForce(totalDownForce); |
820 | } | 852 | } |
821 | 853 | ||
822 | VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},linContrib={3},terrContrib={4},hoverContrib={5},limitContrib={6}", | 854 | VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}", |
823 | Prim.LocalID, newVelocity, totalDownForce, | 855 | Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding); |
824 | linearMotorContribution, terrainHeightContribution, hoverContribution, limitMotorUpContribution | 856 | VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}", |
857 | Prim.LocalID, | ||
858 | linearMotorContribution, terrainHeightContribution, hoverContribution, | ||
859 | limitMotorUpContribution, buoyancyContribution | ||
825 | ); | 860 | ); |
826 | 861 | ||
827 | } // end MoveLinear() | 862 | } // end MoveLinear() |
@@ -942,21 +977,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
942 | } | 977 | } |
943 | 978 | ||
944 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : | 979 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : |
945 | // 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 |
946 | // 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 |
947 | // 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 |
948 | // 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 |
949 | // when they are in mid jump. | 984 | // when they are in mid jump. |
950 | // 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. | ||
951 | public Vector3 ComputeLinearMotorUp(float pTimestep) | 988 | public Vector3 ComputeLinearMotorUp(float pTimestep) |
952 | { | 989 | { |
953 | Vector3 ret = Vector3.Zero; | 990 | Vector3 ret = Vector3.Zero; |
991 | |||
954 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 992 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
955 | { | 993 | { |
956 | // 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. |
957 | // float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos)); | ||
958 | float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition); | 995 | float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition); |
959 | if (distanceAboveGround > 1f) | 996 | // Not colliding if the vehicle is off the ground |
997 | if (!Prim.IsColliding) | ||
960 | { | 998 | { |
961 | // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); | 999 | // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); |
962 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); | 1000 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); |
@@ -977,8 +1015,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
977 | // ======================================================================= | 1015 | // ======================================================================= |
978 | // Apply the effect of the angular motor. | 1016 | // Apply the effect of the angular motor. |
979 | // The 'contribution' is how much angular correction velocity each function wants. | 1017 | // The 'contribution' is how much angular correction velocity each function wants. |
980 | // All the contributions are added together and the orientation of the vehicle | 1018 | // All the contributions are added together and the resulting velocity is |
981 | // is changed by all the contributed corrections. | 1019 | // set directly on the vehicle. |
982 | private void MoveAngular(float pTimestep) | 1020 | private void MoveAngular(float pTimestep) |
983 | { | 1021 | { |
984 | // The user wants how many radians per second angular change? | 1022 | // The user wants how many radians per second angular change? |
@@ -1001,7 +1039,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1001 | 1039 | ||
1002 | Vector3 deflectionContribution = ComputeAngularDeflection(); | 1040 | Vector3 deflectionContribution = ComputeAngularDeflection(); |
1003 | 1041 | ||
1004 | Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z); | 1042 | Vector3 bankingContribution = ComputeAngularBanking(); |
1005 | 1043 | ||
1006 | // ================================================================== | 1044 | // ================================================================== |
1007 | m_lastVertAttractor = verticalAttractionContribution; | 1045 | m_lastVertAttractor = verticalAttractionContribution; |
@@ -1013,11 +1051,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1013 | + bankingContribution; | 1051 | + bankingContribution; |
1014 | 1052 | ||
1015 | // ================================================================== | 1053 | // ================================================================== |
1016 | // The correction is applied to the current orientation. | 1054 | // Apply the correction velocity. |
1055 | // TODO: Should this be applied as an angular force (torque)? | ||
1017 | if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f)) | 1056 | if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f)) |
1018 | { | 1057 | { |
1019 | Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep; | 1058 | Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep; |
1020 | |||
1021 | VehicleRotationalVelocity = scaledCorrection; | 1059 | VehicleRotationalVelocity = scaledCorrection; |
1022 | 1060 | ||
1023 | VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}", | 1061 | VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}", |
@@ -1029,7 +1067,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1029 | } | 1067 | } |
1030 | else | 1068 | else |
1031 | { | 1069 | { |
1032 | // The vehicle is not adding anything velocity wise. | 1070 | // The vehicle is not adding anything angular wise. |
1033 | VehicleRotationalVelocity = Vector3.Zero; | 1071 | VehicleRotationalVelocity = Vector3.Zero; |
1034 | VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); | 1072 | VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); |
1035 | } | 1073 | } |
@@ -1060,19 +1098,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1060 | torqueFromOffset.Y = 0; | 1098 | torqueFromOffset.Y = 0; |
1061 | if (float.IsNaN(torqueFromOffset.Z)) | 1099 | if (float.IsNaN(torqueFromOffset.Z)) |
1062 | torqueFromOffset.Z = 0; | 1100 | torqueFromOffset.Z = 0; |
1063 | torqueFromOffset *= m_vehicleMass; | 1101 | |
1064 | Prim.ApplyTorqueImpulse(torqueFromOffset, true); | 1102 | VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); |
1065 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); | 1103 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); |
1066 | } | 1104 | } |
1067 | 1105 | ||
1068 | } | 1106 | } |
1069 | 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. | ||
1070 | public Vector3 ComputeAngularVerticalAttraction() | 1115 | public Vector3 ComputeAngularVerticalAttraction() |
1071 | { | 1116 | { |
1072 | Vector3 ret = Vector3.Zero; | 1117 | Vector3 ret = Vector3.Zero; |
1073 | 1118 | ||
1074 | // 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... |
1075 | if (m_verticalAttractionTimescale < 500) | 1120 | if (m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1076 | { | 1121 | { |
1077 | // 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. |
1078 | Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; | 1123 | Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; |
@@ -1097,91 +1142,121 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1097 | ret.Y = - verticalError.X; | 1142 | ret.Y = - verticalError.X; |
1098 | ret.Z = 0f; | 1143 | ret.Z = 0f; |
1099 | 1144 | ||
1100 | // scale by the time scale and timestep | 1145 | // Scale the correction force by how far we're off from vertical. |
1146 | // Z error of one says little error. As Z gets smaller, the vehicle is leaning farther over. | ||
1147 | float clampedSqrZError = ClampInRange(0.01f, verticalError.Z * verticalError.Z, 1f); | ||
1148 | float vertForce = 1f / clampedSqrZError; | ||
1149 | |||
1150 | ret *= vertForce; | ||
1151 | |||
1152 | // Correction happens over a number of seconds. | ||
1101 | Vector3 unscaledContrib = ret; | 1153 | Vector3 unscaledContrib = ret; |
1102 | ret /= m_verticalAttractionTimescale; | 1154 | ret /= m_verticalAttractionTimescale; |
1103 | // This returns the angular correction desired. Timestep is added later. | 1155 | |
1104 | // ret *= pTimestep; | 1156 | VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},vertForce={3},eff={4},vertAttr={5}", |
1105 | 1157 | Prim.LocalID, verticalError, unscaledContrib, vertForce, m_verticalAttractionEfficiency, ret); | |
1106 | // apply efficiency | ||
1107 | Vector3 preEfficiencyContrib = ret; | ||
1108 | // TODO: implement efficiency. | ||
1109 | // Effenciency squared seems to give a more realistic effect | ||
1110 | float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency; | ||
1111 | // ret *= efficencySquared; | ||
1112 | |||
1113 | VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}", | ||
1114 | Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib, | ||
1115 | m_verticalAttractionEfficiency, efficencySquared, | ||
1116 | ret); | ||
1117 | } | 1158 | } |
1118 | return ret; | 1159 | return ret; |
1119 | } | 1160 | } |
1120 | 1161 | ||
1121 | // 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 |
1122 | // 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. | ||
1123 | public Vector3 ComputeAngularDeflection() | 1167 | public Vector3 ComputeAngularDeflection() |
1124 | { | 1168 | { |
1125 | Vector3 ret = Vector3.Zero; | 1169 | Vector3 ret = Vector3.Zero; |
1170 | return ret; // DEBUG DEBUG DEBUG debug one force at a time | ||
1126 | 1171 | ||
1127 | if (m_angularDeflectionEfficiency != 0) | 1172 | if (m_angularDeflectionEfficiency != 0) |
1128 | { | 1173 | { |
1129 | // Where the vehicle should want to point relative to the vehicle | 1174 | // The direction the vehicle is moving |
1130 | Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame; | 1175 | Vector3 movingDirection = VehicleVelocity; |
1176 | movingDirection.Normalize(); | ||
1131 | 1177 | ||
1132 | // Where the vehicle is pointing relative to the vehicle. | 1178 | // The direction the vehicle is pointing |
1133 | Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame); | 1179 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; |
1180 | pointingDirection.Normalize(); | ||
1134 | 1181 | ||
1135 | // Difference between where vehicle is pointing and where it should wish to point | 1182 | // The difference between what is and what should be |
1136 | Vector3 directionCorrection = preferredDirection - currentDirection; | 1183 | Vector3 deflectionError = movingDirection - pointingDirection; |
1137 | 1184 | ||
1138 | // Scale the correction by recovery timescale and efficiency | 1185 | // Scale the correction by recovery timescale and efficiency |
1139 | ret = directionCorrection * m_angularDeflectionEfficiency / m_angularDeflectionTimescale; | 1186 | ret = (-deflectionError * VehicleForwardSpeed) * m_angularDeflectionEfficiency; |
1187 | ret /= m_angularDeflectionTimescale; | ||
1140 | 1188 | ||
1141 | 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}", |
1142 | Prim.LocalID, preferredDirection, currentDirection, directionCorrection, ret); | 1190 | Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); |
1143 | } | 1191 | } |
1144 | return ret; | 1192 | return ret; |
1145 | } | 1193 | } |
1146 | 1194 | ||
1147 | // 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 |
1148 | // Remembers the last banking value calculated and returns the difference needed this tick. | 1196 | // is tipped around the X axis. |
1149 | // TurningFactor is rate going left or right (pos=left, neg=right, scale=0..1). | 1197 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: |
1150 | 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() | ||
1151 | { | 1227 | { |
1152 | Vector3 ret = Vector3.Zero; | 1228 | Vector3 ret = Vector3.Zero; |
1153 | Vector3 computedBanking = Vector3.Zero; | ||
1154 | 1229 | ||
1155 | if (m_bankingEfficiency != 0) | 1230 | if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1156 | { | 1231 | { |
1157 | Vector3 currentDirection = Vector3.UnitX * VehicleOrientation; | 1232 | // This works by rotating a unit vector to the orientation of the vehicle. The |
1158 | 1233 | // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt | |
1159 | 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; | ||
1160 | 1236 | ||
1161 | //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. |
1162 | float effSquared = (m_bankingEfficiency * m_bankingEfficiency); | 1238 | float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency; |
1163 | if (m_bankingEfficiency < 0) | 1239 | // Keep the sign |
1164 | effSquared *= -1; //Keep the negative! | 1240 | if (rollComponents.Y < 0f) |
1241 | turnComponent = -turnComponent; | ||
1165 | 1242 | ||
1166 | float mix = Math.Abs(m_bankingMix); | 1243 | // TODO: there must be a better computation of the banking force. |
1167 | // TODO: Must include reference frame. | 1244 | float bankingTurnForce = turnComponent; |
1168 | float forwardSpeed = VehicleVelocity.X; | ||
1169 | 1245 | ||
1170 | if (!Prim.IsColliding && forwardSpeed > mix) | 1246 | // actual error = static turn error + dynamic turn error |
1171 | { | 1247 | float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed; |
1172 | computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f); | 1248 | // TODO: the banking effect should not go to infinity but what to limit it to? |
1173 | } | 1249 | mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f); |
1174 | 1250 | ||
1175 | // '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 |
1176 | ret = computedBanking - m_lastBanking; | 1252 | ret.Z = -mixedBankingError; |
1177 | 1253 | ||
1178 | // Scale the correction by timescale and efficiency | 1254 | // Don't do it all at once. |
1179 | ret /= m_bankingTimescale * m_bankingEfficiency; | 1255 | ret /= m_bankingTimescale; |
1180 | 1256 | ||
1181 | 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}", |
1182 | Prim.LocalID, computedBanking, m_lastBanking, m_bankingEfficiency, effSquared, mult, mix, ret); | 1258 | Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret); |
1183 | } | 1259 | } |
1184 | m_lastBanking = computedBanking; | ||
1185 | return ret; | 1260 | return ret; |
1186 | } | 1261 | } |
1187 | 1262 | ||