Jump to content

Child Rotation (doing my head in)


Ares Halostar
 Share

You are about to reply to a thread that has been inactive for 411 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I have two Prims.  The bottom one points one face to an avatar (disregarding avatars height, so it only tracks left and right).

That simple code is:

default
{
    state_entry()
    {
        llSensorRepeat("", "", AGENT, 96.0, PI,1.0);
    }
    sensor(integer num_detected)
    {
        vector Pos = llDetectedPos(0);
        vector MyPos = llGetPos();
        vector target_posA = <Pos.x, Pos.y, MyPos.z>;
        llRotLookAt(llRotBetween(<1.0, 0.0, 0.0>,llVecNorm(target_posA-MyPos)), 1.0, 0.1);
    }
}

That works fine.

The linked child prim above it, I want it to point to the avatar as well, but not only with the left and right movement, but also up and down.

Seems like a simple thing to accomplish, but rotations have always done my head in.

As an example, think of a rocket launcher rotating on a base, with the actual rocket tube tracking up and down while the base moves around on it's own axis.

Link to comment
Share on other sites

Here's code from an old project of mine, which does exactly that.

rotation TurnTowards(vector pos)
{
    vector this = llGetPos() + <0, 0, 1.06>;

    // Calculate the base (left/right rotation)
    vector direction = llVecNorm(pos - this);
    direction.z = 0;
    rotation final = llRotBetween(<1,0,0>, direction);

    // Calculate the turret (up/down rotation)
    float dist = llVecDist(<pos.x, pos.y, 0>, <this.x, this.y, 0>);
    rotation pitch = llRotBetween(<1,0,0>, llVecNorm(<dist, 0, pos.z - this.z>));

    // Set both values
    llSetLinkPrimitiveParamsFast(2, [PRIM_ROTATION, final,
        PRIM_LINK_TARGET, 3, PRIM_ROTATION, pitch * final]);

    // This is used later for rezzing
    return pitch * final;
}

 

Edited by Wulfie Reanimator
  • Like 1
Link to comment
Share on other sites

integer getLinkNum(string primName)
{    
    integer primCount = llGetNumberOfPrims();    
    integer i;    
    for (i=0; i<primCount+1;i++)    
    {        
        if (llGetLinkName(i)==primName) return i;    
    }    
    return FALSE;
}
rotation TurnTowards(vector pos)
{
    vector this = llGetPos();// + <0, 0, 1.06>;

    // Calculate the base (left/right rotation)
    vector direction = llVecNorm(pos - this);
    direction.z = 0;
    rotation final = llRotBetween(<1,0,0>, direction);

    // Calculate the turret (up/down rotation)
    float dist = llVecDist(<pos.x, pos.y, 0>, <this.x, this.y, 0>);
    rotation pitch = llRotBetween(<1,0,0>, llVecNorm(<dist, 0, pos.z - this.z>));

    // Set both values
    llSetLinkPrimitiveParamsFast(getLinkNum("Main"), [PRIM_ROTATION, final,
        PRIM_LINK_TARGET, getLinkNum("UpDown"), PRIM_ROTATION, pitch * final]);

    // This is used later for rezzing
    return pitch * final;
}
default
{
    state_entry()
    {
        llSensorRepeat("", "", AGENT, 96.0, PI,1.0);
    }
    sensor(integer num_detected)
    {
        TurnTowards(llDetectedPos(0));
    }
}

 

That is the code I am using, and it nearly works, the bottom prim "Main" turns as it should, but the top prim "UpDown" doesn't quite do what it is required and ends up at a different angle as per the photo:

 

 

Prims_001.jpg

Link to comment
Share on other sites

It works, not as smooth as I'd hoped, but with some fine tuning I will get there.

I had to divide by the root rotation TWICE to get the result I wanted with the upper prim.

The final code is below:

integer getLinkNum(string primName)
{    
    integer primCount = llGetNumberOfPrims();    
    integer i;    
    for (i=0; i<primCount+1;i++)    
    {        
        if (llGetLinkName(i)==primName) return i;    
    }    
    return FALSE;
}
rotation TurnTowards(vector pos)
{
    vector this = llGetPos() + <0, 0, 0.75>;

    // Calculate the base (left/right rotation)
    vector direction = llVecNorm(pos - this);
    direction.z = 0;
    rotation final = llRotBetween(<1,0,0>, direction);

    // Calculate the turret (up/down rotation)
    float dist = llVecDist(<pos.x, pos.y, 0>, <this.x, this.y, 0>);
    rotation pitch = llRotBetween(<1,0,0>, llVecNorm(<dist, 0, pos.z - this.z>));

    // Set both values
    llSetLinkPrimitiveParamsFast(getLinkNum("Main"), [PRIM_ROTATION, final,
        PRIM_LINK_TARGET, getLinkNum("UpDown"), PRIM_ROTATION, pitch * final/llGetRootRotation()/llGetRootRotation()]);

    // This is used later for rezzing
    return pitch * final;
}
default
{
    state_entry()
    {
        llSensorRepeat("", "", AGENT, 96.0, PI,1.0);
    }
    sensor(integer num_detected)
    {
        TurnTowards(llDetectedPos(0));
    }
}

Link to comment
Share on other sites

47 minutes ago, Wulfie Reanimator said:

I have no idea why yours is askew like that.

because PRIM_ROTATION is borked for child prims and it's been a known "won't fix" error forever.

and for completeness, the way I would do it:

// I should really thread these 2 functions together and use llAxisAngle2Rot instead of direct sin/cos, but I'm lazy.

rotation YPR2Rot(vector v) // Yaw Pitch Roll
{   return
        <llSin(v.z/2),0,0,llCos(v.z/2)> *
        <0,llSin(v.y/2),0,llCos(v.y/2)> *
        <0,0,llSin(v.x/2),llCos(v.x/2)> ;
}
rotation uVectorRoll2Rot(vector v,float r)
{   return YPR2Rot(<llAtan2(v.y,v.x),-llAtan2(v.z,llVecMag(<v.x,v.y,0>)),r>);
}
Turn_link_towards(vector pos, integer link)
{	vector target= pos-llGetPos(); // assume the offset of the prim from the root is neglidgeable, or account for it here.
    rotation rot =
       uVectorRoll2Rot(target,0);
    llSetLinkPrimitiveParamsFast(link,[PRIM_ROT_LOCAL,rot/llGetRootRotation()]);     
}
// mostly same follower script:
default
{
    state_entry()
    {
        llSensorRepeat("", "", AGENT, 96.0, PI,1.0);
    }
    sensor(integer num_detected)
    {
        Turn_link_towards(llDetectedPos(0),2);
    }
} 

(untested) I would do the linknumber search only once and store in global variables, but I find linkfinding code obnoxious to write, and not really the topic here.

Link to comment
Share on other sites

50 minutes ago, Quistess Alpha said:

because PRIM_ROTATION is borked for child prims and it's been a known "won't fix" error forever.

Ohhh, yeah, that rings a bell.

What was confusing me is that mine works correctly - both moving parts (children) are exactly aligned with each other and the target.

But if the root is rotated along with a child prim, it breaks horribly.

Edited by Wulfie Reanimator
Link to comment
Share on other sites

2 hours ago, Wulfie Reanimator said:

mine works correctly

Did you try rotating the root to a 'crazy' orientation to see if it breaks?

Quote

But if the root is rotated along with a child prim, it breaks horribly.

in the specific case where the root is at ZERO_ROTATION, the 'fix' of dividing through by the root's rotation, is just dividing by 1, which does nothing. or, in simpler terms, if the root has zero rotation, then the global reference frame and local reference frame are the same, and no 'translation' is required to make child prims 'do the right thing'.

Edited by Quistess Alpha
  • Thanks 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 411 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...