Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

BUGFIX: Forcing crazy (-180, 43,-180) Eulers into a valid form

Scalar Tardis
SL Scientist/Engineer
Join date: 5 Nov 2005
Posts: 249
10-29-2006 16:50
For my idea of using prims as control points for making bezier patches, I cannot have this insane jumping around of values that you get when rotations are converted to 3-axis Euler format.

This seems to be a bug in the client which the Lindens have not fixed, but the same behavior appears in LSL when you convert the rotation into a Euler.

I believe I have come up with a way to force the insane values back to a normal, sane state that we are all familiar with. If you drop this code into a prim, and rotate it along the Y-axis in-world and then touch it, you will see that it reports completely sane values for Y from 0 to 359.99

I have only been playing with this for a little while so I do not guarantee I found all the Euler bugs that need squashing.

But I do think that this code should be taken by the Lindens and used to fix the client's axis reporting and editing, and perhaps also code this as a new LSL function:
vector llRot2SaneEulerDeg(<rotation>;) :)


Code for testing this yourself in a prim:
CODE

integer DebugSane = FALSE;

vector llRot2SaneEulerDeg(rotation MyRotation)
{
vector RawEuler = llRot2Euler( MyRotation ) * RAD_TO_DEG;
if (DebugSane)
{
llOwnerSay ("My raw Euler, in degrees: " + (string)RawEuler);
llSleep(0.05); // No delay can cause out-of-order debug messages
}

vector FixedEuler = RawEuler;
// Euler is reporting screwed up y-axis values. Fix it!
if (FixedEuler.x == 180 && FixedEuler.z == 180)
{
FixedEuler.x -= 180; FixedEuler.z -= 180;
FixedEuler.y = (90-FixedEuler.y)+90;
}
if (DebugSane)
{
llOwnerSay ("Euler fix #1: " + (string)FixedEuler );
llSleep(0.05); // No delay can cause out-of-order debug messages
}
if (FixedEuler.x == -180 && FixedEuler.z == -180)
{
FixedEuler.x += 180; FixedEuler.z += 180;
FixedEuler.y = 180 - FixedEuler.y ;
}
if (DebugSane)
{
llOwnerSay ("Euler fix #2: " + (string)FixedEuler );
llSleep(0.05); // No delay can cause out-of-order debug messages
}
// force values to in range of: 0 <= angle < 360
// Note: Boolean math is faster:
FixedEuler.x += 360*(FixedEuler.x < 0) - 360*(FixedEuler.x >= 360);
FixedEuler.y += 360*(FixedEuler.y < 0) - 360*(FixedEuler.y >= 360);
FixedEuler.z += 360*(FixedEuler.z < 0) - 360*(FixedEuler.z >= 360);

//if (FixedEuler.x >= 360) { FixedEuler.x -= 360;}
//if (FixedEuler.y >= 360) { FixedEuler.y -= 360;}
//if (FixedEuler.z >= 360) { FixedEuler.z -= 360;}
//if (FixedEuler.x < 0) { FixedEuler.x += 360;}
//if (FixedEuler.y < 0) { FixedEuler.y += 360;}
//if (FixedEuler.z < 0) { FixedEuler.z += 360;}
if (DebugSane)
{
llOwnerSay ("Range fix: " + (string)FixedEuler );
llSleep(0.05); // No delay can cause out-of-order debug messages
}
// Rot to Euler imprecision below 0.01 degrees will be rounded off
FixedEuler.x = (float)llRound(FixedEuler.x * 100) / 100;
FixedEuler.y = (float)llRound(FixedEuler.y * 100) / 100;
FixedEuler.z = (float)llRound(FixedEuler.z * 100) / 100;
if (DebugSane)
{
llOwnerSay ("Rounded: " + (string)FixedEuler );
}
return FixedEuler;
}

default
{
state_entry()
{
llOwnerSay("Ready.");
}

touch_start(integer total_number)
{

rotation MyRot = llGetRot();
llOwnerSay ("My rotation: " + (string)MyRot );

llOwnerSay ("My raw Euler rotation, in degrees: " +
(string)(llRot2Euler(MyRot) * RAD_TO_DEG));

llOwnerSay ("My sane Euler rotation, in degrees: " +
(string)llRot2SaneEulerDeg(MyRot));
}
}
Scalar Tardis
SL Scientist/Engineer
Join date: 5 Nov 2005
Posts: 249
10-29-2006 16:55
Sample results:

[16:52] Test-Prim: My rotation: <0.00000, 0.45492, 0.00000, 0.89053>
[16:52] Test-Prim: My raw Euler rotation, in degrees: <0.00000, 54.12017, -0.00000>
[16:52] Test-Prim: My sane Euler rotation, in degrees: <0.00000, 54.12000, 0.00000>

[16:52] Test-Prim: My rotation: <-0.00000, 0.96391, -0.00000, 0.26622>
[16:52] Test-Prim: My raw Euler rotation, in degrees: <-180.00000, 30.87950, -180.00000>
[16:52] Test-Prim: My sane Euler rotation, in degrees: <0.00000, 149.12100, 0.00000>

[16:53] Test-Prim: My rotation: <0.00000, -0.88192, 0.00000, 0.47140>
[16:53] Test-Prim: My raw Euler rotation, in degrees: <-180.00000, -56.25001, -180.00000>
[16:53] Test-Prim: My sane Euler rotation, in degrees: <0.00000, 236.25000, 0.00000>

[16:53] Test-Prim: My rotation: <0.00000, -0.29028, 0.00000, 0.95694>
[16:53] Test-Prim: My raw Euler rotation, in degrees: <0.00000, -33.74999, 0.00000>
[16:53] Test-Prim: My sane Euler rotation, in degrees: <0.00000, 326.25000, 0.00000>
carol Wombat
Registered User
Join date: 29 Jan 2006
Posts: 16
10-30-2006 18:58
This is very interesting.

I have noticed that when I adjust rotations in edit mode, usually working on 0,90, 180 and 270 degrees, adjusting one dimension's box can make huge adjustments to the other two dimensions, and the object moves in some unexpected direction. I now only use the control key and the mouse to rotate objects and only then snap them to their target values with the text boxes.

Float numbers are not terribly accurate, really only about 7 decimal digits, so it might also be interesting whether +/- 180.0001 and +/- 179.9999 produce similar results. When I get home I'll try these in a prim script using a for loop.

I did once look at the conversion maths and it seems to involve a heap of matrix manipulation. I guess it would not be hard to make a mistake there.

If we only work in quaternions none of this matters? Only when we change to Euler, so it is the rotation to euler conversions that don't work properly? Do the euler to rotation conversions work ok?

Thanks for this info, Scalar, I guess your name says it all.
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
10-31-2006 01:27
I've also noticed it happens at the 90, 180, 270 values. I'd always assumed it was because the trig values do funny things around there... there's always one that's 0 or discontinuous at those values... hence gimbal lock.

One way that seems to work nicely, go to 1 degree away, then use the arrows to click to the right values. I'm not sure quite what is going with that, but I've never seen the lock kick in with that process. I guess, but I'm not sure, the system correctly returns the values for (say) <189, 89, 0> and the mechanism that advances by 1ยบ from the arrow click works correctly.
_____________________
Eloise's MiniMall
Visit Eloise's Minimall
New, smaller footprint, same great materials.

Check out the new blog
Zi Ree
Mrrrew!
Join date: 25 Feb 2006
Posts: 723
10-31-2006 03:40
When using Euler rotation, you quickly run into a problem called "Gimbal lock" - two axes aligning with each other, eliminating one of the three values.

http://en.wikipedia.org/wiki/Gimbal_lock
_____________________
Zi!

(SuSE Linux 10.2, Kernel 2.6.13-15, AMD64 3200+, 2GB RAM, NVidia GeForce 7800GS 512MB (AGP), KDE 3.5.5, Second Life 1.13.1 (6) alpha soon beta thingie)

Blog: http://ziree.wordpress.com/ - QAvimator: http://qavimator.org

Second Life Linux Users Group IRC Channel: irc.freenode.org #secondlifelug
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
10-31-2006 17:01
Gimbal Lock is why quaternions rock ^_^ (they don't suffer from gimbal lock).
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey