# User:Dora Gustafson/llRotBetween alternatives

From Second Life Wiki

## Contents

## llRotBetween, some alternatives and considerations

##### Scope

Four functions are covered, They are

- llRotBetween( vector a, vector b); // The built in function
- RotBetween( vector a, vector b); // The replacement outlined in the wiki
- rotV2V( vector a, vector b); // The shortest replacement
- 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

## About the function's nature

The function determines a rotation (quaternion) which can map a vector onto another.

- It does nothing else, which means that there are no conditions on the other vectors associated with a rotation in space.

When the solution is used to rotate a body in space one should be aware of it’s nature.

- For a prim whose rotation is defined by three orthogonal vectors the forward vector mapping will be correct while the other vector mappings are unpredictable.
- A prim mapping will normally be rotated about the prim’s forward axis in an unpredictable way.
- The prim will be tilted to one side or the other side with respect to the vertical.