aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs99
1 files changed, 81 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 59ab26b..712bd7d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -705,22 +705,75 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
705 { 705 {
706 //A and B should both be normalized 706 //A and B should both be normalized
707 m_host.AddScriptLPS(1); 707 m_host.AddScriptLPS(1);
708 double dotProduct = LSL_Vector.Dot(a, b); 708 LSL_Rotation rotBetween;
709 LSL_Vector crossProduct = LSL_Vector.Cross(a, b); 709 // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
710 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b); 710 // continue calculation.
711 double angle = Math.Acos(dotProduct / magProduct); 711 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
712 LSL_Vector axis = LSL_Vector.Norm(crossProduct); 712 {
713 double s = Math.Sin(angle / 2); 713 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
714 714 }
715 double x = axis.x * s; 715 else
716 double y = axis.y * s; 716 {
717 double z = axis.z * s; 717 a = LSL_Vector.Norm(a);
718 double w = Math.Cos(angle / 2); 718 b = LSL_Vector.Norm(b);
719 719 double dotProduct = LSL_Vector.Dot(a, b);
720 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w)) 720 // There are two degenerate cases possible. These are for vectors 180 or
721 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 721 // 0 degrees apart. These have to be detected and handled individually.
722 722 //
723 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w); 723 // Check for vectors 180 degrees apart.
724 // A dot product of -1 would mean the angle between vectors is 180 degrees.
725 if (dotProduct < -0.9999999f)
726 {
727 // First assume X axis is orthogonal to the vectors.
728 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
729 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
730 // Check for near zero vector. A very small non-zero number here will create
731 // a rotation in an undesired direction.
732 if (LSL_Vector.Mag(orthoVector) > 0.0001)
733 {
734 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f);
735 }
736 // If the magnitude of the vector was near zero, then assume the X axis is not
737 // orthogonal and use the Z axis instead.
738 else
739 {
740 // Set 180 z rotation.
741 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
742 }
743 }
744 // Check for parallel vectors.
745 // A dot product of 1 would mean the angle between vectors is 0 degrees.
746 else if (dotProduct > 0.9999999f)
747 {
748 // Set zero rotation.
749 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
750 }
751 else
752 {
753 // All special checks have been performed so get the axis of rotation.
754 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
755 // Quarternion s value is the length of the unit vector + dot product.
756 double qs = 1.0 + dotProduct;
757 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
758 // Normalize the rotation.
759 double mag = LSL_Rotation.Mag(rotBetween);
760 // We shouldn't have to worry about a divide by zero here. The qs value will be
761 // non-zero because we already know if we're here, then the dotProduct is not -1 so
762 // qs will not be zero. Also, we've already handled the input vectors being zero so the
763 // crossProduct vector should also not be zero.
764 rotBetween.x = rotBetween.x / mag;
765 rotBetween.y = rotBetween.y / mag;
766 rotBetween.z = rotBetween.z / mag;
767 rotBetween.s = rotBetween.s / mag;
768 // Check for undefined values and set zero rotation if any found. This code might not actually be required
769 // any longer since zero vectors are checked for at the top.
770 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
771 {
772 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
773 }
774 }
775 }
776 return rotBetween;
724 } 777 }
725 778
726 public void llWhisper(int channelID, string text) 779 public void llWhisper(int channelID, string text)
@@ -6520,6 +6573,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6520 if (cut.y - cut.x < 0.05f) 6573 if (cut.y - cut.x < 0.05f)
6521 { 6574 {
6522 cut.x = cut.y - 0.05f; 6575 cut.x = cut.y - 0.05f;
6576 if (cut.x < 0.0f)
6577 {
6578 cut.x = 0.0f;
6579 cut.y = 0.05f;
6580 }
6523 } 6581 }
6524 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); 6582 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
6525 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y)); 6583 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
@@ -6715,9 +6773,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6715 { 6773 {
6716 profilecut.y = 1f; 6774 profilecut.y = 1f;
6717 } 6775 }
6718 if (profilecut.y - cut.x < 0.05f) 6776 if (profilecut.y - profilecut.x < 0.05f)
6719 { 6777 {
6720 profilecut.x = cut.y - 0.05f; 6778 profilecut.x = profilecut.y - 0.05f;
6779 if (profilecut.x < 0.0f)
6780 {
6781 profilecut.x = 0.0f;
6782 profilecut.y = 0.05f;
6783 }
6721 } 6784 }
6722 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); 6785 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
6723 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y)); 6786 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));