aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation
diff options
context:
space:
mode:
authorJohn Cochran2012-01-03 11:38:38 -0600
committerJustin Clark-Casey (justincc)2012-01-06 21:08:54 +0000
commiteb9bf717264083ad76022dff6a2284ad9393ac38 (patch)
tree378d82e25d21439be3d548b9fad5117fbf9207a1 /OpenSim/Region/ScriptEngine/Shared/Api/Implementation
parentImplement the FetchInventory2 capability. This accompanies the existing Fetc... (diff)
downloadopensim-SC-eb9bf717264083ad76022dff6a2284ad9393ac38.zip
opensim-SC-eb9bf717264083ad76022dff6a2284ad9393ac38.tar.gz
opensim-SC-eb9bf717264083ad76022dff6a2284ad9393ac38.tar.bz2
opensim-SC-eb9bf717264083ad76022dff6a2284ad9393ac38.tar.xz
Replaced llRot2Euler function.
The original function suffered from unexpected results due to rounding errors. An error of only 1 or 2 ulps would cause the code to not detect a singularity at Y rotation +/- PI/2 and take the non-singularity code path. The replacement code does not suffer from wildly inaccurate results at the +/- PI/2 singularity. The check in the code for the singularity isn't strictly needed, but gives more consistent results At the singularity, the X and Z rotations add. The if check simply forces the X rotation to be zero so the entirety of the X+Z rotation is carried by Z. Additionally, the test code has been updated to include test cases that caused the old code to fail. The test algorithm is also updated to perform a more meaningful test. The original code checked if the values against expected values. This could fail at +/- PI rotations since a rotation around an axis by PI causes the identical effect as a rotation by -PI. The new test code checks that the returned angles can be used to recreate a quaternion that causes the same rotation.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs31
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: