lsl second life Kept simple: Rotate object towards another object

Chalice Yao

The Purple
Joined
Sep 20, 2018
Messages
451
Location
Somewhere Purple, Germany
SL Rez
2007
Joined SLU
Dec 2007
SLU Posts
9108
(Re-post from SLU due to popularity)

Here is a little snippet for the rotationally-challenged, 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())));
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 two-dimensional.

Code:
                     B
                     *
                     |   Z height
                     |
A     XYdistance     |
*--------------------------- X axis (<1,0,0>)
So we do:

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.
And then we get back to the little first line of code in this post, modified:

Code:
llRotBetween(<1,0,0>,llVecNorm(<fDistance,0,vTarget.z - vPos.z>))
Ta-dah. 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:
Code:
Y
^
|
|                                 *B
|
|
|    *A
|
------------------> X (<1,0,0>)
This time we don't even need to take care of any distance considerations. What we want, we'll get with:

Code:
llRotBetween(<1,0,0>,llVecNorm(<vTarget.x - vPos.x,vTarget.y - vPos.y,0>))
There we go. The needed left/right rotation. Now, let's combine and get the result!

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

Arlequin

New member
Joined
Jan 29, 2019
Messages
3
Location
France
SL Rez
2007
Joined SLU
01/29/2019
Hello

Regarde cette instruction, cela fonctionne très bien et je l'utilise dans mes scripts.
Il n'y a pas de retard.
llLookAt

Code:
//Causes Object to look at nearest Avatar.
default
{
    state_entry()
    {
        llSensorRepeat("", "", AGENT, 20.0, PI, 0.2);
    }
 
    sensor(integer total_number)
    {
        llLookAt( llDetectedPos(0) + <0.0, 0.0, 1.0>, 3.0, 1.0 );
    }
}
Ou pour un objet:

llSensorRepeat("","", ACTIVE+PASSIVE, 96, PI,0.1);
puis

sensor(integer s){

integer x = 0;
for(;x<s;++x){
llLookAt(llDetectedPos(x),.5,.5);
......



LlLookAt - Second Life Wiki

Voilà, si ça peut aider
 

Innula Zenovka

Nasty Brit
VVO Supporter 🍦🎈👾❤
Joined
Sep 20, 2018
Messages
19,742
SLU Posts
18459
llLookAt works well if you want to point the object's positive z axis at a target. If you need to use another axis, though, it's not so good.

llLookAt fonctionne bien si vous voulez pointer l'axe z positif de l'objet sur une cible. Si vous devez utiliser un autre axe, ce n'est pas si bon que ça.
 

Adeon Writer

Member
Joined
Sep 20, 2018
Messages
316
Location
Phoenix, Arizona
llLookAt works well if you want to point the object's positive z axis at a target. If you need to use another axis, though, it's not so good.

llLookAt fonctionne bien si vous voulez pointer l'axe z positif de l'objet sur une cible. Si vous devez utiliser un autre axe, ce n'est pas si bon que ça.
Use llLookAt to point it's positive Z at something, then rotate it by 90 degrees on local X or Y to point X or Y at it.

</bigbrain>
 

Free

sapiens gratis
VVO Supporter 🍦🎈👾❤
Joined
Sep 22, 2018
Messages
31,473
Location
Moonbase Caligula
SL Rez
2008
Joined SLU
2009
SLU Posts
55565
This cannot be a spam run. Or can it...
 

Dorex

New member
Joined
Sep 22, 2023
Messages
1
This works great for the X axis but not the Y or Z

// Y axis
llSetRot(llRotBetween(<0,1,0>,llVecNorm(<fDistance,0,vTarget.z - vPos.z>)) * llRotBetween(<0,1,0>,llVecNorm(<vTarget.x - vPos.x, vTarget.y - vPos.y, 0>)));
// Z axis
llSetRot(llRotBetween(<0,0,1>,llVecNorm(<fDistance,0,vTarget.z - vPos.z>)) * llRotBetween(<0,,0,1>,llVecNorm(<vTarget.x - vPos.x, vTarget.y - vPos.y, 0>)));