De DigiWiki.
llRotBetween(<1.0, 0.0, 0.0>, <0.0, -1.0, 0.0>)
// will return <0.00000, 0.00000, -0.70711, 0.70711> (which represents -90 degrees on the z axis)
llRotBetween(<0.0, 0.0, 0.0>, <0.0, -1.0, 0.0>)
// will return <0.00000, 0.00000, 0.00000, 1.00000> (which represents a zero angle on all axis)
// because <0.0, 0.0, 0.0> does not convey a direction.
rotation RotBetween(vector start, vector end) //adjusts quaternion magnitude so (start * return == end)
{//Authors note: I have never had a use for this but it's good to know how to do it if I did.
rotation rot = llRotBetween(start, end);
float d = start * start;
if(d)//is 'start' zero?
if((d = llPow(end * end / d, 0.25)))//is 'end' zero?
return <rot.x * d, rot.y * d, rot.z * d, rot.s * d>;
return rot;
}//Strife Onizuka
// First Vector is due north second vector is ALMOST due south.
rotation lRotation = llRotBetween( <0., 1., 0.>, <-0.001, -.1, 0.> );
llSay(0, lRotation );
// Provides a result of <1.00000, 0.00000, 0.00000, 0.00000>.
rotation RotBetween(vector a, vector b)
{
float aabb = llSqrt((a * a) * (b * b)); // product of the lengths of the arguments
if (aabb)
{
float ab = (a * b) / aabb; // normalized dotproduct of the arguments (cosine)
vector c = (a % b) / aabb; // normalized crossproduct of the arguments
float cc = c * c; // squared length of the normalized crossproduct (sine)
if (cc) // test if the arguments are (anti)parallel
{
float s;
if (ab > -0.707107) // test if the angle is smaller than 3/4 PI
s = 1.0 + ab; // use the cosine to adjust the s-element
else
s = 1.0 - llSqrt(1.0 - cc); // use the sine to adjust the s-element
float m = llSqrt(cc + s * s); // the magnitude of the quaternion
return <c.x / m, c.y / m, c.z / m, s / m>; // return the normalized quaternion
}
else if (ab < 0.0) // test if the angle is smaller than PI/2
return <1.0, 0.0, 0.0, 0.0>; // the arguments are anti-parallel
}
return ZERO_ROTATION; // the arguments are too small or parallel, return zero rotation
}//Written by Moon Metty, optimized by Strife Onizuka