diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 439 |
1 files changed, 250 insertions, 189 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 6ff8a48..74eb9ab 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -125,6 +125,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
125 | // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. | 125 | // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. |
126 | 126 | ||
127 | //Attractor properties | 127 | //Attractor properties |
128 | private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); | ||
128 | private float m_verticalAttractionEfficiency = 1.0f; // damped | 129 | private float m_verticalAttractionEfficiency = 1.0f; // damped |
129 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. | 130 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. |
130 | 131 | ||
@@ -197,9 +198,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
197 | break; | 198 | break; |
198 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: | 199 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: |
199 | m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); | 200 | m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); |
201 | m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency; | ||
200 | break; | 202 | break; |
201 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: | 203 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: |
202 | m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); | 204 | m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); |
205 | m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale; | ||
203 | break; | 206 | break; |
204 | 207 | ||
205 | // These are vector properties but the engine lets you use a single float value to | 208 | // These are vector properties but the engine lets you use a single float value to |
@@ -314,7 +317,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
314 | m_VhoverEfficiency = 0; | 317 | m_VhoverEfficiency = 0; |
315 | m_VhoverTimescale = 0; | 318 | m_VhoverTimescale = 0; |
316 | m_VehicleBuoyancy = 0; | 319 | m_VehicleBuoyancy = 0; |
317 | 320 | ||
318 | m_linearDeflectionEfficiency = 1; | 321 | m_linearDeflectionEfficiency = 1; |
319 | m_linearDeflectionTimescale = 1; | 322 | m_linearDeflectionTimescale = 1; |
320 | 323 | ||
@@ -363,8 +366,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
363 | m_bankingMix = 1; | 366 | m_bankingMix = 1; |
364 | 367 | ||
365 | m_referenceFrame = Quaternion.Identity; | 368 | m_referenceFrame = Quaternion.Identity; |
366 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | 369 | m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
367 | | VehicleFlag.HOVER_TERRAIN_ONLY | 370 | | VehicleFlag.HOVER_TERRAIN_ONLY |
368 | | VehicleFlag.HOVER_GLOBAL_HEIGHT | 371 | | VehicleFlag.HOVER_GLOBAL_HEIGHT |
369 | | VehicleFlag.HOVER_UP_ONLY); | 372 | | VehicleFlag.HOVER_UP_ONLY); |
370 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | 373 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
@@ -530,12 +533,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
530 | Refresh(); | 533 | Refresh(); |
531 | 534 | ||
532 | m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, | 535 | m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, |
533 | m_linearMotorDecayTimescale, m_linearFrictionTimescale, 1f); | 536 | m_linearMotorDecayTimescale, m_linearFrictionTimescale, |
537 | 1f); | ||
534 | m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | 538 | m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
539 | |||
535 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, | 540 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, |
536 | m_angularMotorDecayTimescale, m_angularFrictionTimescale, 1f); | 541 | m_angularMotorDecayTimescale, m_angularFrictionTimescale, |
542 | 1f); | ||
537 | m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | 543 | m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
538 | 544 | ||
545 | m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, | ||
546 | BSMotor.Infinite, BSMotor.InfiniteVector, | ||
547 | m_verticalAttractionEfficiency); | ||
548 | // Z goes away and we keep X and Y | ||
549 | m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); | ||
550 | m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | ||
551 | |||
539 | // m_bankingMotor = new BSVMotor("BankingMotor", ...); | 552 | // m_bankingMotor = new BSVMotor("BankingMotor", ...); |
540 | } | 553 | } |
541 | 554 | ||
@@ -562,7 +575,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
562 | Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass); | 575 | Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass); |
563 | BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); | 576 | BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); |
564 | 577 | ||
565 | VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", | 578 | VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", |
566 | Prim.LocalID, friction, localInertia, angularDamping); | 579 | Prim.LocalID, friction, localInertia, angularDamping); |
567 | } | 580 | } |
568 | } | 581 | } |
@@ -617,13 +630,64 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
617 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 630 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
618 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); | 631 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); |
619 | 632 | ||
620 | // Current vehicle position | ||
621 | Vector3 pos = Prim.ForcePosition; | 633 | Vector3 pos = Prim.ForcePosition; |
634 | float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | ||
635 | |||
636 | Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep, ref pos, terrainHeight); | ||
637 | |||
638 | Vector3 hoverContribution = ComputeLinearHover(pTimestep, ref pos, terrainHeight); | ||
639 | |||
640 | ComputeLinearBlockingEndPoint(pTimestep, ref pos); | ||
641 | |||
642 | Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep, pos, terrainHeight); | ||
643 | |||
644 | // ================================================================== | ||
645 | Vector3 newVelocity = linearMotorContribution | ||
646 | + terrainHeightContribution | ||
647 | + hoverContribution | ||
648 | + limitMotorUpContribution; | ||
649 | |||
650 | // If not changing some axis, reduce out velocity | ||
651 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | ||
652 | newVelocity.X = 0; | ||
653 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | ||
654 | newVelocity.Y = 0; | ||
655 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | ||
656 | newVelocity.Z = 0; | ||
622 | 657 | ||
623 | // ================================================================== | 658 | // ================================================================== |
624 | Vector3 terrainHeightContribution = Vector3.Zero; | 659 | // Clamp REALLY high or low velocities |
660 | float newVelocityLengthSq = newVelocity.LengthSquared(); | ||
661 | if (newVelocityLengthSq > 1e6f) | ||
662 | { | ||
663 | newVelocity /= newVelocity.Length(); | ||
664 | newVelocity *= 1000f; | ||
665 | } | ||
666 | else if (newVelocityLengthSq < 1e-6f) | ||
667 | newVelocity = Vector3.Zero; | ||
668 | |||
669 | // ================================================================== | ||
670 | // Stuff new linear velocity into the vehicle | ||
671 | Prim.ForceVelocity = newVelocity; | ||
672 | // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG | ||
673 | |||
674 | // Other linear forces are applied as forces. | ||
675 | Vector3 totalDownForce = grav * m_vehicleMass; | ||
676 | if (totalDownForce != Vector3.Zero) | ||
677 | { | ||
678 | Prim.AddForce(totalDownForce, false); | ||
679 | } | ||
680 | |||
681 | VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}", | ||
682 | Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, | ||
683 | newVelocity, Prim.Velocity, totalDownForce); | ||
684 | |||
685 | } // end MoveLinear() | ||
686 | |||
687 | public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep, ref Vector3 pos, float terrainHeight) | ||
688 | { | ||
689 | Vector3 ret = Vector3.Zero; | ||
625 | // If below the terrain, move us above the ground a little. | 690 | // If below the terrain, move us above the ground a little. |
626 | float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | ||
627 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. | 691 | // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. |
628 | // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. | 692 | // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. |
629 | // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; | 693 | // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; |
@@ -635,10 +699,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
635 | Prim.ForcePosition = pos; | 699 | Prim.ForcePosition = pos; |
636 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); | 700 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); |
637 | } | 701 | } |
702 | return ret; | ||
703 | } | ||
704 | |||
705 | public Vector3 ComputeLinearHover(float pTimestep, ref Vector3 pos, float terrainHeight) | ||
706 | { | ||
707 | Vector3 ret = Vector3.Zero; | ||
638 | 708 | ||
639 | // ================================================================== | ||
640 | Vector3 hoverContribution = Vector3.Zero; | ||
641 | // Check if hovering | ||
642 | // m_VhoverEfficiency: 0=bouncy, 1=totally damped | 709 | // m_VhoverEfficiency: 0=bouncy, 1=totally damped |
643 | // m_VhoverTimescale: time to achieve height | 710 | // m_VhoverTimescale: time to achieve height |
644 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) | 711 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) |
@@ -679,24 +746,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
679 | // Replace Vertical speed with correction figure if significant | 746 | // Replace Vertical speed with correction figure if significant |
680 | if (verticalError > 0.01f) | 747 | if (verticalError > 0.01f) |
681 | { | 748 | { |
682 | hoverContribution = new Vector3(0f, 0f, verticalCorrectionVelocity); | 749 | ret = new Vector3(0f, 0f, verticalCorrectionVelocity); |
683 | //KF: m_VhoverEfficiency is not yet implemented | 750 | //KF: m_VhoverEfficiency is not yet implemented |
684 | } | 751 | } |
685 | else if (verticalError < -0.01) | 752 | else if (verticalError < -0.01) |
686 | { | 753 | { |
687 | hoverContribution = new Vector3(0f, 0f, -verticalCorrectionVelocity); | 754 | ret = new Vector3(0f, 0f, -verticalCorrectionVelocity); |
688 | } | 755 | } |
689 | } | 756 | } |
690 | 757 | ||
691 | VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", | 758 | VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", |
692 | Prim.LocalID, pos, hoverContribution, m_VhoverHeight, m_VhoverTargetHeight); | 759 | Prim.LocalID, pos, ret, m_VhoverHeight, m_VhoverTargetHeight); |
693 | } | 760 | } |
694 | 761 | ||
695 | // ================================================================== | 762 | return ret; |
763 | } | ||
764 | |||
765 | public bool ComputeLinearBlockingEndPoint(float pTimestep, ref Vector3 pos) | ||
766 | { | ||
767 | bool changed = false; | ||
768 | |||
696 | Vector3 posChange = pos - m_lastPositionVector; | 769 | Vector3 posChange = pos - m_lastPositionVector; |
697 | if (m_BlockingEndPoint != Vector3.Zero) | 770 | if (m_BlockingEndPoint != Vector3.Zero) |
698 | { | 771 | { |
699 | bool changed = false; | ||
700 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) | 772 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) |
701 | { | 773 | { |
702 | pos.X -= posChange.X + 1; | 774 | pos.X -= posChange.X + 1; |
@@ -729,9 +801,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
729 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); | 801 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); |
730 | } | 802 | } |
731 | } | 803 | } |
804 | return changed; | ||
805 | } | ||
732 | 806 | ||
733 | // ================================================================== | 807 | public Vector3 ComputeLinearMotorUp(float pTimestep, Vector3 pos, float terrainHeight) |
734 | Vector3 limitMotorUpContribution = Vector3.Zero; | 808 | { |
809 | Vector3 ret = Vector3.Zero; | ||
735 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 810 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
736 | { | 811 | { |
737 | // If the vehicle is motoring into the sky, get it going back down. | 812 | // If the vehicle is motoring into the sky, get it going back down. |
@@ -740,58 +815,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
740 | { | 815 | { |
741 | // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); | 816 | // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); |
742 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); | 817 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); |
743 | limitMotorUpContribution = new Vector3(0, 0, -distanceAboveGround); | 818 | ret = new Vector3(0, 0, -distanceAboveGround); |
744 | } | 819 | } |
745 | // TODO: this calculation is all wrong. From the description at | 820 | // TODO: this calculation is all wrong. From the description at |
746 | // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce | 821 | // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce |
747 | // has a decay factor. This says this force should | 822 | // has a decay factor. This says this force should |
748 | // be computed with a motor. | 823 | // be computed with a motor. |
749 | VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", | 824 | VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", |
750 | Prim.LocalID, distanceAboveGround, limitMotorUpContribution); | 825 | Prim.LocalID, distanceAboveGround, ret); |
751 | } | ||
752 | |||
753 | // ================================================================== | ||
754 | Vector3 newVelocity = linearMotorContribution | ||
755 | + terrainHeightContribution | ||
756 | + hoverContribution | ||
757 | + limitMotorUpContribution; | ||
758 | |||
759 | // If not changing some axis, reduce out velocity | ||
760 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | ||
761 | newVelocity.X = 0; | ||
762 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | ||
763 | newVelocity.Y = 0; | ||
764 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | ||
765 | newVelocity.Z = 0; | ||
766 | |||
767 | // ================================================================== | ||
768 | // Clamp REALLY high or low velocities | ||
769 | float newVelocityLengthSq = newVelocity.LengthSquared(); | ||
770 | if (newVelocityLengthSq > 1e6f) | ||
771 | { | ||
772 | newVelocity /= newVelocity.Length(); | ||
773 | newVelocity *= 1000f; | ||
774 | } | 826 | } |
775 | else if (newVelocityLengthSq < 1e-6f) | 827 | return ret; |
776 | newVelocity = Vector3.Zero; | 828 | } |
777 | |||
778 | // ================================================================== | ||
779 | // Stuff new linear velocity into the vehicle | ||
780 | Prim.ForceVelocity = newVelocity; | ||
781 | // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG | ||
782 | |||
783 | // Other linear forces are applied as forces. | ||
784 | Vector3 totalDownForce = grav * m_vehicleMass; | ||
785 | if (totalDownForce != Vector3.Zero) | ||
786 | { | ||
787 | Prim.AddForce(totalDownForce, false); | ||
788 | } | ||
789 | |||
790 | VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}", | ||
791 | Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, | ||
792 | newVelocity, Prim.Velocity, totalDownForce); | ||
793 | |||
794 | } // end MoveLinear() | ||
795 | 829 | ||
796 | // ======================================================================= | 830 | // ======================================================================= |
797 | // ======================================================================= | 831 | // ======================================================================= |
@@ -829,130 +863,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
829 | Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); | 863 | Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); |
830 | 864 | ||
831 | // ================================================================== | 865 | // ================================================================== |
832 | Vector3 verticalAttractionContribution = Vector3.Zero; | 866 | // NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement |
833 | // If vertical attaction timescale is reasonable and we applied an angular force last time... | 867 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) |
834 | if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) | ||
835 | { | ||
836 | float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; | ||
837 | if (Prim.IsColliding) | ||
838 | VAservo = pTimestep * 0.05f / m_verticalAttractionTimescale; | ||
839 | |||
840 | VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | ||
841 | |||
842 | // Create a vector of the vehicle "up" in world coordinates | ||
843 | Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; | ||
844 | // verticalError.X and .Y are the World error amounts. They are 0 when there is no | ||
845 | // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its | ||
846 | // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall | ||
847 | // and .Z will go negative. Similar for tilt and |.Y|. .X and .Y must be | ||
848 | // modulated to prevent a stable inverted body. | ||
849 | |||
850 | // Error is 0 (no error) to +/- 2 (max error) | ||
851 | verticalError.X = Math.Max(-2f, Math.Min(verticalError.X, 2f)); | ||
852 | verticalError.Y = Math.Max(-2f, Math.Min(verticalError.Y, 2f)); | ||
853 | |||
854 | // scale it by VAservo (timestep and timescale) | ||
855 | verticalError = verticalError * VAservo; | ||
856 | |||
857 | // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y | ||
858 | // then .X increases, so change Body angular velocity X based on Y, and Y based on X. | ||
859 | // Z is not changed. | ||
860 | verticalAttractionContribution.X = verticalError.Y; | ||
861 | verticalAttractionContribution.Y = - verticalError.X; | ||
862 | verticalAttractionContribution.Z = 0f; | ||
863 | |||
864 | // scaling appears better usingsquare-law | ||
865 | Vector3 angularVelocity = Prim.ForceRotationalVelocity; | ||
866 | float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | ||
867 | verticalAttractionContribution.X += bounce * angularVelocity.X; | ||
868 | verticalAttractionContribution.Y += bounce * angularVelocity.Y; | ||
869 | |||
870 | VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}", | ||
871 | Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, verticalAttractionContribution); | ||
872 | |||
873 | } | ||
874 | |||
875 | // ================================================================== | ||
876 | Vector3 deflectionContribution = Vector3.Zero; | ||
877 | if (m_angularDeflectionEfficiency != 0) | ||
878 | { | 868 | { |
879 | // Compute a scaled vector that points in the preferred axis (X direction) | 869 | angularMotorContribution.X = 0f; |
880 | Vector3 scaledDefaultDirection = | 870 | angularMotorContribution.Y = 0f; |
881 | new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); | 871 | VDetailLog("{0},MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); |
882 | // Adding the current vehicle orientation and reference frame displaces the orientation to the frame. | ||
883 | // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point. | ||
884 | Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); | ||
885 | |||
886 | // Scale by efficiency and timescale | ||
887 | deflectionContribution = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; | ||
888 | |||
889 | VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", | ||
890 | Prim.LocalID, preferredAxisOfMotion, deflectionContribution); | ||
891 | // This deflection computation is not correct. | ||
892 | deflectionContribution = Vector3.Zero; | ||
893 | } | 872 | } |
894 | 873 | ||
895 | // ================================================================== | 874 | Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(pTimestep); |
896 | Vector3 bankingContribution = Vector3.Zero; | ||
897 | if (m_bankingEfficiency != 0) | ||
898 | { | ||
899 | Vector3 dir = Vector3.One * Prim.ForceOrientation; | ||
900 | float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); | ||
901 | //Changes which way it banks in and out of turns | ||
902 | |||
903 | //Use the square of the efficiency, as it looks much more how SL banking works | ||
904 | float effSquared = (m_bankingEfficiency*m_bankingEfficiency); | ||
905 | if (m_bankingEfficiency < 0) | ||
906 | effSquared *= -1; //Keep the negative! | ||
907 | 875 | ||
908 | float mix = Math.Abs(m_bankingMix); | 876 | Vector3 deflectionContribution = ComputeAngularDeflection(pTimestep); |
909 | if (m_angularMotorVelocity.X == 0) | ||
910 | { | ||
911 | // The vehicle is stopped | ||
912 | /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) | ||
913 | { | ||
914 | Vector3 axisAngle; | ||
915 | float angle; | ||
916 | parent.Orientation.GetAxisAngle(out axisAngle, out angle); | ||
917 | Vector3 rotatedVel = parent.Velocity * parent.Orientation; | ||
918 | if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0)) | ||
919 | m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10; | ||
920 | else | ||
921 | m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10; | ||
922 | }*/ | ||
923 | } | ||
924 | else | ||
925 | { | ||
926 | bankingContribution.Z += (effSquared * (mult * mix)) * (m_angularMotorVelocity.X) * 4; | ||
927 | } | ||
928 | 877 | ||
929 | //If they are colliding, we probably shouldn't shove the prim around... probably | 878 | Vector3 bankingContribution = ComputeAngularBanking(pTimestep); |
930 | if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) | ||
931 | { | ||
932 | float angVelZ = m_angularMotorVelocity.X*-1; | ||
933 | /*if(angVelZ > mix) | ||
934 | angVelZ = mix; | ||
935 | else if(angVelZ < -mix) | ||
936 | angVelZ = -mix;*/ | ||
937 | //This controls how fast and how far the banking occurs | ||
938 | Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); | ||
939 | if (bankingRot.X > 3) | ||
940 | bankingRot.X = 3; | ||
941 | else if (bankingRot.X < -3) | ||
942 | bankingRot.X = -3; | ||
943 | bankingRot *= Prim.ForceOrientation; | ||
944 | bankingContribution += bankingRot; | ||
945 | } | ||
946 | m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; | ||
947 | VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},effSq={3},mult={4},mix={5},banking={6}", | ||
948 | Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, effSquared, mult, mix, bankingContribution); | ||
949 | } | ||
950 | 879 | ||
951 | // ================================================================== | 880 | // ================================================================== |
952 | m_lastVertAttractor = verticalAttractionContribution; | 881 | m_lastVertAttractor = verticalAttractionContribution; |
953 | 882 | ||
954 | // Sum velocities | 883 | // Sum velocities |
955 | m_lastAngularVelocity = angularMotorContribution | 884 | m_lastAngularVelocity = angularMotorContribution |
956 | + verticalAttractionContribution | 885 | + verticalAttractionContribution |
957 | + bankingContribution | 886 | + bankingContribution |
958 | + deflectionContribution; | 887 | + deflectionContribution; |
@@ -989,15 +918,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
989 | } | 918 | } |
990 | 919 | ||
991 | // ================================================================== | 920 | // ================================================================== |
992 | // NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | ||
993 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | ||
994 | { | ||
995 | m_lastAngularVelocity.X = 0; | ||
996 | m_lastAngularVelocity.Y = 0; | ||
997 | VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); | ||
998 | } | ||
999 | |||
1000 | // ================================================================== | ||
1001 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | 921 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) |
1002 | { | 922 | { |
1003 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | 923 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. |
@@ -1011,7 +931,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1011 | // Since we are stuffing the angular velocity directly into the object, the computed | 931 | // Since we are stuffing the angular velocity directly into the object, the computed |
1012 | // velocity needs to be scaled by the timestep. | 932 | // velocity needs to be scaled by the timestep. |
1013 | // Also remove any motion that is on the object so added motion is only from vehicle. | 933 | // Also remove any motion that is on the object so added motion is only from vehicle. |
1014 | Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) | 934 | Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) |
1015 | - Prim.ForceRotationalVelocity); | 935 | - Prim.ForceRotationalVelocity); |
1016 | // Unscale the force by the angular factor so it overwhelmes the Bullet additions. | 936 | // Unscale the force by the angular factor so it overwhelmes the Bullet additions. |
1017 | Prim.ForceRotationalVelocity = applyAngularForce; | 937 | Prim.ForceRotationalVelocity = applyAngularForce; |
@@ -1025,6 +945,147 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1025 | } | 945 | } |
1026 | } | 946 | } |
1027 | 947 | ||
948 | public Vector3 ComputeAngularVerticalAttraction(float pTimestep) | ||
949 | { | ||
950 | Vector3 ret = Vector3.Zero; | ||
951 | |||
952 | // If vertical attaction timescale is reasonable and we applied an angular force last time... | ||
953 | if (m_verticalAttractionTimescale < 500) | ||
954 | { | ||
955 | Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; | ||
956 | verticalError.Normalize(); | ||
957 | m_verticalAttractionMotor.SetCurrent(verticalError); | ||
958 | m_verticalAttractionMotor.SetTarget(Vector3.UnitZ); | ||
959 | ret = m_verticalAttractionMotor.Step(pTimestep); | ||
960 | /* | ||
961 | // Take a vector pointing up and convert it from world to vehicle relative coords. | ||
962 | Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; | ||
963 | verticalError.Normalize(); | ||
964 | |||
965 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) | ||
966 | // is now leaning to one side (rotated around the X axis) and the Y value will | ||
967 | // go from zero (nearly straight up) to one (completely to the side) or leaning | ||
968 | // front-to-back (rotated around the Y axis) and the value of X will be between | ||
969 | // zero and one. | ||
970 | // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. | ||
971 | |||
972 | // If verticalError.Z is negative, the vehicle is upside down. Add additional push. | ||
973 | if (verticalError.Z < 0f) | ||
974 | { | ||
975 | verticalError.X = 2f - verticalError.X; | ||
976 | verticalError.Y = 2f - verticalError.Y; | ||
977 | } | ||
978 | |||
979 | // Y error means needed rotation around X axis and visa versa. | ||
980 | verticalAttractionContribution.X = verticalError.Y; | ||
981 | verticalAttractionContribution.Y = - verticalError.X; | ||
982 | verticalAttractionContribution.Z = 0f; | ||
983 | |||
984 | // scale by the time scale and timestep | ||
985 | Vector3 unscaledContrib = verticalAttractionContribution; | ||
986 | verticalAttractionContribution /= m_verticalAttractionTimescale; | ||
987 | verticalAttractionContribution *= pTimestep; | ||
988 | |||
989 | // apply efficiency | ||
990 | Vector3 preEfficiencyContrib = verticalAttractionContribution; | ||
991 | float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency; | ||
992 | verticalAttractionContribution *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | ||
993 | |||
994 | VDetailLog("{0},MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}", | ||
995 | Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib, | ||
996 | m_verticalAttractionEfficiency, efficencySquared, | ||
997 | verticalAttractionContribution); | ||
998 | */ | ||
999 | |||
1000 | } | ||
1001 | return ret; | ||
1002 | } | ||
1003 | |||
1004 | public Vector3 ComputeAngularDeflection(float pTimestep) | ||
1005 | { | ||
1006 | Vector3 ret = Vector3.Zero; | ||
1007 | |||
1008 | if (m_angularDeflectionEfficiency != 0) | ||
1009 | { | ||
1010 | // Compute a scaled vector that points in the preferred axis (X direction) | ||
1011 | Vector3 scaledDefaultDirection = | ||
1012 | new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); | ||
1013 | // Adding the current vehicle orientation and reference frame displaces the orientation to the frame. | ||
1014 | // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point. | ||
1015 | Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); | ||
1016 | |||
1017 | // Scale by efficiency and timescale | ||
1018 | ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; | ||
1019 | |||
1020 | VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", Prim.LocalID, preferredAxisOfMotion, ret); | ||
1021 | |||
1022 | // This deflection computation is not correct. | ||
1023 | ret = Vector3.Zero; | ||
1024 | } | ||
1025 | return ret; | ||
1026 | } | ||
1027 | |||
1028 | public Vector3 ComputeAngularBanking(float pTimestep) | ||
1029 | { | ||
1030 | Vector3 ret = Vector3.Zero; | ||
1031 | |||
1032 | if (m_bankingEfficiency != 0) | ||
1033 | { | ||
1034 | Vector3 dir = Vector3.One * Prim.ForceOrientation; | ||
1035 | float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); | ||
1036 | //Changes which way it banks in and out of turns | ||
1037 | |||
1038 | //Use the square of the efficiency, as it looks much more how SL banking works | ||
1039 | float effSquared = (m_bankingEfficiency * m_bankingEfficiency); | ||
1040 | if (m_bankingEfficiency < 0) | ||
1041 | effSquared *= -1; //Keep the negative! | ||
1042 | |||
1043 | float mix = Math.Abs(m_bankingMix); | ||
1044 | if (m_angularMotorVelocity.X == 0) | ||
1045 | { | ||
1046 | // The vehicle is stopped | ||
1047 | /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) | ||
1048 | { | ||
1049 | Vector3 axisAngle; | ||
1050 | float angle; | ||
1051 | parent.Orientation.GetAxisAngle(out axisAngle, out angle); | ||
1052 | Vector3 rotatedVel = parent.Velocity * parent.Orientation; | ||
1053 | if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0)) | ||
1054 | m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10; | ||
1055 | else | ||
1056 | m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10; | ||
1057 | }*/ | ||
1058 | } | ||
1059 | else | ||
1060 | { | ||
1061 | ret.Z += (effSquared * (mult * mix)) * (m_angularMotorVelocity.X) * 4; | ||
1062 | } | ||
1063 | |||
1064 | //If they are colliding, we probably shouldn't shove the prim around... probably | ||
1065 | if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) | ||
1066 | { | ||
1067 | float angVelZ = m_angularMotorVelocity.X * -1; | ||
1068 | /*if(angVelZ > mix) | ||
1069 | angVelZ = mix; | ||
1070 | else if(angVelZ < -mix) | ||
1071 | angVelZ = -mix;*/ | ||
1072 | //This controls how fast and how far the banking occurs | ||
1073 | Vector3 bankingRot = new Vector3(angVelZ * (effSquared * mult), 0, 0); | ||
1074 | if (bankingRot.X > 3) | ||
1075 | bankingRot.X = 3; | ||
1076 | else if (bankingRot.X < -3) | ||
1077 | bankingRot.X = -3; | ||
1078 | bankingRot *= Prim.ForceOrientation; | ||
1079 | ret += bankingRot; | ||
1080 | } | ||
1081 | m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; | ||
1082 | VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},effSq={3},mult={4},mix={5},banking={6}", | ||
1083 | Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, effSquared, mult, mix, ret); | ||
1084 | } | ||
1085 | return ret; | ||
1086 | } | ||
1087 | |||
1088 | |||
1028 | // This is from previous instantiations of XXXDynamics.cs. | 1089 | // This is from previous instantiations of XXXDynamics.cs. |
1029 | // Applies roll reference frame. | 1090 | // Applies roll reference frame. |
1030 | // TODO: is this the right way to separate the code to do this operation? | 1091 | // TODO: is this the right way to separate the code to do this operation? |