diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index dc34e1c20d..712bd7d383 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -703,76 +703,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b) { - //A and B should both be normalized - m_host.AddScriptLPS(1); - LSL_Rotation rotBetween; - // Check for zero vectors. If either is zero, return zero rotation. Otherwise, - // continue calculation. - if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) - { - rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); - } - else - { - a = LSL_Vector.Norm(a); - b = LSL_Vector.Norm(b); - double dotProduct = LSL_Vector.Dot(a, b); - // There are two degenerate cases possible. These are for vectors 180 or - // 0 degrees apart. These have to be detected and handled individually. - // - // Check for vectors 180 degrees apart. - // A dot product of -1 would mean the angle between vectors is 180 degrees. - if (dotProduct < -0.9999999f) - { - // First assume X axis is orthogonal to the vectors. - LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); - orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); - // Check for near zero vector. A very small non-zero number here will create - // a rotation in an undesired direction. - if (LSL_Vector.Mag(orthoVector) > 0.0001) - { - rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); - } - // If the magnitude of the vector was near zero, then assume the X axis is not - // orthogonal and use the Z axis instead. - else - { - // Set 180 z rotation. - rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f); - } - } - // Check for parallel vectors. - // A dot product of 1 would mean the angle between vectors is 0 degrees. - else if (dotProduct > 0.9999999f) - { - // Set zero rotation. - rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); - } - else - { - // All special checks have been performed so get the axis of rotation. - LSL_Vector crossProduct = LSL_Vector.Cross(a, b); - // Quarternion s value is the length of the unit vector + dot product. - double qs = 1.0 + dotProduct; - rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs); - // Normalize the rotation. - double mag = LSL_Rotation.Mag(rotBetween); - // We shouldn't have to worry about a divide by zero here. The qs value will be - // non-zero because we already know if we're here, then the dotProduct is not -1 so - // qs will not be zero. Also, we've already handled the input vectors being zero so the - // crossProduct vector should also not be zero. - rotBetween.x = rotBetween.x / mag; - rotBetween.y = rotBetween.y / mag; - rotBetween.z = rotBetween.z / mag; - rotBetween.s = rotBetween.s / mag; - // Check for undefined values and set zero rotation if any found. This code might not actually be required - // any longer since zero vectors are checked for at the top. - if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s)) - { - rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); - } - } - } + //A and B should both be normalized + m_host.AddScriptLPS(1); + LSL_Rotation rotBetween; + // Check for zero vectors. If either is zero, return zero rotation. Otherwise, + // continue calculation. + if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) + { + rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + a = LSL_Vector.Norm(a); + b = LSL_Vector.Norm(b); + double dotProduct = LSL_Vector.Dot(a, b); + // There are two degenerate cases possible. These are for vectors 180 or + // 0 degrees apart. These have to be detected and handled individually. + // + // Check for vectors 180 degrees apart. + // A dot product of -1 would mean the angle between vectors is 180 degrees. + if (dotProduct < -0.9999999f) + { + // First assume X axis is orthogonal to the vectors. + LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); + orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); + // Check for near zero vector. A very small non-zero number here will create + // a rotation in an undesired direction. + if (LSL_Vector.Mag(orthoVector) > 0.0001) + { + rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); + } + // If the magnitude of the vector was near zero, then assume the X axis is not + // orthogonal and use the Z axis instead. + else + { + // Set 180 z rotation. + rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f); + } + } + // Check for parallel vectors. + // A dot product of 1 would mean the angle between vectors is 0 degrees. + else if (dotProduct > 0.9999999f) + { + // Set zero rotation. + rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + // All special checks have been performed so get the axis of rotation. + LSL_Vector crossProduct = LSL_Vector.Cross(a, b); + // Quarternion s value is the length of the unit vector + dot product. + double qs = 1.0 + dotProduct; + rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs); + // Normalize the rotation. + double mag = LSL_Rotation.Mag(rotBetween); + // We shouldn't have to worry about a divide by zero here. The qs value will be + // non-zero because we already know if we're here, then the dotProduct is not -1 so + // qs will not be zero. Also, we've already handled the input vectors being zero so the + // crossProduct vector should also not be zero. + rotBetween.x = rotBetween.x / mag; + rotBetween.y = rotBetween.y / mag; + rotBetween.z = rotBetween.z / mag; + rotBetween.s = rotBetween.s / mag; + // Check for undefined values and set zero rotation if any found. This code might not actually be required + // any longer since zero vectors are checked for at the top. + if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s)) + { + rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + } + } return rotBetween; }