User:Dora Gustafson/llRotBetween alternatives

From Second Life Wiki
Jump to navigation Jump to search

llRotBetween, some alternatives and considerations

Under construction

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 rotation solutions were compared and they didn't compare at all. Testing rotations is a bad idea since there are no single solutions, but infinite numbers of solutions. All 4 functions provide valid, but different solutions. So the sensible thing to do is to test how the solution affects a vector:

Test with random, normalized vectors

<lsl> 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];

}</lsl>

Results for function 1. llRotBetween

Errors > 1E-7 / number of test cycles
10/13, 10/14
Errors > 1E-6 / number of test cycles
7/1000, 3/1000, 8/1000

Results for function 2. RotBetween

Errors > 1E-7 / number of test cycles
10/18, 10/21, 10/27
Errors > 1E-6 / number of test cycles
0/1000, 0/10000

Results for function 3. rotV2V

Errors > 1E-7 / number of test cycles
10/15, 10/22, 10/14
Errors > 1E-6 / number of test cycles
0/1000, 1/10000, 0/10000

Results for function 4. rotbetween

Errors > 1E-7 / number of test cycles
10/16, 10/23, 10/13
Errors > 1E-6 / number of test cycles
0/1000, 0/10000

Test with close to parallel and anti parallel vectors

<lsl> 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];

}</lsl>

Results for function 1. llRotBetween

Errors > 1E-3 / number of test cycles
10/16, 10/15, 10/27
Errors > 1E-2 / number of test cycles
0/1000, 0/10000

Results for function 2. RotBetween

Errors > 1E-3 / number of test cycles
10/98, 10/96, 10/109
Errors > 1E-2 / number of test cycles
0/1000, 0/10000

Results for function 3. rotV2V

Errors > 1E-3 / number of test cycles
10/222, 10/89, 10/99
Errors > 1E-2 / number of test cycles
0/1000, 0/10000

Results for function 4. rotbetween

Errors > 1E-3 / number of test cycles
10/192, 10/164, 10/75
Errors > 1E-2 / number of test cycles
0/1000, 0/10000

Conclusion

Functions 2, 3 and 4 have similar performances. Function 1, the built-in, has a lower performance

Scripts and functions

Function 1, llRotBetween()
This is the built in function, see llRotBetween
Function 2, RotBetween()
This is the suggested replacement for llRotBetween
Function 3, rotV2V()

<lsl>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);

} </lsl>

Function 4, rotbetween()

<lsl>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);

} </lsl>