 Joined
 Sep 20, 2018
 Messages
 451
 Location
 Somewhere Purple, Germany
 SL Rez
 2007
 Joined SLU
 Dec 2007
 SLU Posts
 9108
(Repost from SLU due to popularity)
Here is a little snippet for the rotationallychallenged, or those who have some complex solution but want something much simpler.
How to rotate an object so it points its X axis (which is the 'forward' axis on prims) towards another object?
One complex solution is to take the object's rotation, take the other object's position, try to calculate the angle/rotation in between, adding it to the current rotation...
Way too complex. It's much simpler to calculate the total rotation that needs to be set in one swoop.
Here goes:
Awesome, isn't it? That one line does all the magic. The logic here is that the llRotBetween returns the rotation between the norm'd vector <1,0,0>, which would be the forward vector of an object without any rotation applied (remember, X axis = forward in prims), and the normal vector that points from your object to the target. And that's the whole rotation that needs to be set.
Now, this is already dead seksi, but it can have an effect that some people want to avoid: the object that does the pointing will rotate around its own length. I.e. it will roll left/right along its body axis. How to avoid that?
Solution: Do two different rotations. one that does the left/right turning, followed by a rotation that simply tilts the object up/down. Think of a classic concept like a gun turret. The turret barrel never rotates around the axis it points at, it just moves up/down and left/right.
Hokay, let's do the up/down first. The easiest way to get that rotation is to act like both object positions have the same Y value, and just are their combined XY distance apart on the X axis. Think twodimensional.
So we do:
And then we get back to the little first line of code in this post, modified:
Tadah. This will return the rotation that will make our object point upward correctly at the other object. Not left/right, just the correct upwards angle. the 'vTarget.z  vPos.z' gets done to get the height difference between the two objects.
Now how to do left/right? Easy, it uses the same idea as the above concept of getting the needed up/down rotation, except this time we disregard the Z coordinate and just use the XY difference.
Like this:
This time we don't even need to take care of any distance considerations. What we want, we'll get with:
There we go. The needed left/right rotation. Now, let's combine and get the result!
We take the up/down rotation, and multiply the left/right roation to it..which is the way of combining rotations...and it basically goes in reverse order. Think of the left/right applied first before the up/down gets done to the result rotation. Basically read from right to left when mupltiplying rotations.
And there we go. Correct rotation towards a target without rotating around the own axis. Hope this was educational!
Edit #2: up/down * left/right. I swear, that part is too easy to get wrong.
Here is a little snippet for the rotationallychallenged, or those who have some complex solution but want something much simpler.
How to rotate an object so it points its X axis (which is the 'forward' axis on prims) towards another object?
One complex solution is to take the object's rotation, take the other object's position, try to calculate the angle/rotation in between, adding it to the current rotation...
Way too complex. It's much simpler to calculate the total rotation that needs to be set in one swoop.
Here goes:
Code:
llSetRot(llRotBetween(<1,0,0>,llVecNorm(targetPosition  llGetPos())));
Now, this is already dead seksi, but it can have an effect that some people want to avoid: the object that does the pointing will rotate around its own length. I.e. it will roll left/right along its body axis. How to avoid that?
Solution: Do two different rotations. one that does the left/right turning, followed by a rotation that simply tilts the object up/down. Think of a classic concept like a gun turret. The turret barrel never rotates around the axis it points at, it just moves up/down and left/right.
Hokay, let's do the up/down first. The easiest way to get that rotation is to act like both object positions have the same Y value, and just are their combined XY distance apart on the X axis. Think twodimensional.
Code:
B
*
 Z height

A XYdistance 
* X axis (<1,0,0>)
Code:
vector vTarget=target position;
vector vPos=llGetPos(); //object position
float fDistance=llVecDist(<vTarget.x,vTarget.y,0>,<vPos.x,vPos.y,0>); // XY Distance, disregarding height differences.
Code:
llRotBetween(<1,0,0>,llVecNorm(<fDistance,0,vTarget.z  vPos.z>))
Now how to do left/right? Easy, it uses the same idea as the above concept of getting the needed up/down rotation, except this time we disregard the Z coordinate and just use the XY difference.
Like this:
Code:
Y
^

 *B


 *A

> X (<1,0,0>)
Code:
llRotBetween(<1,0,0>,llVecNorm(<vTarget.x  vPos.x,vTarget.y  vPos.y,0>))
Code:
vector vTarget=llList2Vector(llGetObjectDetails("targetkey",[OBJECT_POS]),0);
vector vPos=llGetPos(); //object position
float fDistance=llVecDist(<vTarget.x,vTarget.y,0>,<vPos.x,vPos.y,0>); // XY Distance, disregarding height differences.
llSetRot(llRotBetween(<1,0,0>,llVecNorm(<fDistance,0,vTarget.z  vPos.z>)) * llRotBetween(<1,0,0>,llVecNorm(<vTarget.x  vPos.x,vTarget.y  vPos.y,0>)));
And there we go. Correct rotation towards a target without rotating around the own axis. Hope this was educational!
Edit #2: up/down * left/right. I swear, that part is too easy to get wrong.