aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common
diff options
context:
space:
mode:
authorCharles Krinke2008-07-17 19:11:56 +0000
committerCharles Krinke2008-07-17 19:11:56 +0000
commit26fd0595d7ebd150df798c63c8bcfd6b7cf3425c (patch)
treec4f252a94a0cd0db46d28426c0cd96123af1417e /OpenSim/Region/ScriptEngine/Common
parentRevert "git merge" (diff)
downloadopensim-SC-26fd0595d7ebd150df798c63c8bcfd6b7cf3425c.zip
opensim-SC-26fd0595d7ebd150df798c63c8bcfd6b7cf3425c.tar.gz
opensim-SC-26fd0595d7ebd150df798c63c8bcfd6b7cf3425c.tar.bz2
opensim-SC-26fd0595d7ebd150df798c63c8bcfd6b7cf3425c.tar.xz
Mantis#1598. Thank you kindly, Matth for a patch that addresses:
The previous implementation of llEuler2Rot was not mathematically incorrect, but it was an awkward way of posing the problem that led to a few degenerate cases which were not handled correctly - for example, PI rotations around X and Z axes were wrong. I put some comments in the source about how I arrived at the current implementation, which I think is easier to read, and gives results that match SL.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs80
1 files changed, 52 insertions, 28 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
index a03d8a6..b53f6c0 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
@@ -354,48 +354,72 @@ namespace OpenSim.Region.ScriptEngine.Common
354 return new LSL_Types.Vector3(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); 354 return new LSL_Types.Vector3(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
355 } 355 }
356 356
357
358 // Xantor's newer llEuler2Rot() *try the second* inverted quaternions (-x,-y,-z,w) as LL seems to like
359 // New and improved, now actually works as described. Prim rotates as expected as does llRot2Euler.
360
361 /* From wiki: 357 /* From wiki:
362 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes 358 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
363 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, 359 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
364 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting 360 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
365 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. 361 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
366 */ 362 */
363
364 /* How we arrived at this llEuler2Rot
365 *
366 * Experiment in SL to determine conventions:
367 * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
368 * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
369 * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
370 *
371 * Important facts about Quaternions
372 * - multiplication is non-commutative (a*b != b*a)
373 * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
374 *
375 * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
376 * Qx = c1+i*s1
377 * Qy = c2+j*s2;
378 * Qz = c3+k*s3;
379 *
380 * Rotations applied in order (from above) Z, Y, X
381 * Q = (Qz * Qy) * Qx
382 * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
383 * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
384 * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
385 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
386 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
387 * regroup: x=i*(s1*c2*c3+c1*s2*s3)
388 * y=j*(c1*s2*c3-s1*c2*s3)
389 * z=k*(s1*s2*c3+c1*c2*s3)
390 * s= c1*c2*c3-s1*s2*s3
391 *
392 * This implementation agrees with the functions found here:
393 * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
394 * And with the results in SL.
395 *
396 * It's also possible to calculate llEuler2Rot by direct multiplication of
397 * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
398 * from the wiki).
399 * Apparently in some cases this is better from a numerical precision perspective?
400 */
367 401
368 public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v) 402 public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v)
369 { 403 {
370 m_host.AddScriptLPS(1); 404 m_host.AddScriptLPS(1);
371 405
372 double x,y,z,s,s_i; 406 double x,y,z,s;
373 407
374 double cosX = Math.Cos(v.x); 408 double c1 = Math.Cos(v.x/2.0);
375 double cosY = Math.Cos(v.y); 409 double c2 = Math.Cos(v.y/2.0);
376 double cosZ = Math.Cos(v.z); 410 double c3 = Math.Cos(v.z/2.0);
377 double sinX = Math.Sin(v.x); 411 double s1 = Math.Sin(v.x/2.0);
378 double sinY = Math.Sin(v.y); 412 double s2 = Math.Sin(v.y/2.0);
379 double sinZ = Math.Sin(v.z); 413 double s3 = Math.Sin(v.z/2.0);
380 414
381 s = Math.Sqrt(cosY * cosZ - sinX * sinY * sinZ + cosX * cosZ + cosX * cosY + 1.0f) * 0.5f; 415 x = s1*c2*c3+c1*s2*s3;
382 if (Math.Abs(s) < 0.00001) // null rotation 416 y = c1*s2*c3-s1*c2*s3;
383 { 417 z = s1*s2*c3+c1*c2*s3;
384 x = 0.0f; 418 s = c1*c2*c3-s1*s2*s3;
385 y = 1.0f; 419
386 z = 0.0f;
387 }
388 else
389 {
390 s_i = 1.0f / (4.0f * s);
391 x = - (-sinX * cosY - cosX * sinY * sinZ - sinX * cosZ) * s_i;
392 y = - (-cosX * sinY * cosZ + sinX * sinZ - sinY) * s_i;
393 z = - (-cosY * sinZ - sinX * sinY * cosZ - cosX * sinZ) * s_i;
394 }
395 return new LSL_Types.Quaternion(x, y, z, s); 420 return new LSL_Types.Quaternion(x, y, z, s);
396 } 421 }
397 422
398
399 public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up) 423 public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up)
400 { 424 {
401 m_host.AddScriptLPS(1); 425 m_host.AddScriptLPS(1);