diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 31 |
1 files changed, 13 insertions, 18 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 443e7a5..d6316b2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -468,26 +468,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
468 | 468 | ||
469 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke | 469 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke |
470 | 470 | ||
471 | // Old implementation of llRot2Euler. Normalization not required as Atan2 function will | 471 | // Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf |
472 | // only return values >= -PI (-180 degrees) and <= PI (180 degrees). | 472 | // to avoid issues with singularity and rounding with Y rotation of +/- PI/2 |
473 | |||
474 | public LSL_Vector llRot2Euler(LSL_Rotation r) | 473 | public LSL_Vector llRot2Euler(LSL_Rotation r) |
475 | { | 474 | { |
476 | m_host.AddScriptLPS(1); | 475 | LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. |
477 | //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke | 476 | double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. |
478 | LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); | 477 | if (m == 0.0) return new LSL_Vector(); |
479 | double m = (t.x + t.y + t.z + t.s); | 478 | double x = Math.Atan2(-v.y, v.z); |
480 | if (m == 0) return new LSL_Vector(); | 479 | double sin = v.x / m; |
481 | double n = 2 * (r.y * r.s + r.x * r.z); | 480 | if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. |
482 | double p = m * m - n * n; | 481 | double y = Math.Asin(sin); |
483 | if (p > 0) | 482 | // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation |
484 | return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), | 483 | v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); |
485 | Math.Atan2(n, Math.Sqrt(p)), | 484 | double z = Math.Atan2(v.y, v.x); |
486 | Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); | 485 | return new LSL_Vector(x, y, z); |
487 | else if (n > 0) | ||
488 | return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); | ||
489 | else | ||
490 | return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); | ||
491 | } | 486 | } |
492 | 487 | ||
493 | /* From wiki: | 488 | /* From wiki: |