Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Why doesn't my trig match the virtual world?

Cyclopean Sprocket
Compulsive Builder
Join date: 16 Feb 2006
Posts: 17
03-05-2006 20:48
I've run into a trig issue that's stumped me. Let's say I have two objects, one is at <0,0,0> and the other is at <2.424, 2.512, 1.71>. I want to create a cylinder that connects the centers of these two objects along it's central Z axis.

The center of the cylinder is easy to spot, it's at <1.212, 1.256, 0.87>, but I've run into an issue with the rotation. If I'm doing my Euler rotation math correctly, I should be determining the X Rotation by getting the arcsin of the Y length divided by the total length, and I should be determining the Y rotation by getting the arccos of the X length divided by the total length. So the math looks like this:

Xlen = 2.424
Ylen = 2.512
Zlen = 1.740
Length = 3.900 ( sqrt(Xlen^2 + Ylen^2 + Zlen^2) )

Xrot = arcsin( Ylen / Length ) = .700 rad = 40.093 degrees
Yrot = arccos( Xlen / Length ) = .900 rad = 51.577 degrees

So far, so good. But when I actually build the thing, the rotations need to be something more like Xrot=55.1 and Yrot=37.7 . Can anyone here clue my rusty trigonometry into what I'm doing wrong?
SuezanneC Baskerville
Forums Rock!
Join date: 22 Dec 2003
Posts: 14,229
03-05-2006 21:51
I haven't been doing enoujgh of this lately, but I think this script was doing what you want to accomplish.

The llLookAt is not the right thing to do, it is a mentally lazy way that works.

I put my own position values for the target objects, <90, 23, 62 > and < 89, 25, 62 > ;
CODE

default
{
state_entry()
{
llSay(0, "Hello, Avatar!");
}

touch_start(integer total_number)
{
llSay(0, "Touched.");
float l;
vector d = <90, 23, 62 > - < 89, 25, 62 >;

l = llVecMag( d ) ;
rotation r;
r = llEuler2Rot(d);

llSetScale( < .1, .1, l >) ;
llSetPos( (<90, 23,62> + <89,25,62>)/2 ) ;
llLookAt( <90,23,62>, 1, 1);

}


I would suggest looking at all the rotation functions like Euler2Rot, Rot2Fwd, etc.

time to sleep.
_____________________
-

So long to these forums, the vBulletin forums that used to be at forums.secondlife.com. I will miss them.

I can be found on the web by searching for "SuezanneC Baskerville", or go to

http://www.google.com/profiles/suezanne

-

http://lindenlab.tribe.net/ created on 11/19/03.

Members: Ben, Catherine, Colin, Cory, Dan, Doug, Jim, Philip, Phoenix, Richard,
Robin, and Ryan

-
Cyclopean Sprocket
Compulsive Builder
Join date: 16 Feb 2006
Posts: 17
03-05-2006 22:29
From: SuezanneC Baskerville
I haven't been doing enoujgh of this lately, but I think this script was doing what you want to accomplish.

The llLookAt is not the right thing to do, it is a mentally lazy way that works.


Thanks, Suzanne. That's a good work-around that'll suit me until I work this out. I'm trying to do all of the math in advance, though, and I'd really like to figure out why my math isn't working.

From: someone
I would suggest looking at all the rotation functions like Euler2Rot, Rot2Fwd, etc.


Euler2Rot does fine, but gives me the exact same results as if I were to pass the numbers into the object editor. That's it's point, I think. Still trying to figure out what the angles are.
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
03-05-2006 23:07
This is can be solved in LSL with limited hassle.

CODE

default
{
state_entry()
{
llSetScale(<1,1,llVecMag(<1.212, 1.256, 0.87>)>);
llSetRot(llRotBetween(<0,0,1>, <1.212, 1.256, 0.87>));
}
}
_____________________
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
Cyclopean Sprocket
Compulsive Builder
Join date: 16 Feb 2006
Posts: 17
03-06-2006 10:53
From: Strife Onizuka
This is can be solved in LSL with limited hassle...

Thanks, Strife. It's more work that I wanted to make the sim do, but it'll get the job done.

From: Strife Onizuka
llSetRot(llRotBetween(<0,0,1>, <1.212, 1.256, 0.87>;));

Why is the Z value of the first location 1 instead of 0?

I'm getting the feeling that the answer to my question "How is my trig wrong" is something like "why on earth would you want to do trig?" If anyone out there is math minded, I'd still like to know how I messed that one up, otherwise I'm going to have to pass this one up as a possible bug. It's entirely possible that everyone on the dev team does it all with quaternions and nobody on this side has ever bothered with the math.
Static Sprocket
Registered User
Join date: 10 Feb 2006
Posts: 157
03-06-2006 12:17
Wouldn't it's Z value be possitive, because you want the "top" of the cylinder to point at the destination? You would be aligning the cylinder's Z-Axis between the two points, not it's X-Axis (forward) or Y-Axis (left).

[edit] Just to expand on this. Your cylinder starts off with the Z axis world aligned, and vertical. You then want to determine what X-Axis rotation and Y-Axis rotation would make a vector from the center of your prim (that goes straight up Z+) rotate so that the vector now points at the destination.

Gawd, I hope that makes sense -- I've been struggling with rotations the last few days too.
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
03-06-2006 12:53
Strife has shown how to let LSL do the work for you, Cyclopean - Here is a (lengthy) explanation for the maths behind it.

What you're bumping into is one of the difficulties of Euler angles that made me grudginlgy resort to learning quaternions - and now I won't go back :)
The problem is that as the Xrot is applied (and it is applied first, then Y, and only then Z), it rotates not only the object, but its axes as well. So after the rotation around the x-axiz is performed, the y axis is no longer where it was - it no longer matches the world's y-axis.

So looking at your example:

using Eulers
Rotation around the x-axis is performed first. Assume we are standing south of your cylinder, facing directly N at it. Its rotation is currently world-aligned (<0.0, 0.0, 0.0>;). We want it to end up pointing away from us(positive Y), up(positive Z) and to the right(positive X), but our first rotation must be around the X-axis, which runs from left to right. This means we need to tip the cylinder's top (and its Z axis) back away from us. Right-hand rule tells us that this is negative rotation around X. We want to rotate it so that a point 2.512m horizontally away from the origin will be 1.74m up.

If Theta is the angle between the rotated cylinder and the ground plane then Tan(Theta)=1.74/2.512
Of course, the Z-axis starts vertically, not on the ground plane, so the rotation is actually 90-arctan(1.74/2.512).
But right-hand-rule told us we need negative rotation, so it's actually 360-(90-arctan(1.74/2.512)), which is 304.709 degrees.

Now it would be quite easy to calculate the global Z-rotation needed to spin the object into its final rotation, BUT neither the Y-axis nor the Z-axis are world-aligned anymore. They have both been rotated 304.709 degrees off true. With some fancy trig we could calculate the needed rotation around the object's local Y-axis (ends up being 38.4 degrees), but DAMN! it's tricky. Rather we could look at ...

using Quaternions
Quats, unlike Eulers, perform one co-ordinated rotation, rather than three seperate ones.
They are encoded by taking a normalised axis-of-rotation, multiplying each value by the sin of half of the angle of rotation, and adding the cos of half of the angle as a fourth number.
Don't worry why it is done like this - just remember that if x, y and z are the axis or rotation, and ha is half of the angle of rotation, then the corresponding quat is <x.sin(ha), y.sin(ha), z.sin(ha), cos(ha)>.

The axis of rotation is easy to find in this example. It is perpendicular to the plane of rotation, which passes through the vertical (Z) axis, and passes through the ground plane at <2.424, 2.512, 0.0>. The axis of rotation then is simply the line that passes through the origin and <-2.512, 2.424, 0.0> (because the line-segment <a, b, 0> is always perpendicular to <-b, a, 0>;)

Normalise (using your calculator, or llVecNorm) <-2.512, 2.424, 0.0> to <-0.72, 0.694, 0.0>
The angle of rotation (around that axis) from the ground plane up is given by arctan(1.74/h) where h is the hypotenuse of the triangle with X=2.424 and Y=2.512. Same as we did with Eulers, subtract that answer from 90 degrees because we are rotating from vertical rather than from the ground plane, and we get 63.506

This basically gives us the answer
CODE
float HalfAngle = (63.506 * DEG_TO_RAD) / 2.0;
float Sin = llSin(HalfAngle);
llSetRot( <-0.72*Sin, 0.694*Sin, 0.0, llCos(HalfAngle)> );


I know it takes some getting used to at first, but persevere and you'll soon find quats far easier to work with than Eulers. :)

If you need elucidation (love that word:)) on any of that - or pictures - let me know.
Candide LeMay
Registered User
Join date: 30 Dec 2004
Posts: 538
03-06-2006 15:12
That's a pretty good explanation of quaternions and the surrounding issues, Ben :)
_____________________
"If Mel Gibson and other cyberspace writers are right, one day the entire internet will be like Second Life." -- geldonyetich
Cyclopean Sprocket
Compulsive Builder
Join date: 16 Feb 2006
Posts: 17
03-06-2006 17:23
From: Ben Bacon
The problem is that as the Xrot is applied (and it is applied first, then Y, and only then Z), it rotates not only the object, but its axes as well.

Aha! Now it makes sense. It's like a tank turret mounted on the (Y,Z) plane, with the barrel pointed down the Z axis. First the turret turns, then the barrel is raised or lowered, then the barrel unscrews like a carriage bolt.

Well, ok, so it's not a perfect analogy, but it does allow me to understand where I went wrong. Applied to my previous equasions:

Xlen = 2.424
Ylen = 2.512
Zlen = 1.740
Length = 3.900 ( sqrt(Xlen^2 + Ylen^2 + Zlen^2) )

Xrot = arctan( Ylen / Zlen ) = .965 rad = 55.291 degrees
Yrot = arcsin( Xlen / Length ) = .671 rad = 38.423 degrees

Which matches well with my observed Xrot=55.1 and Yrot=37.7.

I still intend to figure out quaternions, but this will get me by for my current project.

Thanks, Ben, I owe you one.
Kitten Lulu
Registered User
Join date: 8 Jul 2005
Posts: 114
03-07-2006 01:18
From: Ben Bacon
Here is a (lengthy) explanation for the maths behind it.


This is useful, I tried to post it as a comment to the wiki entry about 'rotation' but it doesn't show up. Probably it needs approval by someone.

Please, oh Powers Of The Wiki, add those notes from Ben to the 'rotation' wiki page.
_____________________
I've got a blog!

My products are available on SLExchange or in-world in my shops: Kitten Lulu's Emporium and Kitten&Co.