diff options
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 161 |
1 files changed, 128 insertions, 33 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 15a40fe..9749429 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -127,10 +127,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
127 | private float m_verticalAttractionEfficiency = 1.0f; // damped | 127 | private float m_verticalAttractionEfficiency = 1.0f; // damped |
128 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. | 128 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. |
129 | 129 | ||
130 | // Local | ||
131 | private float m_knownTerrainHeight; | ||
132 | private float m_knownWaterLevel; | ||
133 | |||
134 | public BSDynamics(BSScene myScene, BSPrim myPrim) | 130 | public BSDynamics(BSScene myScene, BSPrim myPrim) |
135 | { | 131 | { |
136 | PhysicsScene = myScene; | 132 | PhysicsScene = myScene; |
@@ -560,9 +556,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
560 | { | 556 | { |
561 | if (IsActive) | 557 | if (IsActive) |
562 | { | 558 | { |
559 | // Remember the mass so we don't have to fetch it every step | ||
563 | m_vehicleMass = Prim.Linkset.LinksetMass; | 560 | m_vehicleMass = Prim.Linkset.LinksetMass; |
564 | 561 | ||
565 | // Friction effects are handled by this vehicle code | 562 | // Friction affects are handled by this vehicle code |
566 | float friction = 0f; | 563 | float friction = 0f; |
567 | BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction); | 564 | BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction); |
568 | 565 | ||
@@ -600,31 +597,130 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
600 | Refresh(); | 597 | Refresh(); |
601 | } | 598 | } |
602 | 599 | ||
600 | #region Known vehicle value functions | ||
601 | private int m_knownChanged; | ||
602 | private float? m_knownTerrainHeight; | ||
603 | private float? m_knownWaterLevel; | ||
604 | |||
605 | private Vector3? m_knownPosition; | ||
606 | private Vector3? m_knownVelocity; | ||
607 | private Quaternion? m_knownOrientation; | ||
608 | private Vector3? m_knownRotationalVelocity; | ||
609 | |||
610 | private const int m_knownChangedPosition = 1 << 0; | ||
611 | private const int m_knownChangedVelocity = 1 << 1; | ||
612 | private const int m_knownChangedOrientation = 1 << 2; | ||
613 | private const int m_knownChangedRotationalVelocity = 1 << 3; | ||
614 | |||
615 | private void ForgetKnownVehicleProperties() | ||
616 | { | ||
617 | m_knownTerrainHeight = null; | ||
618 | m_knownWaterLevel = null; | ||
619 | m_knownPosition = null; | ||
620 | m_knownVelocity = null; | ||
621 | m_knownOrientation = null; | ||
622 | m_knownRotationalVelocity = null; | ||
623 | m_knownChanged = 0; | ||
624 | } | ||
625 | private void PushKnownChanged() | ||
626 | { | ||
627 | if (m_knownChanged != 0) | ||
628 | { | ||
629 | if ((m_knownChanged & m_knownChangedPosition) != 0) Prim.ForcePosition = VehiclePosition; | ||
630 | if ((m_knownChanged & m_knownChangedOrientation) != 0) Prim.ForceOrientation = VehicleOrientation; | ||
631 | if ((m_knownChanged & m_knownChangedVelocity) != 0) Prim.ForceVelocity = VehicleVelocity; | ||
632 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) Prim.ForceRotationalVelocity = VehicleRotationalVelocity; | ||
633 | // If we set one of the values (ie, the physics engine doesn't do it) we must make sure there | ||
634 | // is an UpdateProperties event to send the changes up to the simulator. | ||
635 | BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); | ||
636 | } | ||
637 | } | ||
638 | |||
603 | // Since the computation of terrain height can be a little involved, this routine | 639 | // Since the computation of terrain height can be a little involved, this routine |
604 | // is used ot fetch the height only once for each vehicle simulation step. | 640 | // is used ot fetch the height only once for each vehicle simulation step. |
605 | private float GetTerrainHeight(Vector3 pos) | 641 | private float GetTerrainHeight(Vector3 pos) |
606 | { | 642 | { |
607 | if (m_knownTerrainHeight == float.MinValue) | 643 | if (m_knownTerrainHeight == null) |
608 | m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | 644 | m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); |
609 | return m_knownTerrainHeight; | 645 | return (float)m_knownTerrainHeight; |
610 | } | 646 | } |
611 | 647 | ||
612 | // Since the computation of water level can be a little involved, this routine | 648 | // Since the computation of water level can be a little involved, this routine |
613 | // is used ot fetch the level only once for each vehicle simulation step. | 649 | // is used ot fetch the level only once for each vehicle simulation step. |
614 | private float GetWaterLevel(Vector3 pos) | 650 | private float GetWaterLevel(Vector3 pos) |
615 | { | 651 | { |
616 | if (m_knownWaterLevel == float.MinValue) | 652 | if (m_knownWaterLevel == null) |
617 | m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); | 653 | m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); |
618 | return m_knownWaterLevel; | 654 | return (float)m_knownWaterLevel; |
655 | } | ||
656 | |||
657 | private Vector3 VehiclePosition | ||
658 | { | ||
659 | get | ||
660 | { | ||
661 | if (m_knownPosition == null) | ||
662 | m_knownPosition = Prim.ForcePosition; | ||
663 | return (Vector3)m_knownPosition; | ||
664 | } | ||
665 | set | ||
666 | { | ||
667 | m_knownPosition = value; | ||
668 | m_knownChanged |= m_knownChangedPosition; | ||
669 | } | ||
670 | } | ||
671 | |||
672 | private Quaternion VehicleOrientation | ||
673 | { | ||
674 | get | ||
675 | { | ||
676 | if (m_knownOrientation == null) | ||
677 | m_knownOrientation = Prim.ForceOrientation; | ||
678 | return (Quaternion)m_knownOrientation; | ||
679 | } | ||
680 | set | ||
681 | { | ||
682 | m_knownOrientation = value; | ||
683 | m_knownChanged |= m_knownChangedOrientation; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | private Vector3 VehicleVelocity | ||
688 | { | ||
689 | get | ||
690 | { | ||
691 | if (m_knownVelocity == null) | ||
692 | m_knownVelocity = Prim.ForceVelocity; | ||
693 | return (Vector3)m_knownVelocity; | ||
694 | } | ||
695 | set | ||
696 | { | ||
697 | m_knownVelocity = value; | ||
698 | m_knownChanged |= m_knownChangedVelocity; | ||
699 | } | ||
700 | } | ||
701 | |||
702 | private Vector3 VehicleRotationalVelocity | ||
703 | { | ||
704 | get | ||
705 | { | ||
706 | if (m_knownRotationalVelocity == null) | ||
707 | m_knownRotationalVelocity = Prim.ForceRotationalVelocity; | ||
708 | return (Vector3)m_knownRotationalVelocity; | ||
709 | } | ||
710 | set | ||
711 | { | ||
712 | m_knownRotationalVelocity = value; | ||
713 | m_knownChanged |= m_knownChangedRotationalVelocity; | ||
714 | } | ||
619 | } | 715 | } |
716 | #endregion // Known vehicle value functions | ||
620 | 717 | ||
621 | // One step of the vehicle properties for the next 'pTimestep' seconds. | 718 | // One step of the vehicle properties for the next 'pTimestep' seconds. |
622 | internal void Step(float pTimestep) | 719 | internal void Step(float pTimestep) |
623 | { | 720 | { |
624 | if (!IsActive) return; | 721 | if (!IsActive) return; |
625 | 722 | ||
626 | // Zap values so they will be fetched if needed | 723 | ForgetKnownVehicleProperties(); |
627 | m_knownTerrainHeight = m_knownWaterLevel = float.MinValue; | ||
628 | 724 | ||
629 | MoveLinear(pTimestep); | 725 | MoveLinear(pTimestep); |
630 | MoveAngular(pTimestep); | 726 | MoveAngular(pTimestep); |
@@ -632,15 +728,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
632 | LimitRotation(pTimestep); | 728 | LimitRotation(pTimestep); |
633 | 729 | ||
634 | // remember the position so next step we can limit absolute movement effects | 730 | // remember the position so next step we can limit absolute movement effects |
635 | m_lastPositionVector = Prim.ForcePosition; | 731 | m_lastPositionVector = VehiclePosition; |
636 | 732 | ||
637 | // Force the physics engine to decide whether values were updated. | 733 | // If we forced the changing of some vehicle parameters, update the values and |
638 | // TODO: this is only necessary if pos, velocity, etc were updated. Is it quicker | 734 | // for the physics engine to note the changes so an UpdateProperties event will happen. |
639 | // to check for changes here or just push the update? | 735 | PushKnownChanged(); |
640 | BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); | ||
641 | 736 | ||
642 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | 737 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", |
643 | Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); | 738 | Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); |
644 | } | 739 | } |
645 | 740 | ||
646 | // Apply the effect of the linear motor and other linear motions (like hover and float). | 741 | // Apply the effect of the linear motor and other linear motions (like hover and float). |
@@ -650,7 +745,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
650 | 745 | ||
651 | // The movement computed in the linear motor is relative to the vehicle | 746 | // The movement computed in the linear motor is relative to the vehicle |
652 | // coordinates. Rotate the movement to world coordinates. | 747 | // coordinates. Rotate the movement to world coordinates. |
653 | linearMotorContribution *= Prim.ForceOrientation; | 748 | linearMotorContribution *= VehicleOrientation; |
654 | 749 | ||
655 | // ================================================================== | 750 | // ================================================================== |
656 | // Gravity and Buoyancy | 751 | // Gravity and Buoyancy |
@@ -658,7 +753,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
658 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 753 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
659 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); | 754 | Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); |
660 | 755 | ||
661 | Vector3 pos = Prim.ForcePosition; | 756 | Vector3 pos = VehiclePosition; |
662 | 757 | ||
663 | Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(ref pos); | 758 | Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(ref pos); |
664 | 759 | ||
@@ -696,7 +791,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
696 | // ================================================================== | 791 | // ================================================================== |
697 | // Stuff new linear velocity into the vehicle. | 792 | // Stuff new linear velocity into the vehicle. |
698 | // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us. | 793 | // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us. |
699 | Prim.ForceVelocity = newVelocity; | 794 | VehicleVelocity = newVelocity; |
700 | 795 | ||
701 | // Other linear forces are applied as forces. | 796 | // Other linear forces are applied as forces. |
702 | Vector3 totalDownForce = grav * m_vehicleMass * pTimestep; | 797 | Vector3 totalDownForce = grav * m_vehicleMass * pTimestep; |
@@ -721,7 +816,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
721 | { | 816 | { |
722 | // TODO: correct position by applying force rather than forcing position. | 817 | // TODO: correct position by applying force rather than forcing position. |
723 | pos.Z = GetTerrainHeight(pos) + 2; | 818 | pos.Z = GetTerrainHeight(pos) + 2; |
724 | Prim.ForcePosition = pos; | 819 | VehiclePosition = pos; |
725 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, GetTerrainHeight(pos), pos); | 820 | VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, GetTerrainHeight(pos), pos); |
726 | } | 821 | } |
727 | return ret; | 822 | return ret; |
@@ -761,7 +856,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
761 | if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f) | 856 | if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f) |
762 | { | 857 | { |
763 | pos.Z = m_VhoverTargetHeight; | 858 | pos.Z = m_VhoverTargetHeight; |
764 | Prim.ForcePosition = pos; | 859 | VehiclePosition = pos; |
765 | } | 860 | } |
766 | } | 861 | } |
767 | else | 862 | else |
@@ -818,7 +913,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
818 | } | 913 | } |
819 | if (changed) | 914 | if (changed) |
820 | { | 915 | { |
821 | Prim.ForcePosition = pos; | 916 | VehiclePosition = pos; |
822 | VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | 917 | VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", |
823 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); | 918 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); |
824 | } | 919 | } |
@@ -958,6 +1053,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
958 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | 1053 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. |
959 | // TODO: zeroing is good but it also sets values in unmanaged code. Remove the stores when idle. | 1054 | // TODO: zeroing is good but it also sets values in unmanaged code. Remove the stores when idle. |
960 | VDetailLog("{0},MoveAngular,done,zero,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); | 1055 | VDetailLog("{0},MoveAngular,done,zero,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); |
1056 | VehicleRotationalVelocity = Vector3.Zero; | ||
961 | Prim.ZeroAngularMotion(true); | 1057 | Prim.ZeroAngularMotion(true); |
962 | } | 1058 | } |
963 | else | 1059 | else |
@@ -967,10 +1063,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
967 | // Since we are stuffing the angular velocity directly into the object, the computed | 1063 | // Since we are stuffing the angular velocity directly into the object, the computed |
968 | // velocity needs to be scaled by the timestep. | 1064 | // velocity needs to be scaled by the timestep. |
969 | // Also remove any motion that is on the object so added motion is only from vehicle. | 1065 | // Also remove any motion that is on the object so added motion is only from vehicle. |
970 | Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) | 1066 | Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - VehicleRotationalVelocity); |
971 | - Prim.ForceRotationalVelocity); | ||
972 | // Unscale the force by the angular factor so it overwhelmes the Bullet additions. | 1067 | // Unscale the force by the angular factor so it overwhelmes the Bullet additions. |
973 | Prim.ForceRotationalVelocity = applyAngularForce; | 1068 | VehicleRotationalVelocity = applyAngularForce; |
974 | 1069 | ||
975 | VDetailLog("{0},MoveAngular,done,nonZero,angMotor={1},vertAttr={2},bank={3},deflect={4},newAngForce={5},lastAngular={6}", | 1070 | VDetailLog("{0},MoveAngular,done,nonZero,angMotor={1},vertAttr={2},bank={3},deflect={4},newAngForce={5},lastAngular={6}", |
976 | Prim.LocalID, | 1071 | Prim.LocalID, |
@@ -988,14 +1083,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
988 | // If vertical attaction timescale is reasonable and we applied an angular force last time... | 1083 | // If vertical attaction timescale is reasonable and we applied an angular force last time... |
989 | if (m_verticalAttractionTimescale < 500) | 1084 | if (m_verticalAttractionTimescale < 500) |
990 | { | 1085 | { |
991 | Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; | 1086 | Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; |
992 | verticalError.Normalize(); | 1087 | verticalError.Normalize(); |
993 | m_verticalAttractionMotor.SetCurrent(verticalError); | 1088 | m_verticalAttractionMotor.SetCurrent(verticalError); |
994 | m_verticalAttractionMotor.SetTarget(Vector3.UnitZ); | 1089 | m_verticalAttractionMotor.SetTarget(Vector3.UnitZ); |
995 | ret = m_verticalAttractionMotor.Step(pTimestep); | 1090 | ret = m_verticalAttractionMotor.Step(pTimestep); |
996 | /* | 1091 | /* |
997 | // Take a vector pointing up and convert it from world to vehicle relative coords. | 1092 | // Take a vector pointing up and convert it from world to vehicle relative coords. |
998 | Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; | 1093 | Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; |
999 | verticalError.Normalize(); | 1094 | verticalError.Normalize(); |
1000 | 1095 | ||
1001 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) | 1096 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) |
@@ -1048,7 +1143,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1048 | new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); | 1143 | new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); |
1049 | // Adding the current vehicle orientation and reference frame displaces the orientation to the frame. | 1144 | // Adding the current vehicle orientation and reference frame displaces the orientation to the frame. |
1050 | // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point. | 1145 | // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point. |
1051 | Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); | 1146 | Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(VehicleOrientation, m_referenceFrame); |
1052 | 1147 | ||
1053 | // Scale by efficiency and timescale | 1148 | // Scale by efficiency and timescale |
1054 | ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; | 1149 | ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; |
@@ -1067,7 +1162,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1067 | 1162 | ||
1068 | if (m_bankingEfficiency != 0) | 1163 | if (m_bankingEfficiency != 0) |
1069 | { | 1164 | { |
1070 | Vector3 dir = Vector3.One * Prim.ForceOrientation; | 1165 | Vector3 dir = Vector3.One * VehicleOrientation; |
1071 | float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); | 1166 | float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); |
1072 | //Changes which way it banks in and out of turns | 1167 | //Changes which way it banks in and out of turns |
1073 | 1168 | ||
@@ -1111,7 +1206,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1111 | bankingRot.X = 3; | 1206 | bankingRot.X = 3; |
1112 | else if (bankingRot.X < -3) | 1207 | else if (bankingRot.X < -3) |
1113 | bankingRot.X = -3; | 1208 | bankingRot.X = -3; |
1114 | bankingRot *= Prim.ForceOrientation; | 1209 | bankingRot *= VehicleOrientation; |
1115 | ret += bankingRot; | 1210 | ret += bankingRot; |
1116 | } | 1211 | } |
1117 | m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; | 1212 | m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; |
@@ -1128,7 +1223,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1128 | // Should this be in MoveAngular()? | 1223 | // Should this be in MoveAngular()? |
1129 | internal void LimitRotation(float timestep) | 1224 | internal void LimitRotation(float timestep) |
1130 | { | 1225 | { |
1131 | Quaternion rotq = Prim.ForceOrientation; | 1226 | Quaternion rotq = VehicleOrientation; |
1132 | Quaternion m_rot = rotq; | 1227 | Quaternion m_rot = rotq; |
1133 | if (m_RollreferenceFrame != Quaternion.Identity) | 1228 | if (m_RollreferenceFrame != Quaternion.Identity) |
1134 | { | 1229 | { |
@@ -1156,7 +1251,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1156 | } | 1251 | } |
1157 | if (rotq != m_rot) | 1252 | if (rotq != m_rot) |
1158 | { | 1253 | { |
1159 | Prim.ForceOrientation = m_rot; | 1254 | VehicleOrientation = m_rot; |
1160 | VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); | 1255 | VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); |
1161 | } | 1256 | } |
1162 | 1257 | ||