Difference between revisions of "User:Dora Gustafson/llRotBetween alternatives"
Line 26: | Line 26: | ||
if ( llVecDist( u*solution, v) > epsilon ) record += [cycles, u, v]; | if ( llVecDist( u*solution, v) > epsilon ) record += [cycles, u, v]; | ||
}</lsl> | }</lsl> | ||
== | <table style="width: 800px;" border="1" cellpadding="2" | ||
cellspacing="2"> | |||
: | <tr> | ||
; | <th style="text-align: center;" colspan="1" | ||
: | rowspan="2">Errors / test cycles</th> | ||
= | <th style="text-align: center;">Function 1</th> | ||
; | <th style="text-align: center;">Function 2</th> | ||
: 10/18 | <th style="text-align: center;">Function 3</th> | ||
; | <th style="text-align: center;">Function 4</th> | ||
: | </tr> | ||
==== | <tr> | ||
; | <th style="text-align: center;">llRotBetween</th> | ||
: | <th style="text-align: center;">RotBetween</th> | ||
; | <th style="text-align: center;">rotV2V</th> | ||
: 0/ | <th style="text-align: center;">rotbetween</th> | ||
== | </tr> | ||
; | <tr> | ||
: | <th style="text-align: center;" colspan="1" | ||
; | rowspan="3">abs error > 1e-7</th> | ||
<td style="text-align: right;"> 10 / 13</td> | |||
<td style="text-align: right;"> 10 / 18</td> | |||
<td style="text-align: right;"> 10 / 15</td> | |||
<td style="text-align: right;"> 10 / 16</td> | |||
</tr> | |||
<tr> | |||
<td style="text-align: right;"> 10 / 14</td> | |||
<td style="text-align: right;"> 10 / 21</td> | |||
<td style="text-align: right;"> 10 / 22</td> | |||
<td style="text-align: right;"> 10 / 23</td> | |||
</tr> | |||
<tr> | |||
<td style="text-align: right;"></td> | |||
<td style="text-align: right;"> 10 / 27</td> | |||
<td style="text-align: right;">10 / 14</td> | |||
<td style="text-align: right;"> 10 / 13</td> | |||
</tr> | |||
<tr> | |||
<th style="text-align: center;" colspan="1" | |||
rowspan="3">abs error > 1e-6</th> | |||
<td style="text-align: right;"> 7 / 1000</td> | |||
<td style="text-align: right;"> 0 / 1000</td> | |||
<td style="text-align: right;"> 0 / 1000</td> | |||
<td style="text-align: right;"> 0 / 1000</td> | |||
</tr> | |||
<tr> | |||
<td style="text-align: right;"> 3 / 1000</td> | |||
<td style="text-align: right;"> 0 / 10000</td> | |||
<td style="text-align: right;"> 1 / 10000</td> | |||
<td style="text-align: right;"> 0 / 10000</td> | |||
</tr> | |||
<tr> | |||
<td style="text-align: right;"> 8 / 1000</td> | |||
<td style="text-align: right;"></td> | |||
<td style="text-align: right;"> 0 / 10000</td> | |||
<td style="text-align: right;"></td> | |||
</tr> | |||
</table> | |||
== Test with close to parallel and anti parallel vectors == | == Test with close to parallel and anti parallel vectors == | ||
Line 60: | Line 97: | ||
if ( llVecDist( u*solution, v) > epsilon ) record += [cycles, u, v]; | if ( llVecDist( u*solution, v) > epsilon ) record += [cycles, u, v]; | ||
}</lsl> | }</lsl> | ||
== | <table style="width: 800px;" border="1" cellpadding="2" | ||
cellspacing="2"> | |||
: | <tr> | ||
; | <th style="text-align: center;" colspan="1" | ||
: | rowspan="2">Errors / test cycles</th> | ||
== | <th style="text-align: center;">Function 1</th> | ||
; | <th style="text-align: center;">Function 2</th> | ||
: 10/98 | <th style="text-align: center;">Function 3</th> | ||
; | <th style="text-align: center;">Function 4</th> | ||
: | </tr> | ||
==== | <tr> | ||
; | <th style="text-align: center;">llRotBetween</th> | ||
: 10/ | <th style="text-align: center;">RotBetween</th> | ||
; | <th style="text-align: center;">rotV2V</th> | ||
: 0/1000 | <th style="text-align: center;">rotbetween</th> | ||
= | </tr> | ||
; | <tr> | ||
: | <th style="text-align: center;" colspan="1" | ||
; | rowspan="3">abs error > 1e-3</th> | ||
: 0/ | <td style="text-align: right;"> 10 / 16</td> | ||
<td style="text-align: right;"> 10 / 98</td> | |||
<td style="text-align: right;"> 10 / 222</td> | |||
<td style="text-align: right;"> 10 / 192</td> | |||
</tr> | |||
<tr> | |||
<td style="text-align: right;"> 10 / 15</td> | |||
<td style="text-align: right;"> 10 / 96</td> | |||
<td style="text-align: right;"> 10 / 89</td> | |||
<td style="text-align: right;"> 10 / 164</td> | |||
</tr> | |||
<tr> | |||
<td style="text-align: right;"> 10 / 27</td> | |||
<td style="text-align: right;"> 10 / 109</td> | |||
<td style="text-align: right;">10 / 99</td> | |||
<td style="text-align: right;"> 10 / 75</td> | |||
</tr> | |||
<tr> | |||
<th style="text-align: center;" colspan="1" | |||
rowspan="2">abs error > 1e-2</th> | |||
<td style="text-align: right;"> 0 / 1000</td> | |||
<td style="text-align: right;"> 0 / 1000</td> | |||
<td style="text-align: right;"> 0 / 1000</td> | |||
<td style="text-align: right;"> 0 / 1000</td> | |||
</tr> | |||
<tr> | |||
<td style="text-align: right;"> 0 / 10000</td> | |||
<td style="text-align: right;"> 0 / 10000</td> | |||
<td style="text-align: right;"> 0 / 10000</td> | |||
<td style="text-align: right;"> 0 / 10000</td> | |||
</tr> | |||
</table> | |||
== Conclusion == | == Conclusion == |
Revision as of 05:49, 26 December 2012
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 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>
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
<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>
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
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>