diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs | 176 |
1 files changed, 170 insertions, 6 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs index 4e7d5ef..e29ee5a 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs | |||
@@ -283,6 +283,41 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
283 | } | 283 | } |
284 | 284 | ||
285 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke | 285 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke |
286 | |||
287 | // Xantor's new llRot2Euler | ||
288 | public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) | ||
289 | { | ||
290 | m_host.AddScriptLPS(1); | ||
291 | double x, y, z; | ||
292 | double sqw = r.s*r.s; | ||
293 | double sqx = r.x*r.x; | ||
294 | double sqy = r.y*r.y; | ||
295 | double sqz = r.z*r.z; | ||
296 | double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor | ||
297 | double test = r.x*r.y + r.z*r.s; | ||
298 | if (test > 0.499 * unit) // singularity at north pole | ||
299 | { | ||
300 | x = 0; | ||
301 | y = 2 * Math.Atan2(r.x, r.s); | ||
302 | z = Math.PI/2; | ||
303 | return new LSL_Types.Vector3(x, y, z); | ||
304 | } | ||
305 | if (test < -0.499 * unit) // singularity at south pole | ||
306 | { | ||
307 | x = 0; | ||
308 | y = -2 * Math.Atan2(r.x,r.s); | ||
309 | z = -Math.PI/2; | ||
310 | return new LSL_Types.Vector3(x, y, z); | ||
311 | } | ||
312 | x = Math.Atan2(2 * r.x * r.s - 2 * r.y * r.z, -sqx + sqy - sqz + sqw); | ||
313 | y = Math.Atan2(2*r.y*r.s-2*r.x*r.z , sqx - sqy - sqz + sqw); | ||
314 | z = Math.Asin(2*test/unit); | ||
315 | return new LSL_Types.Vector3(x, y, z); | ||
316 | } | ||
317 | |||
318 | |||
319 | // Old implementation of llRot2Euler | ||
320 | /* | ||
286 | public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) | 321 | public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r) |
287 | { | 322 | { |
288 | m_host.AddScriptLPS(1); | 323 | m_host.AddScriptLPS(1); |
@@ -301,7 +336,42 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
301 | else | 336 | else |
302 | return new LSL_Types.Vector3(0.0, -Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); | 337 | return new LSL_Types.Vector3(0.0, -Math.PI / 2, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); |
303 | } | 338 | } |
339 | */ | ||
340 | |||
341 | // Xantor's new llEuler2Rot() | ||
342 | /* From wiki: | ||
343 | The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes | ||
344 | in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, | ||
345 | a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting | ||
346 | vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. | ||
347 | */ | ||
348 | public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) | ||
349 | { | ||
350 | m_host.AddScriptLPS(1); | ||
351 | |||
352 | double x,y,z,s; | ||
353 | |||
354 | double c1 = Math.Cos(v.y / 2); | ||
355 | double s1 = Math.Sin(v.y / 2 ); | ||
356 | double c2 = Math.Cos(v.z / 2 ); | ||
357 | double s2 = Math.Sin(v.z / 2 ); | ||
358 | double c3 = Math.Cos(v.x / 2 ); | ||
359 | double s3 = Math.Sin(v.x / 2 ); | ||
360 | |||
361 | double c1c2 = c1 * c2; | ||
362 | double s1s2 = s1 * s2; | ||
363 | |||
364 | s = c1c2 * c3 - s1s2 * s3; | ||
365 | x = c1c2 * s3 + s1s2 * c3; | ||
366 | y = s1 * c2 * c3 + c1 * s2 * s3; | ||
367 | z = c1 * s2 * c3 - s1 * c2 * s3; | ||
304 | 368 | ||
369 | return new LSL_Types.Quaternion(x, y, z, s); | ||
370 | } | ||
371 | |||
372 | |||
373 | /* | ||
374 | // Old implementation | ||
305 | public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) | 375 | public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) |
306 | { | 376 | { |
307 | m_host.AddScriptLPS(1); | 377 | m_host.AddScriptLPS(1); |
@@ -337,6 +407,9 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
337 | } | 407 | } |
338 | return a; | 408 | return a; |
339 | } | 409 | } |
410 | |||
411 | */ | ||
412 | |||
340 | 413 | ||
341 | public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) | 414 | public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) |
342 | { | 415 | { |
@@ -2721,24 +2794,115 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
2721 | return 0; | 2794 | return 0; |
2722 | } | 2795 | } |
2723 | 2796 | ||
2797 | |||
2798 | /* The new / changed functions were tested with the following LSL script: | ||
2799 | |||
2800 | default | ||
2801 | { | ||
2802 | state_entry() | ||
2803 | { | ||
2804 | rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD); | ||
2805 | |||
2806 | llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot) ); | ||
2807 | llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG)); | ||
2808 | |||
2809 | // convert back and forth between quaternion <-> vector and angle | ||
2810 | |||
2811 | rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot)); | ||
2812 | |||
2813 | llOwnerSay("Old rotation was: "+(string) rot); | ||
2814 | llOwnerSay("re-converted rotation is: "+(string) newrot); | ||
2815 | |||
2816 | llSetRot(rot); // to check the parameters in the prim | ||
2817 | } | ||
2818 | } | ||
2819 | */ | ||
2820 | |||
2821 | |||
2822 | |||
2823 | // Xantor 29/apr/2008 | ||
2824 | // Returns rotation described by rotating angle radians about axis. | ||
2825 | // q = cos(a/2) + i ( x * sin(a/2)) + j (y * sin(a/2)) + k ( z * sin(a/2)) | ||
2724 | public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle) | 2826 | public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle) |
2725 | { | 2827 | { |
2726 | m_host.AddScriptLPS(1); | 2828 | m_host.AddScriptLPS(1); |
2727 | NotImplemented("llAxisAngle2Rot"); | 2829 | |
2728 | return new LSL_Types.Quaternion(); | 2830 | double x, y, z, s, t; |
2831 | |||
2832 | s = Math.Cos(angle / 2); | ||
2833 | t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs | ||
2834 | x = axis.x * t; | ||
2835 | y = axis.y * t; | ||
2836 | z = axis.z * t; | ||
2837 | |||
2838 | return new LSL_Types.Quaternion(x,y,z,s); | ||
2839 | // NotImplemented("llAxisAngle2Rot"); | ||
2729 | } | 2840 | } |
2730 | 2841 | ||
2842 | |||
2843 | // Xantor 29/apr/2008 | ||
2844 | // converts a Quaternion to X,Y,Z axis rotations | ||
2731 | public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot) | 2845 | public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot) |
2732 | { | 2846 | { |
2733 | m_host.AddScriptLPS(1); | 2847 | m_host.AddScriptLPS(1); |
2734 | NotImplemented("llRot2Axis"); | 2848 | double x,y,z; |
2735 | return new LSL_Types.Vector3(); | 2849 | |
2850 | if (rot.s > 1) // normalization needed | ||
2851 | { | ||
2852 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
2853 | rot.z * rot.z + rot.s * rot.s); | ||
2854 | |||
2855 | rot.x /= length; | ||
2856 | rot.y /= length; | ||
2857 | rot.z /= length; | ||
2858 | rot.s /= length; | ||
2859 | |||
2860 | } | ||
2861 | |||
2862 | double angle = 2 * Math.Acos(rot.s); | ||
2863 | double s = Math.Sqrt(1 - rot.s * rot.s); | ||
2864 | if (s < 0.001) | ||
2865 | { | ||
2866 | x = 1; | ||
2867 | y = z = 0; | ||
2868 | } | ||
2869 | else | ||
2870 | { | ||
2871 | x = rot.x / s; // normalise axis | ||
2872 | y = rot.y / s; | ||
2873 | z = rot.z / s; | ||
2874 | } | ||
2875 | |||
2876 | |||
2877 | return new LSL_Types.Vector3(x,y,z); | ||
2878 | |||
2879 | |||
2880 | // NotImplemented("llRot2Axis"); | ||
2736 | } | 2881 | } |
2737 | 2882 | ||
2738 | public void llRot2Angle() | 2883 | |
2884 | // Returns the angle of a quaternion (see llRot2Axis for the axis) | ||
2885 | public double llRot2Angle(LSL_Types.Quaternion rot) | ||
2739 | { | 2886 | { |
2740 | m_host.AddScriptLPS(1); | 2887 | m_host.AddScriptLPS(1); |
2741 | NotImplemented("llRot2Angle"); | 2888 | |
2889 | if (rot.s > 1) // normalization needed | ||
2890 | { | ||
2891 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
2892 | rot.z * rot.z + rot.s * rot.s); | ||
2893 | |||
2894 | rot.x /= length; | ||
2895 | rot.y /= length; | ||
2896 | rot.z /= length; | ||
2897 | rot.s /= length; | ||
2898 | |||
2899 | } | ||
2900 | |||
2901 | double angle = 2 * Math.Acos(rot.s); | ||
2902 | |||
2903 | return angle; | ||
2904 | |||
2905 | // NotImplemented("llRot2Angle"); | ||
2742 | } | 2906 | } |
2743 | 2907 | ||
2744 | public double llAcos(double val) | 2908 | public double llAcos(double val) |