# User:Dora Gustafson/llRotBetween alternatives

## llRotBetween, some alternatives and considerations

##### Scope

Four functions are covered, They are

1. llRotBetween( vector a, vector b); // The built in function
2. RotBetween( vector a, vector b); // The replacement outlined in the wiki
3. rotV2V( vector a, vector b); // The shortest replacement
4. rotbetween( vector a, vector b); // Using a Vector to rotation function
##### Tests

First the rotations provided by functions were compared and they didn't compare at all.

Testing rotations is a bad idea since there is no single solution to the question, but an infinite number of solutions.
All 4 functions provide valid, but different rotations.

So the sensible thing to do is to test how the solution rotates a vector:

## Test with random, normalized vectors

```cycles = 0;
record = [];
while ( cycles++ < nLimit && llGetListLength( record) < 30)
{
u = llVecNorm(< llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 >);
v = llVecNorm(< llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 >);
solution = rotbetween( u, v);
if ( llVecDist( u*solution, v) > epsilon ) record += [cycles, u, v];
}
```
Errors / test cycles Function 1 Function 2 Function 3 Function 4
llRotBetween RotBetween rotV2V rotbetween
abs error > 1e-7 10 / 13 10 / 18 10 / 15 10 / 16
10 / 14 10 / 21 10 / 22 10 / 23
10 / 27 10 / 14 10 / 13
abs error > 1e-6 7 / 1000 0 / 1000 0 / 1000 0 / 1000
3 / 1000 0 / 10000 1 / 10000 0 / 10000
8 / 1000 0 / 10000

## Test with close to parallel and anti parallel vectors

```cycles = 0;
record = [];
while ( cycles++ < nLimit && llGetListLength( record) < 30)
{
u = llVecNorm(< llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 >);
v = < llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3, llFrand( 2E-3)-1E-3 >;
if ( llFrand(1.0) < 0.5 ) v -= u;
else v += u;
solution = rotbetween( u, v);
if ( llVecDist( u*solution, v) > epsilon ) record += [cycles, u, v];
}
```
Errors / test cycles Function 1 Function 2 Function 3 Function 4
llRotBetween RotBetween rotV2V rotbetween
abs error > 1e-3 10 / 16 10 / 98 10 / 222 10 / 192
10 / 15 10 / 96 10 / 89 10 / 164
10 / 27 10 / 109 10 / 99 10 / 75
abs error > 1e-2 0 / 1000 0 / 1000 0 / 1000 0 / 1000
0 / 10000 0 / 10000 0 / 10000 0 / 10000

## Conclusion

Functions 2, 3 and 4 have similar performances. Function 1, the built-in, has a lower performance.
All four functions are very good except with parallel and anti parallel vectors.
The rotation found is not always what you expect.

The rotation will point a vector in the right direction, i.e. the rotation's forward is the vector direction.
See note about the functions nature
Function 4 is different, the solution will map a rotation with left in the horizontal plane

## Scripts and functions

Function 1, llRotBetween( vector a, vector b)
This is the built in function, see llRotBetween
See note about the functions nature
Function 2, RotBetween( vector a, vector b)
This is the suggested Replacement for llRotBetween
See note about the functions nature
Function 3, rotV2V( vector a, vector b)
```rotation rotV2V( vector a, vector b)
{
a = llVecNorm(a);
b = llVecNorm(b);
vector c = b;
while ( llFabs(a*c) > 0.999999 ) c = llVecNorm(< llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, llFrand( 2.0)-1.0 >);
c = llVecNorm(a%c);
return ZERO_ROTATION/llAxes2Rot( a, c, a%c)*llAxes2Rot( b, c, b%c);
}
```
See note about the functions nature
Function 4, rotbetween( vector a, vector b)
```rotation Vec2Rot( vector a)
{
a = llVecNorm(a);
vector  c = < 0.0, 0.0, 1.0 >;
if ( llFabs(a*c) > 0.999999 ) c = llVecNorm(< llFrand( 2.0)-1.0, llFrand( 2.0)-1.0, 0.0 >);
vector b = llVecNorm(c%a);
return llAxes2Rot( a, b, a%b);
}

rotation rotbetween( vector a, vector b)
{
return ZERO_ROTATION/Vec2Rot(a)*Vec2Rot(b);
}
```
Returns a solution that will map a rotation with left in the horizontal plane. This is convenient for cameras and prims you don't want tilted