diff options
Diffstat (limited to 'OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 1114 |
1 files changed, 600 insertions, 514 deletions
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index fbe52c8..5f802d0 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | |||
@@ -64,11 +64,16 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
64 | private Vector3 m_taintVelocity; | 64 | private Vector3 m_taintVelocity; |
65 | private Vector3 m_taintTorque; | 65 | private Vector3 m_taintTorque; |
66 | private Quaternion m_taintrot; | 66 | private Quaternion m_taintrot; |
67 | private Vector3 m_angularEnable = Vector3.One; // Current setting | 67 | private Vector3 m_rotateEnable = Vector3.One; // Current setting |
68 | private Vector3 m_taintAngularLock = Vector3.One; // Request from LSL | 68 | private Vector3 m_rotateEnableRequest = Vector3.One; // Request from LSL |
69 | 69 | private bool m_rotateEnableUpdate = false; | |
70 | 70 | private Vector3 m_lockX; | |
71 | private Vector3 m_lockY; | ||
72 | private Vector3 m_lockZ; | ||
71 | private IntPtr Amotor = IntPtr.Zero; | 73 | private IntPtr Amotor = IntPtr.Zero; |
74 | private IntPtr AmotorX = IntPtr.Zero; | ||
75 | private IntPtr AmotorY = IntPtr.Zero; | ||
76 | private IntPtr AmotorZ = IntPtr.Zero; | ||
72 | 77 | ||
73 | private Vector3 m_PIDTarget; | 78 | private Vector3 m_PIDTarget; |
74 | private float m_PIDTau; | 79 | private float m_PIDTau; |
@@ -80,6 +85,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
80 | private float m_APIDStrength = 0.5f; | 85 | private float m_APIDStrength = 0.5f; |
81 | private float m_APIDDamping = 0.5f; | 86 | private float m_APIDDamping = 0.5f; |
82 | private bool m_useAPID = false; | 87 | private bool m_useAPID = false; |
88 | private float m_APIDdamper = 1.0f; | ||
83 | 89 | ||
84 | // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), | 90 | // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), |
85 | // do not confuse with VEHICLE HOVER | 91 | // do not confuse with VEHICLE HOVER |
@@ -126,6 +132,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
126 | //public GCHandle gc; | 132 | //public GCHandle gc; |
127 | private CollisionLocker ode; | 133 | private CollisionLocker ode; |
128 | 134 | ||
135 | private bool m_meshfailed = false; | ||
129 | private bool m_taintforce = false; | 136 | private bool m_taintforce = false; |
130 | private bool m_taintaddangularforce = false; | 137 | private bool m_taintaddangularforce = false; |
131 | private Vector3 m_force; | 138 | private Vector3 m_force; |
@@ -137,7 +144,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
137 | private OdeScene _parent_scene; | 144 | private OdeScene _parent_scene; |
138 | public IntPtr m_targetSpace = IntPtr.Zero; | 145 | public IntPtr m_targetSpace = IntPtr.Zero; |
139 | public IntPtr prim_geom; | 146 | public IntPtr prim_geom; |
140 | public IntPtr prev_geom; | 147 | // public IntPtr prev_geom; |
141 | public IntPtr _triMeshData; | 148 | public IntPtr _triMeshData; |
142 | 149 | ||
143 | private IntPtr _linkJointGroup = IntPtr.Zero; | 150 | private IntPtr _linkJointGroup = IntPtr.Zero; |
@@ -249,8 +256,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
249 | 256 | ||
250 | 257 | ||
251 | public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, | 258 | public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, |
252 | Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) | 259 | Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode, uint localid) |
253 | { | 260 | { |
261 | m_localID = localid; | ||
254 | ode = dode; | 262 | ode = dode; |
255 | if (!pos.IsFinite()) | 263 | if (!pos.IsFinite()) |
256 | { | 264 | { |
@@ -269,7 +277,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
269 | 277 | ||
270 | 278 | ||
271 | prim_geom = IntPtr.Zero; | 279 | prim_geom = IntPtr.Zero; |
272 | prev_geom = IntPtr.Zero; | 280 | // prev_geom = IntPtr.Zero; |
273 | 281 | ||
274 | if (!pos.IsFinite()) | 282 | if (!pos.IsFinite()) |
275 | { | 283 | { |
@@ -538,6 +546,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
538 | if (value.IsFinite()) | 546 | if (value.IsFinite()) |
539 | { | 547 | { |
540 | _velocity = value; | 548 | _velocity = value; |
549 | if (_velocity.ApproxEquals(Vector3.Zero,0.001f)) | ||
550 | _acceleration = Vector3.Zero; | ||
541 | 551 | ||
542 | m_taintVelocity = value; | 552 | m_taintVelocity = value; |
543 | _parent_scene.AddPhysicsActorTaint(this); | 553 | _parent_scene.AddPhysicsActorTaint(this); |
@@ -655,7 +665,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
655 | 665 | ||
656 | public override Vector3 Acceleration // client updates read data via here | 666 | public override Vector3 Acceleration // client updates read data via here |
657 | { | 667 | { |
658 | get { return _acceleration; } | 668 | get |
669 | { | ||
670 | if (_zeroFlag) | ||
671 | { | ||
672 | return Vector3.Zero; | ||
673 | } | ||
674 | return _acceleration; | ||
675 | } | ||
659 | } | 676 | } |
660 | 677 | ||
661 | 678 | ||
@@ -744,14 +761,18 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
744 | 761 | ||
745 | public override void LockAngularMotion(Vector3 axis) | 762 | public override void LockAngularMotion(Vector3 axis) |
746 | { | 763 | { |
747 | // reverse the zero/non zero values for ODE. | 764 | // This is actually ROTATION ENABLE, not a lock. |
765 | // default is <1,1,1> which is all enabled. | ||
766 | // The lock value is updated inside Move(), no point in using the taint system. | ||
767 | // OS 'm_taintAngularLock' etc change to m_rotateEnable. | ||
748 | if (axis.IsFinite()) | 768 | if (axis.IsFinite()) |
749 | { | 769 | { |
750 | axis.X = (axis.X > 0) ? 1f : 0f; | 770 | axis.X = (axis.X > 0) ? 1f : 0f; |
751 | axis.Y = (axis.Y > 0) ? 1f : 0f; | 771 | axis.Y = (axis.Y > 0) ? 1f : 0f; |
752 | axis.Z = (axis.Z > 0) ? 1f : 0f; | 772 | axis.Z = (axis.Z > 0) ? 1f : 0f; |
753 | m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); | 773 | m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); |
754 | m_taintAngularLock = axis; | 774 | m_rotateEnableRequest = axis; |
775 | m_rotateEnableUpdate = true; | ||
755 | } | 776 | } |
756 | else | 777 | else |
757 | { | 778 | { |
@@ -762,13 +783,26 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
762 | 783 | ||
763 | public void SetGeom(IntPtr geom) | 784 | public void SetGeom(IntPtr geom) |
764 | { | 785 | { |
765 | prev_geom = prim_geom; | 786 | if(prim_geom != IntPtr.Zero) |
787 | { | ||
788 | // Remove any old entries | ||
789 | //string tPA; | ||
790 | //_parent_scene.geom_name_map.TryGetValue(prim_geom, out tPA); | ||
791 | //Console.WriteLine("**** Remove {0}", tPA); | ||
792 | if(_parent_scene.geom_name_map.ContainsKey(prim_geom)) _parent_scene.geom_name_map.Remove(prim_geom); | ||
793 | if(_parent_scene.actor_name_map.ContainsKey(prim_geom)) _parent_scene.actor_name_map.Remove(prim_geom); | ||
794 | d.GeomDestroy(prim_geom); | ||
795 | } | ||
796 | |||
766 | prim_geom = geom; | 797 | prim_geom = geom; |
767 | //Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName); | 798 | //Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName); |
768 | if (prim_geom != IntPtr.Zero) | 799 | if (prim_geom != IntPtr.Zero) |
769 | { | 800 | { |
801 | _parent_scene.geom_name_map[prim_geom] = this.m_primName; | ||
802 | _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; | ||
770 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); | 803 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); |
771 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); | 804 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); |
805 | //Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, this.m_primName); | ||
772 | } | 806 | } |
773 | 807 | ||
774 | if (childPrim) | 808 | if (childPrim) |
@@ -856,300 +890,285 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
856 | 890 | ||
857 | private float CalculateMass() | 891 | private float CalculateMass() |
858 | { | 892 | { |
859 | float volume = 0; | 893 | float volume = _size.X * _size.Y * _size.Z; // default |
860 | 894 | float tmp; | |
861 | // No material is passed to the physics engines yet.. soo.. | ||
862 | // we're using the m_density constant in the class definition | ||
863 | 895 | ||
864 | float returnMass = 0; | 896 | float returnMass = 0; |
865 | 897 | float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; | |
898 | float hollowVolume = hollowAmount * hollowAmount; | ||
899 | |||
866 | switch (_pbs.ProfileShape) | 900 | switch (_pbs.ProfileShape) |
867 | { | 901 | { |
868 | case ProfileShape.Square: | 902 | case ProfileShape.Square: |
869 | // Profile Volume | 903 | // default box |
870 | 904 | ||
871 | volume = _size.X*_size.Y*_size.Z; | 905 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
906 | { | ||
907 | if (hollowAmount > 0.0) | ||
908 | { | ||
909 | switch (_pbs.HollowShape) | ||
910 | { | ||
911 | case HollowShape.Square: | ||
912 | case HollowShape.Same: | ||
913 | break; | ||
872 | 914 | ||
873 | // If the user has 'hollowed out' | 915 | case HollowShape.Circle: |
874 | // ProfileHollow is one of those 0 to 50000 values :P | ||
875 | // we like percentages better.. so turning into a percentage | ||
876 | 916 | ||
877 | if (((float) _pbs.ProfileHollow/50000f) > 0.0) | 917 | hollowVolume *= 0.78539816339f; |
878 | { | 918 | break; |
879 | float hollowAmount = (float) _pbs.ProfileHollow/50000f; | 919 | |
920 | case HollowShape.Triangle: | ||
921 | |||
922 | hollowVolume *= (0.5f * .5f); | ||
923 | break; | ||
880 | 924 | ||
881 | // calculate the hollow volume by it's shape compared to the prim shape | 925 | default: |
882 | float hollowVolume = 0; | 926 | hollowVolume = 0; |
883 | switch (_pbs.HollowShape) | 927 | break; |
928 | } | ||
929 | volume *= (1.0f - hollowVolume); | ||
930 | } | ||
931 | } | ||
932 | |||
933 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
884 | { | 934 | { |
885 | case HollowShape.Square: | 935 | //a tube |
886 | case HollowShape.Same: | 936 | |
887 | // Cube Hollow volume calculation | 937 | volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); |
888 | float hollowsizex = _size.X*hollowAmount; | 938 | tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); |
889 | float hollowsizey = _size.Y*hollowAmount; | 939 | volume -= volume*tmp*tmp; |
890 | float hollowsizez = _size.Z*hollowAmount; | 940 | |
891 | hollowVolume = hollowsizex*hollowsizey*hollowsizez; | 941 | if (hollowAmount > 0.0) |
892 | break; | 942 | { |
893 | 943 | hollowVolume *= hollowAmount; | |
894 | case HollowShape.Circle: | 944 | |
895 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | 945 | switch (_pbs.HollowShape) |
896 | // Cyllinder hollow volume calculation | 946 | { |
897 | float hRadius = _size.X/2; | 947 | case HollowShape.Square: |
898 | float hLength = _size.Z; | 948 | case HollowShape.Same: |
899 | 949 | break; | |
900 | // pi * r2 * h | 950 | |
901 | hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); | 951 | case HollowShape.Circle: |
902 | break; | 952 | hollowVolume *= 0.78539816339f;; |
903 | 953 | break; | |
904 | case HollowShape.Triangle: | 954 | |
905 | // Equilateral Triangular Prism volume hollow calculation | 955 | case HollowShape.Triangle: |
906 | // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y | 956 | hollowVolume *= 0.5f * 0.5f; |
907 | 957 | break; | |
908 | float aLength = _size.Y; | 958 | default: |
909 | // 1/2 abh | 959 | hollowVolume = 0; |
910 | hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); | 960 | break; |
911 | break; | 961 | } |
912 | 962 | volume *= (1.0f - hollowVolume); | |
913 | default: | 963 | } |
914 | hollowVolume = 0; | ||
915 | break; | ||
916 | } | 964 | } |
917 | volume = volume - hollowVolume; | ||
918 | } | ||
919 | 965 | ||
920 | break; | 966 | break; |
967 | |||
921 | case ProfileShape.Circle: | 968 | case ProfileShape.Circle: |
922 | if (_pbs.PathCurve == (byte)Extrusion.Straight) | ||
923 | { | ||
924 | // Cylinder | ||
925 | float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z); | ||
926 | float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z); | ||
927 | 969 | ||
928 | // Approximating the cylinder's irregularity. | 970 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
929 | if (volume1 > volume2) | ||
930 | { | ||
931 | volume = (float)volume1 - (volume1 - volume2); | ||
932 | } | ||
933 | else if (volume2 > volume1) | ||
934 | { | 971 | { |
935 | volume = (float)volume2 - (volume2 - volume1); | 972 | volume *= 0.78539816339f; // elipse base |
973 | |||
974 | if (hollowAmount > 0.0) | ||
975 | { | ||
976 | switch (_pbs.HollowShape) | ||
977 | { | ||
978 | case HollowShape.Same: | ||
979 | case HollowShape.Circle: | ||
980 | break; | ||
981 | |||
982 | case HollowShape.Square: | ||
983 | hollowVolume *= 0.5f * 2.5984480504799f; | ||
984 | break; | ||
985 | |||
986 | case HollowShape.Triangle: | ||
987 | hollowVolume *= .5f * 1.27323954473516f; | ||
988 | break; | ||
989 | |||
990 | default: | ||
991 | hollowVolume = 0; | ||
992 | break; | ||
993 | } | ||
994 | volume *= (1.0f - hollowVolume); | ||
995 | } | ||
936 | } | 996 | } |
937 | else | 997 | |
998 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) | ||
938 | { | 999 | { |
939 | // Regular cylinder | 1000 | volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); |
940 | volume = volume1; | 1001 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); |
941 | } | 1002 | volume *= (1.0f - tmp * tmp); |
942 | } | 1003 | |
943 | else | 1004 | if (hollowAmount > 0.0) |
944 | { | 1005 | { |
945 | // We don't know what the shape is yet, so use default | ||
946 | volume = _size.X * _size.Y * _size.Z; | ||
947 | } | ||
948 | // If the user has 'hollowed out' | ||
949 | // ProfileHollow is one of those 0 to 50000 values :P | ||
950 | // we like percentages better.. so turning into a percentage | ||
951 | 1006 | ||
952 | if (((float)_pbs.ProfileHollow / 50000f) > 0.0) | 1007 | // calculate the hollow volume by it's shape compared to the prim shape |
953 | { | 1008 | hollowVolume *= hollowAmount; |
954 | float hollowAmount = (float)_pbs.ProfileHollow / 50000f; | ||
955 | 1009 | ||
956 | // calculate the hollow volume by it's shape compared to the prim shape | 1010 | switch (_pbs.HollowShape) |
957 | float hollowVolume = 0; | 1011 | { |
958 | switch (_pbs.HollowShape) | 1012 | case HollowShape.Same: |
959 | { | 1013 | case HollowShape.Circle: |
960 | case HollowShape.Same: | 1014 | break; |
961 | case HollowShape.Circle: | 1015 | |
962 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | 1016 | case HollowShape.Square: |
963 | // Cyllinder hollow volume calculation | 1017 | hollowVolume *= 0.5f * 2.5984480504799f; |
964 | float hRadius = _size.X / 2; | 1018 | break; |
965 | float hLength = _size.Z; | 1019 | |
966 | 1020 | case HollowShape.Triangle: | |
967 | // pi * r2 * h | 1021 | hollowVolume *= .5f * 1.27323954473516f; |
968 | hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); | 1022 | break; |
969 | break; | 1023 | |
970 | 1024 | default: | |
971 | case HollowShape.Square: | 1025 | hollowVolume = 0; |
972 | // Cube Hollow volume calculation | 1026 | break; |
973 | float hollowsizex = _size.X * hollowAmount; | 1027 | } |
974 | float hollowsizey = _size.Y * hollowAmount; | 1028 | volume *= (1.0f - hollowVolume); |
975 | float hollowsizez = _size.Z * hollowAmount; | 1029 | } |
976 | hollowVolume = hollowsizex * hollowsizey * hollowsizez; | ||
977 | break; | ||
978 | |||
979 | case HollowShape.Triangle: | ||
980 | // Equilateral Triangular Prism volume hollow calculation | ||
981 | // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y | ||
982 | |||
983 | float aLength = _size.Y; | ||
984 | // 1/2 abh | ||
985 | hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); | ||
986 | break; | ||
987 | |||
988 | default: | ||
989 | hollowVolume = 0; | ||
990 | break; | ||
991 | } | 1030 | } |
992 | volume = volume - hollowVolume; | ||
993 | } | ||
994 | break; | 1031 | break; |
995 | 1032 | ||
996 | case ProfileShape.HalfCircle: | 1033 | case ProfileShape.HalfCircle: |
997 | if (_pbs.PathCurve == (byte)Extrusion.Curve1) | 1034 | if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
998 | { | 1035 | { |
999 | if (_size.X == _size.Y && _size.Y == _size.Z) | 1036 | volume *= 0.52359877559829887307710723054658f; |
1000 | { | ||
1001 | // regular sphere | ||
1002 | // v = 4/3 * pi * r^3 | ||
1003 | float sradius3 = (float)Math.Pow((_size.X / 2), 3); | ||
1004 | volume = (float)((4f / 3f) * Math.PI * sradius3); | ||
1005 | } | ||
1006 | else | ||
1007 | { | ||
1008 | // we treat this as a box currently | ||
1009 | volume = _size.X * _size.Y * _size.Z; | ||
1010 | } | ||
1011 | } | ||
1012 | else | ||
1013 | { | ||
1014 | // We don't know what the shape is yet, so use default | ||
1015 | volume = _size.X * _size.Y * _size.Z; | ||
1016 | } | 1037 | } |
1017 | break; | 1038 | break; |
1018 | 1039 | ||
1019 | case ProfileShape.EquilateralTriangle: | 1040 | case ProfileShape.EquilateralTriangle: |
1020 | /* | ||
1021 | v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h | ||
1022 | 1041 | ||
1023 | // seed mesh | 1042 | if (_pbs.PathCurve == (byte)Extrusion.Straight) |
1024 | Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); | 1043 | { |
1025 | Vertex PM = new Vertex(+0.5f, 0f, 0.0f); | 1044 | volume *= 0.32475953f; |
1026 | Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); | 1045 | |
1027 | */ | 1046 | if (hollowAmount > 0.0) |
1028 | float xA = -0.25f * _size.X; | 1047 | { |
1029 | float yA = -0.45f * _size.Y; | ||
1030 | 1048 | ||
1031 | float xB = 0.5f * _size.X; | 1049 | // calculate the hollow volume by it's shape compared to the prim shape |
1032 | float yB = 0; | 1050 | switch (_pbs.HollowShape) |
1051 | { | ||
1052 | case HollowShape.Same: | ||
1053 | case HollowShape.Triangle: | ||
1054 | hollowVolume *= .25f; | ||
1055 | break; | ||
1033 | 1056 | ||
1034 | float xC = -0.25f * _size.X; | 1057 | case HollowShape.Square: |
1035 | float yC = 0.45f * _size.Y; | 1058 | hollowVolume *= 0.499849f * 3.07920140172638f; |
1059 | break; | ||
1036 | 1060 | ||
1037 | volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); | 1061 | case HollowShape.Circle: |
1062 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | ||
1063 | // Cyllinder hollow volume calculation | ||
1038 | 1064 | ||
1039 | // If the user has 'hollowed out' | 1065 | hollowVolume *= 0.1963495f * 3.07920140172638f; |
1040 | // ProfileHollow is one of those 0 to 50000 values :P | 1066 | break; |
1041 | // we like percentages better.. so turning into a percentage | ||
1042 | float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); | ||
1043 | if (((float)fhollowFactor / 50000f) > 0.0) | ||
1044 | { | ||
1045 | float hollowAmount = (float)fhollowFactor / 50000f; | ||
1046 | 1067 | ||
1047 | // calculate the hollow volume by it's shape compared to the prim shape | 1068 | default: |
1048 | float hollowVolume = 0; | 1069 | hollowVolume = 0; |
1049 | switch (_pbs.HollowShape) | 1070 | break; |
1050 | { | 1071 | } |
1051 | case HollowShape.Same: | 1072 | volume *= (1.0f - hollowVolume); |
1052 | case HollowShape.Triangle: | 1073 | } |
1053 | // Equilateral Triangular Prism volume hollow calculation | ||
1054 | // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y | ||
1055 | |||
1056 | float aLength = _size.Y; | ||
1057 | // 1/2 abh | ||
1058 | hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); | ||
1059 | break; | ||
1060 | |||
1061 | case HollowShape.Square: | ||
1062 | // Cube Hollow volume calculation | ||
1063 | float hollowsizex = _size.X * hollowAmount; | ||
1064 | float hollowsizey = _size.Y * hollowAmount; | ||
1065 | float hollowsizez = _size.Z * hollowAmount; | ||
1066 | hollowVolume = hollowsizex * hollowsizey * hollowsizez; | ||
1067 | break; | ||
1068 | |||
1069 | case HollowShape.Circle: | ||
1070 | // Hollow shape is a perfect cyllinder in respect to the cube's scale | ||
1071 | // Cyllinder hollow volume calculation | ||
1072 | float hRadius = _size.X / 2; | ||
1073 | float hLength = _size.Z; | ||
1074 | |||
1075 | // pi * r2 * h | ||
1076 | hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount); | ||
1077 | break; | ||
1078 | |||
1079 | default: | ||
1080 | hollowVolume = 0; | ||
1081 | break; | ||
1082 | } | 1074 | } |
1083 | volume = volume - hollowVolume; | 1075 | else if (_pbs.PathCurve == (byte)Extrusion.Curve1) |
1084 | } | 1076 | { |
1085 | break; | 1077 | volume *= 0.32475953f; |
1078 | volume *= 0.01f * (float)(200 - _pbs.PathScaleX); | ||
1079 | tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); | ||
1080 | volume *= (1.0f - tmp * tmp); | ||
1086 | 1081 | ||
1087 | default: | 1082 | if (hollowAmount > 0.0) |
1088 | // we don't have all of the volume formulas yet so | 1083 | { |
1089 | // use the common volume formula for all | ||
1090 | volume = _size.X*_size.Y*_size.Z; | ||
1091 | break; | ||
1092 | } | ||
1093 | 1084 | ||
1094 | // Calculate Path cut effect on volume | 1085 | hollowVolume *= hollowAmount; |
1095 | // Not exact, in the triangle hollow example | ||
1096 | // They should never be zero or less then zero.. | ||
1097 | // we'll ignore it if it's less then zero | ||
1098 | 1086 | ||
1099 | // ProfileEnd and ProfileBegin are values | 1087 | switch (_pbs.HollowShape) |
1100 | // from 0 to 50000 | 1088 | { |
1089 | case HollowShape.Same: | ||
1090 | case HollowShape.Triangle: | ||
1091 | hollowVolume *= .25f; | ||
1092 | break; | ||
1101 | 1093 | ||
1102 | // Turning them back into percentages so that I can cut that percentage off the volume | 1094 | case HollowShape.Square: |
1095 | hollowVolume *= 0.499849f * 3.07920140172638f; | ||
1096 | break; | ||
1103 | 1097 | ||
1104 | float PathCutEndAmount = _pbs.ProfileEnd; | 1098 | case HollowShape.Circle: |
1105 | float PathCutStartAmount = _pbs.ProfileBegin; | ||
1106 | if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) | ||
1107 | { | ||
1108 | float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); | ||
1109 | 1099 | ||
1110 | // Check the return amount for sanity | 1100 | hollowVolume *= 0.1963495f * 3.07920140172638f; |
1111 | if (pathCutAmount >= 0.99f) | 1101 | break; |
1112 | pathCutAmount = 0.99f; | ||
1113 | 1102 | ||
1114 | volume = volume - (volume*pathCutAmount); | 1103 | default: |
1115 | } | 1104 | hollowVolume = 0; |
1116 | UInt16 taperX = _pbs.PathScaleX; | 1105 | break; |
1117 | UInt16 taperY = _pbs.PathScaleY; | 1106 | } |
1118 | float taperFactorX = 0; | 1107 | volume *= (1.0f - hollowVolume); |
1119 | float taperFactorY = 0; | 1108 | } |
1109 | } | ||
1110 | break; | ||
1120 | 1111 | ||
1121 | // Mass = density * volume | 1112 | default: |
1122 | if (taperX != 100) | 1113 | break; |
1123 | { | ||
1124 | if (taperX > 100) | ||
1125 | { | ||
1126 | taperFactorX = 1.0f - ((float)taperX / 200); | ||
1127 | //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); | ||
1128 | } | ||
1129 | else | ||
1130 | { | ||
1131 | taperFactorX = 1.0f - ((100 - (float)taperX) / 100); | ||
1132 | //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); | ||
1133 | } | 1114 | } |
1134 | volume = (float)volume * ((taperFactorX / 3f) + 0.001f); | ||
1135 | } | ||
1136 | 1115 | ||
1137 | if (taperY != 100) | 1116 | |
1138 | { | 1117 | |
1139 | if (taperY > 100) | 1118 | float taperX1; |
1119 | float taperY1; | ||
1120 | float taperX; | ||
1121 | float taperY; | ||
1122 | float pathBegin; | ||
1123 | float pathEnd; | ||
1124 | float profileBegin; | ||
1125 | float profileEnd; | ||
1126 | |||
1127 | if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) | ||
1140 | { | 1128 | { |
1141 | taperFactorY = 1.0f - ((float)taperY / 200); | 1129 | taperX1 = _pbs.PathScaleX * 0.01f; |
1142 | //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); | 1130 | if (taperX1 > 1.0f) |
1131 | taperX1 = 2.0f - taperX1; | ||
1132 | taperX = 1.0f - taperX1; | ||
1133 | |||
1134 | taperY1 = _pbs.PathScaleY * 0.01f; | ||
1135 | if (taperY1 > 1.0f) | ||
1136 | taperY1 = 2.0f - taperY1; | ||
1137 | taperY = 1.0f - taperY1; | ||
1143 | } | 1138 | } |
1144 | else | 1139 | else |
1145 | { | 1140 | { |
1146 | taperFactorY = 1.0f - ((100 - (float)taperY) / 100); | 1141 | taperX = _pbs.PathTaperX * 0.01f; |
1147 | //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); | 1142 | if (taperX < 0.0f) |
1143 | taperX = -taperX; | ||
1144 | taperX1 = 1.0f - taperX; | ||
1145 | |||
1146 | taperY = _pbs.PathTaperY * 0.01f; | ||
1147 | if (taperY < 0.0f) | ||
1148 | taperY = -taperY; | ||
1149 | taperY1 = 1.0f - taperY; | ||
1150 | |||
1148 | } | 1151 | } |
1149 | volume = (float)volume * ((taperFactorY / 3f) + 0.001f); | 1152 | |
1150 | } | 1153 | |
1151 | returnMass = m_density*volume; | 1154 | volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); |
1152 | if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. | 1155 | |
1156 | pathBegin = (float)_pbs.PathBegin * 2.0e-5f; | ||
1157 | pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; | ||
1158 | volume *= (pathEnd - pathBegin); | ||
1159 | |||
1160 | // this is crude aproximation | ||
1161 | profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; | ||
1162 | profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; | ||
1163 | volume *= (profileEnd - profileBegin); | ||
1164 | |||
1165 | returnMass = m_density * volume; | ||
1166 | |||
1167 | if (returnMass <= 0) | ||
1168 | returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. | ||
1169 | // else if (returnMass > _parent_scene.maximumMassObject) | ||
1170 | // returnMass = _parent_scene.maximumMassObject; | ||
1171 | |||
1153 | 1172 | ||
1154 | 1173 | ||
1155 | 1174 | ||
@@ -1280,7 +1299,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1280 | disableBody(); | 1299 | disableBody(); |
1281 | } | 1300 | } |
1282 | } | 1301 | } |
1283 | |||
1284 | IntPtr vertices, indices; | 1302 | IntPtr vertices, indices; |
1285 | int vertexCount, indexCount; | 1303 | int vertexCount, indexCount; |
1286 | int vertexStride, triStride; | 1304 | int vertexStride, triStride; |
@@ -1304,10 +1322,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1304 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1322 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1305 | try | 1323 | try |
1306 | { | 1324 | { |
1307 | if (prim_geom == IntPtr.Zero) | 1325 | // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer |
1308 | { | 1326 | // { |
1309 | SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); | 1327 | SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); |
1310 | } | 1328 | // } |
1311 | } | 1329 | } |
1312 | catch (AccessViolationException) | 1330 | catch (AccessViolationException) |
1313 | { | 1331 | { |
@@ -1336,8 +1354,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1336 | if (prim_geom != IntPtr.Zero) | 1354 | if (prim_geom != IntPtr.Zero) |
1337 | { | 1355 | { |
1338 | if (!_position.ApproxEquals(m_taintposition, 0f)) | 1356 | if (!_position.ApproxEquals(m_taintposition, 0f)) |
1357 | { | ||
1339 | changemove(timestep); | 1358 | changemove(timestep); |
1340 | 1359 | } | |
1341 | if (m_taintrot != _orientation) | 1360 | if (m_taintrot != _orientation) |
1342 | { | 1361 | { |
1343 | if(childPrim && IsPhysical) // For physical child prim... | 1362 | if(childPrim && IsPhysical) // For physical child prim... |
@@ -1357,8 +1376,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1357 | // | 1376 | // |
1358 | 1377 | ||
1359 | if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) | 1378 | if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) |
1379 | { | ||
1360 | changePhysicsStatus(timestep); | 1380 | changePhysicsStatus(timestep); |
1361 | // | 1381 | }// |
1362 | 1382 | ||
1363 | if (!_size.ApproxEquals(m_taintsize,0f)) | 1383 | if (!_size.ApproxEquals(m_taintsize,0f)) |
1364 | changesize(timestep); | 1384 | changesize(timestep); |
@@ -1391,10 +1411,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1391 | 1411 | ||
1392 | if (m_taintCollidesWater != m_collidesWater) | 1412 | if (m_taintCollidesWater != m_collidesWater) |
1393 | changefloatonwater(timestep); | 1413 | changefloatonwater(timestep); |
1394 | 1414 | /* obsolete | |
1395 | if (!m_angularEnable.ApproxEquals(m_taintAngularLock,0f)) | 1415 | if (!m_angularLock.ApproxEquals(m_taintAngularLock,0f)) |
1396 | changeAngularLock(timestep); | 1416 | changeAngularLock(timestep); |
1397 | 1417 | */ | |
1398 | } | 1418 | } |
1399 | else | 1419 | else |
1400 | { | 1420 | { |
@@ -1402,15 +1422,16 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1402 | } | 1422 | } |
1403 | } | 1423 | } |
1404 | 1424 | ||
1405 | 1425 | /* obsolete | |
1406 | private void changeAngularLock(float timestep) | 1426 | private void changeAngularLock(float timestep) |
1407 | { | 1427 | { |
1408 | if (_parent == null) | 1428 | if (_parent == null) |
1409 | { | 1429 | { |
1410 | m_angularEnable = m_taintAngularLock; | 1430 | m_angularLock = m_taintAngularLock; |
1431 | m_angularLockSet = true; | ||
1411 | } | 1432 | } |
1412 | } | 1433 | } |
1413 | 1434 | */ | |
1414 | private void changelink(float timestep) | 1435 | private void changelink(float timestep) |
1415 | { | 1436 | { |
1416 | // If the newly set parent is not null | 1437 | // If the newly set parent is not null |
@@ -1468,6 +1489,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1468 | if (Body == IntPtr.Zero) | 1489 | if (Body == IntPtr.Zero) |
1469 | { | 1490 | { |
1470 | Body = d.BodyCreate(_parent_scene.world); | 1491 | Body = d.BodyCreate(_parent_scene.world); |
1492 | // disconnect from world gravity so we can apply buoyancy | ||
1493 | d.BodySetGravityMode (Body, false); | ||
1494 | |||
1471 | setMass(); | 1495 | setMass(); |
1472 | } | 1496 | } |
1473 | if (Body != IntPtr.Zero) | 1497 | if (Body != IntPtr.Zero) |
@@ -1508,7 +1532,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1508 | m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet"); | 1532 | m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet"); |
1509 | continue; | 1533 | continue; |
1510 | } | 1534 | } |
1511 | //Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + m_primName); | ||
1512 | d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); | 1535 | d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); |
1513 | d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); | 1536 | d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); |
1514 | 1537 | ||
@@ -1551,9 +1574,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1551 | m_collisionCategories |= CollisionCategories.Body; | 1574 | m_collisionCategories |= CollisionCategories.Body; |
1552 | m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); | 1575 | m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); |
1553 | 1576 | ||
1554 | //Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + m_primName); | ||
1555 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); | 1577 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); |
1556 | //Console.WriteLine(" Post GeomSetCategoryBits 2"); | ||
1557 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); | 1578 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); |
1558 | 1579 | ||
1559 | 1580 | ||
@@ -1708,6 +1729,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1708 | { | 1729 | { |
1709 | disableBodySoft(); | 1730 | disableBodySoft(); |
1710 | } | 1731 | } |
1732 | if (Body != IntPtr.Zero) | ||
1733 | { | ||
1734 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | ||
1735 | d.BodySetForce(Body, 0f, 0f, 0f); | ||
1736 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
1737 | d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f); | ||
1738 | } | ||
1739 | |||
1711 | } | 1740 | } |
1712 | else | 1741 | else |
1713 | { | 1742 | { |
@@ -1728,12 +1757,18 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1728 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); | 1757 | d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); |
1729 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); | 1758 | d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); |
1730 | } | 1759 | } |
1760 | if (Body != IntPtr.Zero) | ||
1761 | { | ||
1762 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | ||
1763 | d.BodySetForce(Body, 0f, 0f, 0f); | ||
1764 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
1765 | d.BodySetTorque (Body, 0.0f, 0.0f, 0.0f); | ||
1766 | } | ||
1767 | |||
1731 | if (m_isphysical) | 1768 | if (m_isphysical) |
1732 | { | 1769 | { |
1733 | if (Body != IntPtr.Zero) | 1770 | if (Body != IntPtr.Zero) |
1734 | { | 1771 | { |
1735 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | ||
1736 | d.BodySetForce(Body, 0, 0, 0); | ||
1737 | enableBodySoft(); | 1772 | enableBodySoft(); |
1738 | } | 1773 | } |
1739 | } | 1774 | } |
@@ -1758,23 +1793,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1758 | 1793 | ||
1759 | public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) | 1794 | public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) |
1760 | { | 1795 | { |
1761 | //Console.WriteLine("CreateGeom:"); | 1796 | if (_mesh != null) // Special - make mesh |
1762 | if (_mesh != null) | ||
1763 | { | 1797 | { |
1764 | setMesh(_parent_scene, _mesh); | 1798 | setMesh(_parent_scene, _mesh); |
1765 | } | 1799 | } |
1766 | else | 1800 | else // not a mesh |
1767 | { | 1801 | { |
1768 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) | 1802 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) // special profile?? |
1769 | { | 1803 | { |
1770 | if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) | 1804 | if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) // Equi-size |
1771 | { | 1805 | { |
1772 | if (((_size.X / 2f) > 0f)) | 1806 | if (((_size.X / 2f) > 0f)) // Has size |
1773 | { | 1807 | { |
1774 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1808 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1775 | try | 1809 | try |
1776 | { | 1810 | { |
1777 | //Console.WriteLine(" CreateGeom 1"); | ||
1778 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); | 1811 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); |
1779 | } | 1812 | } |
1780 | catch (AccessViolationException) | 1813 | catch (AccessViolationException) |
@@ -1789,7 +1822,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1789 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1822 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1790 | try | 1823 | try |
1791 | { | 1824 | { |
1792 | //Console.WriteLine(" CreateGeom 2"); | ||
1793 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1825 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1794 | } | 1826 | } |
1795 | catch (AccessViolationException) | 1827 | catch (AccessViolationException) |
@@ -1800,12 +1832,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1800 | } | 1832 | } |
1801 | } | 1833 | } |
1802 | } | 1834 | } |
1803 | else | 1835 | else // not equi-size |
1804 | { | 1836 | { |
1805 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1837 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1806 | try | 1838 | try |
1807 | { | 1839 | { |
1808 | //Console.WriteLine(" CreateGeom 3"); | ||
1809 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1840 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1810 | } | 1841 | } |
1811 | catch (AccessViolationException) | 1842 | catch (AccessViolationException) |
@@ -1817,12 +1848,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1817 | } | 1848 | } |
1818 | } | 1849 | } |
1819 | 1850 | ||
1820 | else | 1851 | else // not special profile |
1821 | { | 1852 | { |
1822 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1853 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
1823 | try | 1854 | try |
1824 | { | 1855 | { |
1825 | //Console.WriteLine(" CreateGeom 4"); | ||
1826 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 1856 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); |
1827 | } | 1857 | } |
1828 | catch (AccessViolationException) | 1858 | catch (AccessViolationException) |
@@ -1845,12 +1875,20 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1845 | 1875 | ||
1846 | m_targetSpace = targetspace; | 1876 | m_targetSpace = targetspace; |
1847 | 1877 | ||
1848 | if (_mesh == null) | 1878 | if (_mesh == null && m_meshfailed == false) |
1849 | { | 1879 | { |
1850 | if (_parent_scene.needsMeshing(_pbs)) | 1880 | if (_parent_scene.needsMeshing(_pbs)) |
1851 | { | 1881 | { |
1852 | // Don't need to re-enable body.. it's done in SetMesh | 1882 | // Don't need to re-enable body.. it's done in SetMesh |
1853 | _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); | 1883 | try |
1884 | { | ||
1885 | _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); | ||
1886 | } | ||
1887 | catch | ||
1888 | { | ||
1889 | //Don't continuously try to mesh prims when meshing has failed | ||
1890 | m_meshfailed = true; | ||
1891 | } | ||
1854 | // createmesh returns null when it's a shape that isn't a cube. | 1892 | // createmesh returns null when it's a shape that isn't a cube. |
1855 | // m_log.Debug(m_localID); | 1893 | // m_log.Debug(m_localID); |
1856 | } | 1894 | } |
@@ -1859,7 +1897,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1859 | 1897 | ||
1860 | lock (_parent_scene.OdeLock) | 1898 | lock (_parent_scene.OdeLock) |
1861 | { | 1899 | { |
1862 | //Console.WriteLine("changeadd 1"); | ||
1863 | CreateGeom(m_targetSpace, _mesh); | 1900 | CreateGeom(m_targetSpace, _mesh); |
1864 | 1901 | ||
1865 | if (prim_geom != IntPtr.Zero) | 1902 | if (prim_geom != IntPtr.Zero) |
@@ -1879,9 +1916,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1879 | } | 1916 | } |
1880 | } | 1917 | } |
1881 | 1918 | ||
1882 | _parent_scene.geom_name_map[prim_geom] = this.m_primName; | ||
1883 | _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; | ||
1884 | |||
1885 | changeSelectedStatus(timestep); | 1919 | changeSelectedStatus(timestep); |
1886 | 1920 | ||
1887 | m_taintadd = false; | 1921 | m_taintadd = false; |
@@ -1889,10 +1923,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1889 | 1923 | ||
1890 | public void changemove(float timestep) | 1924 | public void changemove(float timestep) |
1891 | { | 1925 | { |
1892 | //Console.WriteLine("changemove sing/root {0} to {1}", m_primName, _position ); | ||
1893 | if (m_isphysical) | 1926 | if (m_isphysical) |
1894 | { | 1927 | { |
1895 | //Console.WriteLine("phys {0} {1} {2}", m_disabled, m_taintremove, childPrim); | ||
1896 | // if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits! | 1928 | // if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits! |
1897 | if (!m_taintremove && !childPrim) | 1929 | if (!m_taintremove && !childPrim) |
1898 | { | 1930 | { |
@@ -1918,7 +1950,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1918 | if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body) | 1950 | if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body) |
1919 | { | 1951 | { |
1920 | // KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used?? | 1952 | // KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used?? |
1921 | Console.WriteLine(" JointCreateFixed"); | 1953 | Console.WriteLine("ODEPrim JointCreateFixed !!!"); |
1922 | m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); | 1954 | m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); |
1923 | d.JointAttach(m_linkJoint, Body, odParent.Body); | 1955 | d.JointAttach(m_linkJoint, Body, odParent.Body); |
1924 | d.JointSetFixed(m_linkJoint); | 1956 | d.JointSetFixed(m_linkJoint); |
@@ -2030,23 +2062,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2030 | { | 2062 | { |
2031 | if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) | 2063 | if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) |
2032 | { | 2064 | { |
2033 | 2065 | _mesh = null; | |
2034 | |||
2035 | if (prim_geom != IntPtr.Zero) | ||
2036 | { | ||
2037 | try | ||
2038 | { | ||
2039 | d.GeomDestroy(prim_geom); | ||
2040 | prim_geom = IntPtr.Zero; | ||
2041 | _mesh = null; | ||
2042 | } | ||
2043 | catch (System.AccessViolationException) | ||
2044 | { | ||
2045 | prim_geom = IntPtr.Zero; | ||
2046 | m_log.Error("[PHYSICS]: PrimGeom dead"); | ||
2047 | } | ||
2048 | } | ||
2049 | //Console.WriteLine("changePhysicsStatus for " + m_primName ); | ||
2050 | changeadd(2f); | 2066 | changeadd(2f); |
2051 | } | 2067 | } |
2052 | if (childPrim) | 2068 | if (childPrim) |
@@ -2105,12 +2121,10 @@ Console.WriteLine(" JointCreateFixed"); | |||
2105 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 2121 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
2106 | d.SpaceRemove(m_targetSpace, prim_geom); | 2122 | d.SpaceRemove(m_targetSpace, prim_geom); |
2107 | } | 2123 | } |
2108 | d.GeomDestroy(prim_geom); | ||
2109 | prim_geom = IntPtr.Zero; | ||
2110 | // we don't need to do space calculation because the client sends a position update also. | 2124 | // we don't need to do space calculation because the client sends a position update also. |
2111 | 2125 | ||
2112 | // Construction of new prim | 2126 | // Construction of new prim |
2113 | if (_parent_scene.needsMeshing(_pbs)) | 2127 | if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false) |
2114 | { | 2128 | { |
2115 | float meshlod = _parent_scene.meshSculptLOD; | 2129 | float meshlod = _parent_scene.meshSculptLOD; |
2116 | 2130 | ||
@@ -2120,11 +2134,17 @@ Console.WriteLine(" JointCreateFixed"); | |||
2120 | 2134 | ||
2121 | IMesh mesh = null; | 2135 | IMesh mesh = null; |
2122 | 2136 | ||
2123 | if (_parent_scene.needsMeshing(_pbs)) | 2137 | try |
2124 | mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | 2138 | { |
2139 | if (_parent_scene.needsMeshing(_pbs)) | ||
2140 | mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | ||
2141 | } | ||
2142 | catch | ||
2143 | { | ||
2144 | m_meshfailed = true; | ||
2145 | } | ||
2125 | 2146 | ||
2126 | //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | 2147 | //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); |
2127 | //Console.WriteLine("changesize 1"); | ||
2128 | CreateGeom(m_targetSpace, mesh); | 2148 | CreateGeom(m_targetSpace, mesh); |
2129 | 2149 | ||
2130 | 2150 | ||
@@ -2132,7 +2152,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
2132 | else | 2152 | else |
2133 | { | 2153 | { |
2134 | _mesh = null; | 2154 | _mesh = null; |
2135 | //Console.WriteLine("changesize 2"); | ||
2136 | CreateGeom(m_targetSpace, _mesh); | 2155 | CreateGeom(m_targetSpace, _mesh); |
2137 | } | 2156 | } |
2138 | 2157 | ||
@@ -2208,38 +2227,35 @@ Console.WriteLine(" JointCreateFixed"); | |||
2208 | disableBody(); | 2227 | disableBody(); |
2209 | } | 2228 | } |
2210 | } | 2229 | } |
2211 | try | 2230 | |
2212 | { | 2231 | |
2213 | d.GeomDestroy(prim_geom); | ||
2214 | } | ||
2215 | catch (System.AccessViolationException) | ||
2216 | { | ||
2217 | prim_geom = IntPtr.Zero; | ||
2218 | m_log.Error("[PHYSICS]: PrimGeom dead"); | ||
2219 | } | ||
2220 | prim_geom = IntPtr.Zero; | ||
2221 | // we don't need to do space calculation because the client sends a position update also. | 2232 | // we don't need to do space calculation because the client sends a position update also. |
2222 | if (_size.X <= 0) _size.X = 0.01f; | 2233 | if (_size.X <= 0) _size.X = 0.01f; |
2223 | if (_size.Y <= 0) _size.Y = 0.01f; | 2234 | if (_size.Y <= 0) _size.Y = 0.01f; |
2224 | if (_size.Z <= 0) _size.Z = 0.01f; | 2235 | if (_size.Z <= 0) _size.Z = 0.01f; |
2225 | // Construction of new prim | 2236 | // Construction of new prim |
2226 | 2237 | ||
2227 | if (_parent_scene.needsMeshing(_pbs)) | 2238 | if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false) |
2228 | { | 2239 | { |
2229 | // Don't need to re-enable body.. it's done in SetMesh | 2240 | // Don't need to re-enable body.. it's done in SetMesh |
2230 | float meshlod = _parent_scene.meshSculptLOD; | 2241 | float meshlod = _parent_scene.meshSculptLOD; |
2231 | 2242 | ||
2232 | if (IsPhysical) | 2243 | if (IsPhysical) |
2233 | meshlod = _parent_scene.MeshSculptphysicalLOD; | 2244 | meshlod = _parent_scene.MeshSculptphysicalLOD; |
2234 | 2245 | try | |
2235 | IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | 2246 | { |
2247 | IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | ||
2248 | CreateGeom(m_targetSpace, mesh); | ||
2249 | } | ||
2250 | catch | ||
2251 | { | ||
2252 | m_meshfailed = true; | ||
2253 | } | ||
2236 | // createmesh returns null when it doesn't mesh. | 2254 | // createmesh returns null when it doesn't mesh. |
2237 | CreateGeom(m_targetSpace, mesh); | ||
2238 | } | 2255 | } |
2239 | else | 2256 | else |
2240 | { | 2257 | { |
2241 | _mesh = null; | 2258 | _mesh = null; |
2242 | //Console.WriteLine("changeshape"); | ||
2243 | CreateGeom(m_targetSpace, null); | 2259 | CreateGeom(m_targetSpace, null); |
2244 | } | 2260 | } |
2245 | 2261 | ||
@@ -2314,6 +2330,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2314 | return; | 2330 | return; |
2315 | } | 2331 | } |
2316 | d.BodyEnable(Body); | 2332 | d.BodyEnable(Body); |
2333 | |||
2317 | d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); | 2334 | d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); |
2318 | } | 2335 | } |
2319 | m_forcelist.Clear(); | 2336 | m_forcelist.Clear(); |
@@ -2421,7 +2438,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
2421 | { | 2438 | { |
2422 | if (CollisionEventsThisFrame == null) | 2439 | if (CollisionEventsThisFrame == null) |
2423 | CollisionEventsThisFrame = new CollisionEventUpdate(); | 2440 | CollisionEventsThisFrame = new CollisionEventUpdate(); |
2424 | CollisionEventsThisFrame.addCollider(CollidedWith, contact); | 2441 | CollisionEventsThisFrame.AddCollider(CollidedWith, contact); |
2425 | } | 2442 | } |
2426 | 2443 | ||
2427 | public void SendCollisions() | 2444 | public void SendCollisions() |
@@ -2985,13 +3002,10 @@ Console.WriteLine(" JointCreateFixed"); | |||
2985 | // This is a temp patch until proper region crossing is developed. | 3002 | // This is a temp patch until proper region crossing is developed. |
2986 | 3003 | ||
2987 | int failureLimit = _parent_scene.geomCrossingFailuresBeforeOutofbounds; | 3004 | int failureLimit = _parent_scene.geomCrossingFailuresBeforeOutofbounds; |
2988 | int fence = _parent_scene.geomRegionFence; | 3005 | float fence = _parent_scene.geomRegionFence; |
2989 | 3006 | ||
2990 | float border_limit = 0.05f; // original limit | 3007 | frcount++; // used to limit debug comment output |
2991 | if (fence == 1) border_limit = 0.5f; // bounce point | 3008 | if (frcount > 50) |
2992 | |||
2993 | frcount++; // used to limit debug comment output | ||
2994 | if (frcount > 10) | ||
2995 | frcount = 0; | 3009 | frcount = 0; |
2996 | 3010 | ||
2997 | if(revcount > 0) revcount--; | 3011 | if(revcount > 0) revcount--; |
@@ -3033,35 +3047,34 @@ Console.WriteLine(" JointCreateFixed"); | |||
3033 | 3047 | ||
3034 | // Check if outside region | 3048 | // Check if outside region |
3035 | // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border! | 3049 | // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border! |
3036 | if (l_position.X > ((float)_parent_scene.WorldExtents.X - border_limit)) | 3050 | if (l_position.X > ((float)_parent_scene.WorldExtents.X - fence)) |
3037 | { | 3051 | { |
3038 | l_position.X = ((float)_parent_scene.WorldExtents.X - border_limit); | 3052 | l_position.X = ((float)_parent_scene.WorldExtents.X - fence); |
3039 | outside = 1; | 3053 | outside = 1; |
3040 | } | 3054 | } |
3041 | 3055 | ||
3042 | if (l_position.X < border_limit) | 3056 | if (l_position.X < fence) |
3043 | { | 3057 | { |
3044 | l_position.X = border_limit; | 3058 | l_position.X = fence; |
3045 | outside = 2; | 3059 | outside = 2; |
3046 | } | 3060 | } |
3047 | if (l_position.Y > ((float)_parent_scene.WorldExtents.Y - border_limit)) | 3061 | if (l_position.Y > ((float)_parent_scene.WorldExtents.Y - fence)) |
3048 | { | 3062 | { |
3049 | l_position.Y = ((float)_parent_scene.WorldExtents.Y - border_limit); | 3063 | l_position.Y = ((float)_parent_scene.WorldExtents.Y - fence); |
3050 | outside = 3; | 3064 | outside = 3; |
3051 | } | 3065 | } |
3052 | 3066 | ||
3053 | if (l_position.Y < border_limit) | 3067 | if (l_position.Y < fence) |
3054 | { | 3068 | { |
3055 | l_position.Y = border_limit; | 3069 | l_position.Y = fence; |
3056 | outside = 4; | 3070 | outside = 4; |
3057 | } | 3071 | } |
3058 | 3072 | ||
3059 | if (outside > 0) | 3073 | if (outside > 0) |
3060 | { | 3074 | { |
3061 | //Console.WriteLine(" fence = {0}",fence); | ||
3062 | 3075 | ||
3063 | //Console.WriteLine("Border {0}", l_position); | 3076 | //Console.WriteLine("Border {0} fence={1}", l_position, fence); |
3064 | if (fence == 1) // bounce object off boundary | 3077 | if (fence > 0.0f) // bounce object off boundary |
3065 | { | 3078 | { |
3066 | if (revcount == 0) | 3079 | if (revcount == 0) |
3067 | { | 3080 | { |
@@ -3095,8 +3108,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
3095 | else | 3108 | else |
3096 | { // Too many tries | 3109 | { // Too many tries |
3097 | if (_parent == null) base.RaiseOutOfBounds(l_position); | 3110 | if (_parent == null) base.RaiseOutOfBounds(l_position); |
3098 | //Console.WriteLine("ROOB 2"); | ||
3099 | |||
3100 | return; // Dont process any other motion? | 3111 | return; // Dont process any other motion? |
3101 | } // end various methods | 3112 | } // end various methods |
3102 | } // end outside region horizontally | 3113 | } // end outside region horizontally |
@@ -3112,7 +3123,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
3112 | 3123 | ||
3113 | //IsPhysical = false; | 3124 | //IsPhysical = false; |
3114 | if (_parent == null) base.RaiseOutOfBounds(_position); | 3125 | if (_parent == null) base.RaiseOutOfBounds(_position); |
3115 | //Console.WriteLine("ROOB 3"); | ||
3116 | 3126 | ||
3117 | 3127 | ||
3118 | _acceleration.X = 0; // This stuff may stop client display but it has no | 3128 | _acceleration.X = 0; // This stuff may stop client display but it has no |
@@ -3122,6 +3132,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
3122 | _velocity.X = 0; | 3132 | _velocity.X = 0; |
3123 | _velocity.Y = 0; | 3133 | _velocity.Y = 0; |
3124 | _velocity.Z = 0; | 3134 | _velocity.Z = 0; |
3135 | m_lastVelocity = Vector3.Zero; | ||
3125 | m_rotationalVelocity.X = 0; | 3136 | m_rotationalVelocity.X = 0; |
3126 | m_rotationalVelocity.Y = 0; | 3137 | m_rotationalVelocity.Y = 0; |
3127 | m_rotationalVelocity.Z = 0; | 3138 | m_rotationalVelocity.Z = 0; |
@@ -3135,10 +3146,12 @@ Console.WriteLine(" JointCreateFixed"); | |||
3135 | } // end neg Z check | 3146 | } // end neg Z check |
3136 | 3147 | ||
3137 | // Is it moving? | 3148 | // Is it moving? |
3138 | if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) | 3149 | /* if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) |
3139 | && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) | 3150 | && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) |
3140 | && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) | 3151 | && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) */ |
3141 | && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001)) // KF 0.01 is far to large | 3152 | if ( (Vector3.Mag(_velocity) < 0.01) && // moving very slowly |
3153 | (Vector3.Mag(_velocity) < Vector3.Mag(m_lastVelocity)) && // decelerating | ||
3154 | (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001) ) // spinning very slowly | ||
3142 | { | 3155 | { |
3143 | _zeroFlag = true; | 3156 | _zeroFlag = true; |
3144 | m_throttleUpdates = false; | 3157 | m_throttleUpdates = false; |
@@ -3155,15 +3168,20 @@ Console.WriteLine(" JointCreateFixed"); | |||
3155 | { // Its stopped | 3168 | { // Its stopped |
3156 | _velocity.X = 0.0f; | 3169 | _velocity.X = 0.0f; |
3157 | _velocity.Y = 0.0f; | 3170 | _velocity.Y = 0.0f; |
3158 | _velocity.Z = 0.0f; | 3171 | // _velocity.Z = 0.0f; |
3159 | 3172 | ||
3160 | _acceleration.X = 0; | 3173 | _acceleration.X = 0; |
3161 | _acceleration.Y = 0; | 3174 | _acceleration.Y = 0; |
3162 | _acceleration.Z = 0; | 3175 | // _acceleration.Z = 0; |
3163 | 3176 | ||
3164 | m_rotationalVelocity.X = 0; | 3177 | m_rotationalVelocity.X = 0; |
3165 | m_rotationalVelocity.Y = 0; | 3178 | m_rotationalVelocity.Y = 0; |
3166 | m_rotationalVelocity.Z = 0; | 3179 | m_rotationalVelocity.Z = 0; |
3180 | // Stop it in the phys engine | ||
3181 | d.BodySetLinearVel(Body, 0.0f, 0.0f, _velocity.Z); | ||
3182 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
3183 | d.BodySetForce(Body, 0f, 0f, 0f); | ||
3184 | |||
3167 | if (!m_lastUpdateSent) | 3185 | if (!m_lastUpdateSent) |
3168 | { | 3186 | { |
3169 | m_throttleUpdates = false; | 3187 | m_throttleUpdates = false; |
@@ -3200,8 +3218,91 @@ Console.WriteLine(" JointCreateFixed"); | |||
3200 | } | 3218 | } |
3201 | m_lastposition = l_position; | 3219 | m_lastposition = l_position; |
3202 | 3220 | ||
3203 | /// End UpdatePositionAndVelocity insert | 3221 | /// End UpdatePositionAndVelocity insert |
3204 | 3222 | ||
3223 | |||
3224 | // Rotation lock ===================================== | ||
3225 | if(m_rotateEnableUpdate) | ||
3226 | { | ||
3227 | // Snapshot current angles, set up Amotor(s) | ||
3228 | m_rotateEnableUpdate = false; | ||
3229 | m_rotateEnable = m_rotateEnableRequest; | ||
3230 | //Console.WriteLine("RotEnable {0} = {1}",m_primName, m_rotateEnable); | ||
3231 | |||
3232 | if (Amotor != IntPtr.Zero) | ||
3233 | { | ||
3234 | d.JointDestroy(Amotor); | ||
3235 | Amotor = IntPtr.Zero; | ||
3236 | //Console.WriteLine("Old Amotor Destroyed"); | ||
3237 | } | ||
3238 | |||
3239 | if (!m_rotateEnable.ApproxEquals(Vector3.One, 0.003f)) | ||
3240 | { // not all are enabled | ||
3241 | d.Quaternion r = d.BodyGetQuaternion(Body); | ||
3242 | Quaternion locrot = new Quaternion(r.X, r.Y, r.Z, r.W); | ||
3243 | // extract the axes vectors | ||
3244 | Vector3 vX = new Vector3(1f,0f,0f); | ||
3245 | Vector3 vY = new Vector3(0f,1f,0f); | ||
3246 | Vector3 vZ = new Vector3(0f,0f,1f); | ||
3247 | vX = vX * locrot; | ||
3248 | vY = vY * locrot; | ||
3249 | vZ = vZ * locrot; | ||
3250 | // snapshot the current angle vectors | ||
3251 | m_lockX = vX; | ||
3252 | m_lockY = vY; | ||
3253 | m_lockZ = vZ; | ||
3254 | // m_lockRot = locrot; | ||
3255 | Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); | ||
3256 | d.JointAttach(Amotor, Body, IntPtr.Zero); | ||
3257 | d.JointSetAMotorMode(Amotor, 0); // User mode?? | ||
3258 | //Console.WriteLine("New Amotor Created for {0}", m_primName); | ||
3259 | |||
3260 | float axisnum = 3; // how many to lock | ||
3261 | axisnum = (axisnum - (m_rotateEnable.X + m_rotateEnable.Y + m_rotateEnable.Z)); | ||
3262 | d.JointSetAMotorNumAxes(Amotor,(int)axisnum); | ||
3263 | //Console.WriteLine("AxisNum={0}",(int)axisnum); | ||
3264 | |||
3265 | int i = 0; | ||
3266 | |||
3267 | if (m_rotateEnable.X == 0) | ||
3268 | { | ||
3269 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockX.X, m_lockX.Y, m_lockX.Z); | ||
3270 | //Console.WriteLine("AxisX {0} set to {1}", i, m_lockX); | ||
3271 | i++; | ||
3272 | } | ||
3273 | |||
3274 | if (m_rotateEnable.Y == 0) | ||
3275 | { | ||
3276 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockY.X, m_lockY.Y, m_lockY.Z); | ||
3277 | //Console.WriteLine("AxisY {0} set to {1}", i, m_lockY); | ||
3278 | i++; | ||
3279 | } | ||
3280 | |||
3281 | if (m_rotateEnable.Z == 0) | ||
3282 | { | ||
3283 | d.JointSetAMotorAxis(Amotor, i, 0, m_lockZ.X, m_lockZ.Y, m_lockZ.Z); | ||
3284 | //Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); | ||
3285 | i++; | ||
3286 | } | ||
3287 | |||
3288 | // These lowstops and high stops are effectively (no wiggle room) | ||
3289 | d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0f); | ||
3290 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f); | ||
3291 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0f); | ||
3292 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f); | ||
3293 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); | ||
3294 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f); | ||
3295 | d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 0f); | ||
3296 | d.JointSetAMotorParam(Amotor, (int) dParam.Vel3, 0f); | ||
3297 | d.JointSetAMotorParam(Amotor, (int) dParam.Vel2, 0f); | ||
3298 | d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f); | ||
3299 | d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f); | ||
3300 | d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f); | ||
3301 | } // else none are locked | ||
3302 | } // end Rotation Update | ||
3303 | |||
3304 | |||
3305 | // VEHICLE processing ========================================== | ||
3205 | if (m_type != Vehicle.TYPE_NONE) | 3306 | if (m_type != Vehicle.TYPE_NONE) |
3206 | { | 3307 | { |
3207 | // get body attitude | 3308 | // get body attitude |
@@ -3213,7 +3314,6 @@ Console.WriteLine(" JointCreateFixed"); | |||
3213 | d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame | 3314 | d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame |
3214 | Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z); | 3315 | Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z); |
3215 | m_lLinObjectVel = vel_now * irotq; | 3316 | m_lLinObjectVel = vel_now * irotq; |
3216 | |||
3217 | if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate | 3317 | if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate |
3218 | { | 3318 | { |
3219 | if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f) | 3319 | if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f) |
@@ -3339,7 +3439,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
3339 | d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); | 3439 | d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); |
3340 | // apply gravity force | 3440 | // apply gravity force |
3341 | d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); | 3441 | d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); |
3342 | //if(frcount == 0) Console.WriteLine("Grav {0}", grav); | 3442 | //if(frcount == 0) Console.WriteLine("Vel={0} Force={1}",linvel , grav); |
3343 | // end MoveLinear() | 3443 | // end MoveLinear() |
3344 | 3444 | ||
3345 | 3445 | ||
@@ -3420,7 +3520,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
3420 | //if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); | 3520 | //if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); |
3421 | 3521 | ||
3422 | 3522 | ||
3423 | // Rotation Axis Disables: | 3523 | /* // Rotation Axis Disables: |
3424 | if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) | 3524 | if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) |
3425 | { | 3525 | { |
3426 | if (m_angularEnable.X == 0) | 3526 | if (m_angularEnable.X == 0) |
@@ -3430,7 +3530,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
3430 | if (m_angularEnable.Z == 0) | 3530 | if (m_angularEnable.Z == 0) |
3431 | angObjectVel.Z = 0f; | 3531 | angObjectVel.Z = 0f; |
3432 | } | 3532 | } |
3433 | 3533 | */ | |
3434 | angObjectVel = angObjectVel * rotq; // ================ Converts to WORLD rotation | 3534 | angObjectVel = angObjectVel * rotq; // ================ Converts to WORLD rotation |
3435 | 3535 | ||
3436 | // Vertical attractor section | 3536 | // Vertical attractor section |
@@ -3500,100 +3600,58 @@ Console.WriteLine(" JointCreateFixed"); | |||
3500 | } // end VEHICLES | 3600 | } // end VEHICLES |
3501 | else | 3601 | else |
3502 | { | 3602 | { |
3603 | // Dyamics (NON-'VEHICLES') are dealt with here ================================================================ | ||
3604 | |||
3503 | if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 | 3605 | if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 |
3504 | // NON-'VEHICLES' are dealt with here | 3606 | |
3505 | /// Dynamics Angular Lock ======================================================================== | 3607 | /// Dynamics Buoyancy |
3506 | if (d.BodyIsEnabled(Body) && !m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) | ||
3507 | { | ||
3508 | d.Vector3 avel2 = d.BodyGetAngularVel(Body); | ||
3509 | if (m_angularEnable.X == 0) | ||
3510 | avel2.X = 0; | ||
3511 | if (m_angularEnable.Y == 0) | ||
3512 | avel2.Y = 0; | ||
3513 | if (m_angularEnable.Z == 0) | ||
3514 | avel2.Z = 0; | ||
3515 | d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); | ||
3516 | } | ||
3517 | |||
3518 | |||
3519 | /// Dynamics Buoyancy =============================================================================== | ||
3520 | //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. | 3608 | //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. |
3521 | // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up | 3609 | // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up |
3522 | // NB Prims in ODE are no subject to global gravity | 3610 | // NB Prims in ODE are no subject to global gravity |
3611 | // This should only affect gravity operations | ||
3612 | |||
3523 | float m_mass = CalculateMass(); | 3613 | float m_mass = CalculateMass(); |
3614 | // calculate z-force due togravity on object. | ||
3524 | fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass | 3615 | fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass |
3525 | 3616 | if ((m_usePID) && (m_PIDTau > 0.0f)) // Dynamics llMoveToTarget. | |
3526 | if (m_usePID) | ||
3527 | { | 3617 | { |
3528 | //if(frcount == 0) Console.WriteLine("PID " + m_primName); | 3618 | fz = 0; // llMoveToTarget ignores gravity. |
3529 | // KF - this is for object MoveToTarget. | 3619 | // it also ignores mass of object, and any physical resting on it. |
3530 | 3620 | // Vector3 m_PIDTarget is where we are going | |
3531 | //if (!d.BodyIsEnabled(Body)) | 3621 | // float m_PIDTau is time to get there |
3532 | //d.BodySetForce(Body, 0f, 0f, 0f); | 3622 | fx = 0; |
3533 | 3623 | fy = 0; | |
3534 | // no lock; for now it's only called from within Simulate() | ||
3535 | |||
3536 | // If the PID Controller isn't active then we set our force | ||
3537 | // calculating base velocity to the current position | ||
3538 | |||
3539 | if ((m_PIDTau < 1) && (m_PIDTau != 0)) | ||
3540 | { | ||
3541 | //PID_G = PID_G / m_PIDTau; | ||
3542 | m_PIDTau = 1; | ||
3543 | } | ||
3544 | |||
3545 | if ((PID_G - m_PIDTau) <= 0) | ||
3546 | { | ||
3547 | PID_G = m_PIDTau + 1; | ||
3548 | } | ||
3549 | //PidStatus = true; | ||
3550 | |||
3551 | // PhysicsVector vec = new PhysicsVector(); | ||
3552 | // d.Vector3 vel = d.BodyGetLinearVel(Body); | ||
3553 | |||
3554 | d.Vector3 pos = d.BodyGetPosition(Body); | 3624 | d.Vector3 pos = d.BodyGetPosition(Body); |
3555 | _target_velocity = | 3625 | Vector3 error = new Vector3( |
3556 | new Vector3( | 3626 | (m_PIDTarget.X - pos.X), |
3557 | (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), | 3627 | (m_PIDTarget.Y - pos.Y), |
3558 | (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), | 3628 | (m_PIDTarget.Z - pos.Z)); |
3559 | (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) | 3629 | if (error.ApproxEquals(Vector3.Zero,0.01f)) |
3560 | ); | 3630 | { // Very close, Jump there and quit move |
3561 | 3631 | ||
3562 | // if velocity is zero, use position control; otherwise, velocity control | ||
3563 | |||
3564 | if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f)) | ||
3565 | { | ||
3566 | // keep track of where we stopped. No more slippin' & slidin' | ||
3567 | |||
3568 | // We only want to deactivate the PID Controller if we think we want to have our surrogate | ||
3569 | // react to the physics scene by moving it's position. | ||
3570 | // Avatar to Avatar collisions | ||
3571 | // Prim to avatar collisions | ||
3572 | |||
3573 | //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); | ||
3574 | //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); | ||
3575 | //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; | ||
3576 | d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); | 3632 | d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); |
3577 | d.BodySetLinearVel(Body, 0, 0, 0); | 3633 | _target_velocity = Vector3.Zero; |
3578 | d.BodyAddForce(Body, 0, 0, fz); | 3634 | d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z); |
3579 | // return; | 3635 | d.BodySetForce(Body, 0f, 0f, 0f); |
3580 | } | 3636 | } |
3581 | else | 3637 | else |
3582 | { | 3638 | { |
3583 | _zeroFlag = false; | 3639 | float scale = 50.0f * timestep / m_PIDTau; |
3584 | 3640 | if ((error.ApproxEquals(Vector3.Zero,0.5f)) && (_target_velocity != Vector3.Zero)) | |
3585 | // We're flying and colliding with something | 3641 | { |
3586 | fx = ((_target_velocity.X) - vel.X) * (PID_D); | 3642 | // Nearby, quit update of velocity |
3587 | fy = ((_target_velocity.Y) - vel.Y) * (PID_D); | 3643 | } |
3588 | 3644 | else | |
3589 | // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; | 3645 | { // Far, calc damped velocity |
3590 | 3646 | _target_velocity = error * scale; | |
3591 | fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); | 3647 | } |
3592 | } | 3648 | d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z); |
3593 | } // end if (m_usePID) | 3649 | } |
3650 | } // end PID MoveToTarget | ||
3594 | 3651 | ||
3652 | |||
3595 | /// Dynamics Hover =================================================================================== | 3653 | /// Dynamics Hover =================================================================================== |
3596 | // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller | 3654 | // Hover PID Controller can only run if the PIDcontroller is not in use. |
3597 | if (m_useHoverPID && !m_usePID) | 3655 | if (m_useHoverPID && !m_usePID) |
3598 | { | 3656 | { |
3599 | //Console.WriteLine("Hover " + m_primName); | 3657 | //Console.WriteLine("Hover " + m_primName); |
@@ -3662,11 +3720,10 @@ Console.WriteLine(" JointCreateFixed"); | |||
3662 | // Avatar to Avatar collisions | 3720 | // Avatar to Avatar collisions |
3663 | // Prim to avatar collisions | 3721 | // Prim to avatar collisions |
3664 | d.Vector3 dlinvel = vel; | 3722 | d.Vector3 dlinvel = vel; |
3665 | |||
3666 | d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); | 3723 | d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); |
3667 | d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z); | 3724 | d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z); |
3668 | d.BodyAddForce(Body, 0, 0, fz); | 3725 | d.BodyAddForce(Body, 0, 0, fz); |
3669 | //KF this prevents furthur motions return; | 3726 | //KF this prevents furthur motions return; |
3670 | } | 3727 | } |
3671 | else | 3728 | else |
3672 | { | 3729 | { |
@@ -3677,57 +3734,11 @@ Console.WriteLine(" JointCreateFixed"); | |||
3677 | } | 3734 | } |
3678 | } // end m_useHoverPID && !m_usePID | 3735 | } // end m_useHoverPID && !m_usePID |
3679 | 3736 | ||
3680 | /// Dynamics RotLookAt ================================================================================= | ||
3681 | if (m_useAPID) | ||
3682 | { | ||
3683 | // RotLookAt, apparently overrides all other rotation sources. Inputs: | ||
3684 | // Quaternion m_APIDTarget | ||
3685 | // float m_APIDStrength // From SL experiments, this is the time to get there | ||
3686 | // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly | ||
3687 | // Also in SL the mass of the object has no effect on time to get there. | ||
3688 | // Factors: | ||
3689 | // get present body rotation | ||
3690 | float limit = 1.0f; | ||
3691 | float scaler = 50f; // adjusts damping time | ||
3692 | float RLAservo = 0f; | ||
3693 | |||
3694 | d.Quaternion rot = d.BodyGetQuaternion(Body); | ||
3695 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); | ||
3696 | Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; | ||
3697 | float diff_angle; | ||
3698 | Vector3 diff_axis; | ||
3699 | rot_diff.GetAxisAngle(out diff_axis, out diff_angle); | ||
3700 | diff_axis.Normalize(); | ||
3701 | if(diff_angle > 0.01f) // diff_angle is always +ve | ||
3702 | { | ||
3703 | // PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); | ||
3704 | Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); | ||
3705 | rotforce = rotforce * rotq; | ||
3706 | if(diff_angle > limit) diff_angle = limit; // cap the rotate rate | ||
3707 | // RLAservo = timestep / m_APIDStrength * m_mass * scaler; | ||
3708 | // rotforce = rotforce * RLAservo * diff_angle ; | ||
3709 | // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); | ||
3710 | RLAservo = timestep / m_APIDStrength * scaler; | ||
3711 | rotforce = rotforce * RLAservo * diff_angle ; | ||
3712 | |||
3713 | if (m_angularEnable.X == 0) | ||
3714 | rotforce.X = 0; | ||
3715 | if (m_angularEnable.Y == 0) | ||
3716 | rotforce.Y = 0; | ||
3717 | if (m_angularEnable.Z == 0) | ||
3718 | rotforce.Z = 0; | ||
3719 | |||
3720 | d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); | ||
3721 | //Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); | ||
3722 | } | ||
3723 | //if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); | ||
3724 | } // end m_useAPID | ||
3725 | 3737 | ||
3726 | /// Dynamics Apply Forces =================================================================================== | 3738 | /// Dynamics Apply Forces =================================================================================== |
3727 | fx *= m_mass; | 3739 | fx *= m_mass; |
3728 | fy *= m_mass; | 3740 | fy *= m_mass; |
3729 | //fz *= m_mass; | 3741 | //fz *= m_mass; |
3730 | |||
3731 | fx += m_force.X; | 3742 | fx += m_force.X; |
3732 | fy += m_force.Y; | 3743 | fy += m_force.Y; |
3733 | fz += m_force.Z; | 3744 | fz += m_force.Z; |
@@ -3744,7 +3755,7 @@ Console.WriteLine(" JointCreateFixed"); | |||
3744 | // this appears to re-enable it incase the surface it is upon vanishes, | 3755 | // this appears to re-enable it incase the surface it is upon vanishes, |
3745 | // and the body should fall again. | 3756 | // and the body should fall again. |
3746 | d.BodySetLinearVel(Body, 0f, 0f, 0f); | 3757 | d.BodySetLinearVel(Body, 0f, 0f, 0f); |
3747 | d.BodySetForce(Body, 0, 0, 0); | 3758 | d.BodySetForce(Body, 0f, 0f, 0f); |
3748 | enableBodySoft(); | 3759 | enableBodySoft(); |
3749 | } | 3760 | } |
3750 | 3761 | ||
@@ -3762,27 +3773,102 @@ Console.WriteLine(" JointCreateFixed"); | |||
3762 | if (fy < nmin) | 3773 | if (fy < nmin) |
3763 | fy = nmin; | 3774 | fy = nmin; |
3764 | d.BodyAddForce(Body, fx, fy, fz); | 3775 | d.BodyAddForce(Body, fx, fy, fz); |
3765 | //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); | 3776 | } // end apply forces |
3766 | } | 3777 | } // end Vehicle/Dynamics |
3767 | } | 3778 | |
3768 | } | 3779 | /// RotLookAt / LookAt ================================================================================= |
3769 | else | 3780 | if (m_useAPID) |
3770 | { // is not physical, or is not a body or is selected | 3781 | { |
3771 | // from old UpdatePositionAndVelocity, ... Not a body.. so Make sure the client isn't interpolating | 3782 | // RotLookAt, apparently overrides all other rotation sources. Inputs: |
3772 | _velocity.X = 0; | 3783 | // Quaternion m_APIDTarget |
3773 | _velocity.Y = 0; | 3784 | // float m_APIDStrength // From SL experiments, this is the time to get there |
3774 | _velocity.Z = 0; | 3785 | // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly |
3775 | 3786 | // Also in SL the mass of the object has no effect on time to get there. | |
3776 | _acceleration.X = 0; | 3787 | // Factors: |
3777 | _acceleration.Y = 0; | 3788 | // get present body rotation |
3778 | _acceleration.Z = 0; | 3789 | float limit = 1.0f; |
3779 | 3790 | float rscaler = 50f; // adjusts rotation damping time | |
3780 | m_rotationalVelocity.X = 0; | 3791 | float lscaler = 10f; // adjusts linear damping time in llLookAt |
3781 | m_rotationalVelocity.Y = 0; | 3792 | float RLAservo = 0f; |
3782 | m_rotationalVelocity.Z = 0; | 3793 | Vector3 diff_axis; |
3783 | _zeroFlag = true; | 3794 | float diff_angle; |
3784 | return; | 3795 | d.Quaternion rot = d.BodyGetQuaternion(Body); // prim present rotation |
3785 | } | 3796 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); |
3786 | } // end Move() | 3797 | Quaternion rtarget = new Quaternion(); |
3798 | |||
3799 | if(m_APIDTarget.W == -99.9f) | ||
3800 | { | ||
3801 | // this is really a llLookAt(), x,y,z is the target vector | ||
3802 | Vector3 target = new Vector3(m_APIDTarget.X, m_APIDTarget.Y, m_APIDTarget.Z); | ||
3803 | Vector3 ospin = new Vector3(1.0f, 0.0f, 0.0f) * rotq; | ||
3804 | Vector3 error = new Vector3(0.0f, 0.0f, 0.0f); | ||
3805 | float twopi = 2.0f * (float)Math.PI; | ||
3806 | Vector3 dir = target - _position; | ||
3807 | dir.Normalize(); | ||
3808 | float tzrot = (float)Math.Atan2(dir.Y, dir.X); | ||
3809 | float txy = (float)Math.Sqrt((dir.X * dir.X) + (dir.Y * dir.Y)); | ||
3810 | float terot = (float)Math.Atan2(dir.Z, txy); | ||
3811 | float ozrot = (float)Math.Atan2(ospin.Y, ospin.X); | ||
3812 | float oxy = (float)Math.Sqrt((ospin.X * ospin.X) + (ospin.Y * ospin.Y)); | ||
3813 | float oerot = (float)Math.Atan2(ospin.Z, oxy); | ||
3814 | float ra = 2.0f * ((rotq.W * rotq.X) + (rotq.Y * rotq.Z)); | ||
3815 | float rb = 1.0f - 2.0f * ((rotq.Y * rotq.Y)+(rotq.X * rotq.X)); | ||
3816 | float roll = (float)Math.Atan2(ra, rb); | ||
3817 | float errorz = tzrot - ozrot; | ||
3818 | if(errorz > (float)Math.PI) errorz -= twopi; | ||
3819 | else if(errorz < -(float)Math.PI) errorz += twopi; | ||
3820 | float errory = oerot - terot; | ||
3821 | if(errory > (float)Math.PI) errory -= twopi; | ||
3822 | else if(errory < -(float)Math.PI) errory += twopi; | ||
3823 | diff_angle = Math.Abs(errorz) + Math.Abs(errory) + Math.Abs(roll); | ||
3824 | if(diff_angle > 0.01f * m_APIDdamper) | ||
3825 | { | ||
3826 | m_APIDdamper = 1.0f; | ||
3827 | RLAservo = timestep / m_APIDStrength * rscaler; | ||
3828 | errorz *= RLAservo; | ||
3829 | errory *= RLAservo; | ||
3830 | error.X = -roll * 8.0f; | ||
3831 | error.Y = errory; | ||
3832 | error.Z = errorz; | ||
3833 | error *= rotq; | ||
3834 | d.BodySetAngularVel (Body, error.X, error.Y, error.Z); | ||
3835 | } | ||
3836 | else | ||
3837 | { | ||
3838 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
3839 | m_APIDdamper = 2.0f; | ||
3840 | } | ||
3841 | } | ||
3842 | else | ||
3843 | { | ||
3844 | // this is a llRotLookAt() | ||
3845 | rtarget = m_APIDTarget; | ||
3846 | |||
3847 | Quaternion rot_diff = Quaternion.Inverse(rotq) * rtarget; // difference to desired rot | ||
3848 | rot_diff.GetAxisAngle(out diff_axis, out diff_angle); // convert to axis to point at & error angle | ||
3849 | //if(frcount == 0) Console.WriteLine("axis {0} angle {1}",diff_axis * 57.3f, diff_angle); | ||
3850 | |||
3851 | // diff_axis.Normalize(); it already is! | ||
3852 | if(diff_angle > 0.01f * m_APIDdamper) // diff_angle is always +ve // if there is enough error | ||
3853 | { | ||
3854 | m_APIDdamper = 1.0f; | ||
3855 | Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); | ||
3856 | rotforce = rotforce * rotq; | ||
3857 | if(diff_angle > limit) diff_angle = limit; // cap the rotate rate | ||
3858 | RLAservo = timestep / m_APIDStrength * lscaler; | ||
3859 | rotforce = rotforce * RLAservo * diff_angle ; | ||
3860 | d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); | ||
3861 | //Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); | ||
3862 | } | ||
3863 | else | ||
3864 | { // close enough | ||
3865 | d.BodySetAngularVel (Body, 0.0f, 0.0f, 0.0f); | ||
3866 | m_APIDdamper = 2.0f; | ||
3867 | } | ||
3868 | } // end llLookAt/llRotLookAt | ||
3869 | //if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); | ||
3870 | } // end m_useAPID | ||
3871 | } // end root prims | ||
3872 | } // end Move() | ||
3787 | } // end class | 3873 | } // end class |
3788 | } | 3874 | } |