diff options
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 85 |
1 files changed, 49 insertions, 36 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a005b01..1d7dcee 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -535,43 +535,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
535 | public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up) | 535 | public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up) |
536 | { | 536 | { |
537 | m_host.AddScriptLPS(1); | 537 | m_host.AddScriptLPS(1); |
538 | double x, y, z, s; | 538 | double s; |
539 | int f = 0; | 539 | double tr = fwd.x + left.y + up.z + 1.0; |
540 | // Important Note: q1=<x,y,z,s> is equal to q2=<-x,-y,-z,-s> | ||
541 | // Computing quaternion x,y,z,s values | ||
542 | x = ((fwd.x - left.y - up.z + 1) / 4); | ||
543 | x *= x; | ||
544 | x = Math.Sqrt(Math.Sqrt(x)); | ||
545 | y = ((1 - up.z) / 2 - x * x); | ||
546 | y *= y; | ||
547 | y = Math.Sqrt(Math.Sqrt(y)); | ||
548 | z = ((1 - left.y) / 2 - x * x); | ||
549 | z *= z; | ||
550 | z = Math.Sqrt(Math.Sqrt(z)); | ||
551 | s = (1 - x * x - y * y - z * z); | ||
552 | s *= s; | ||
553 | s = Math.Sqrt(Math.Sqrt(s)); | ||
554 | |||
555 | // Set f for signs detection | ||
556 | if (fwd.y + left.x >= 0) { f += 1; } | ||
557 | if (fwd.z + up.x >= 0) { f += 2; } | ||
558 | if (left.z - up.y >= 0) { f += 4; } | ||
559 | // Set correct quaternion signs based on f value | ||
560 | if (f == 0) { x = -x; } | ||
561 | if (f == 1) { x = -x; y = -y; } | ||
562 | if (f == 2) { x = -x; z = -z; } | ||
563 | if (f == 3) { s = -s; } | ||
564 | if (f == 4) { x = -x; s = -s; } | ||
565 | if (f == 5) { z = -z; } | ||
566 | if (f == 6) { y = -y; } | ||
567 | |||
568 | LSL_Rotation result = new LSL_Rotation(x, y, z, s); | ||
569 | |||
570 | // a hack to correct a few questionable angles :( | ||
571 | if (llVecDist(llRot2Fwd(result), fwd) > 0.001 || llVecDist(llRot2Left(result), left) > 0.001) | ||
572 | result.s = -s; | ||
573 | 540 | ||
574 | return result; | 541 | if (tr >= 1.0) |
542 | { | ||
543 | s = 0.5 / Math.Sqrt(tr); | ||
544 | return new LSL_Rotation( | ||
545 | (left.z - up.y) * s, | ||
546 | (up.x - fwd.z) * s, | ||
547 | (fwd.y - left.x) * s, | ||
548 | 0.25 / s); | ||
549 | } | ||
550 | else | ||
551 | { | ||
552 | double max = (left.y > up.z) ? left.y : up.z; | ||
553 | |||
554 | if (max < fwd.x) | ||
555 | { | ||
556 | s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0); | ||
557 | double x = s * 0.5; | ||
558 | s = 0.5 / s; | ||
559 | return new LSL_Rotation( | ||
560 | x, | ||
561 | (fwd.y + left.x) * s, | ||
562 | (up.x + fwd.z) * s, | ||
563 | (left.z - up.y) * s); | ||
564 | } | ||
565 | else if (max == left.y) | ||
566 | { | ||
567 | s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0); | ||
568 | double y = s * 0.5; | ||
569 | s = 0.5 / s; | ||
570 | return new LSL_Rotation( | ||
571 | (fwd.y + left.x) * s, | ||
572 | y, | ||
573 | (left.z + up.y) * s, | ||
574 | (up.x - fwd.z) * s); | ||
575 | } | ||
576 | else | ||
577 | { | ||
578 | s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0); | ||
579 | double z = s * 0.5; | ||
580 | s = 0.5 / s; | ||
581 | return new LSL_Rotation( | ||
582 | (up.x + fwd.z) * s, | ||
583 | (left.z + up.y) * s, | ||
584 | z, | ||
585 | (fwd.y - left.x) * s); | ||
586 | } | ||
587 | } | ||
575 | } | 588 | } |
576 | 589 | ||
577 | public LSL_Vector llRot2Fwd(LSL_Rotation r) | 590 | public LSL_Vector llRot2Fwd(LSL_Rotation r) |