Jump to content

Help requested: rotating child prim on moving object


Shard Soyinka
 Share

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

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

Recommended Posts

Whenever I start to deal with vector math and radians my eyes just start to glaze over. 

So here's the problem: I have a train (non-physical moving multi-prim object) and I want a child prim (a load on the train) to always be pointing in the same direction (example: always face North) even while the train is in constant motion.

Setting the initial vector for the for the child prim's facing isn't the issue, it's doing the math and rotation to keep it facing that way.  

Please help.

Link to comment
Share on other sites

This ought to do it.

Use a timer to poll the current rotation of the cargo object:

        rotation rCargo = llList2Rot(llGetLinkPrimitiveParams(iCargoLink,[PRIM_ROTATION]),0);

        vector vCargo = llRot2Fwd(rCargo);
 

and then update it:

        rotation rCargoUpdate = llRotBetween(vCargo, <0.0,0.0,PI/2>);

Link to comment
Share on other sites

See, I'm already kind of lost on what every line is doing. Is this how you'd implement that?

    timer()
    {
        rotation rCargo = llList2Rot(llGetLinkPrimitiveParams(iCargoLink,[PRIM_ROTATION]),0);
        vector vCargo = llRot2Fwd(rCargo); 
        rotation rCargoUpdate = llRotBetween(vCargo, <0.0,0.0,PI/2>);
        llSetLocalRot(rCargoUpdate);
    }//timer

I figure the idea is that I have a specific vector I want the Cargo prim to be facing,
So I need to check the cargo's current facing vector and compare it to the one I want it to face,
Then rotate the cargo back to that vector?

Alternatively, and this seams like a stupid kludge:
I could just set a timer event to re-position the Cargo prim to the vector I want it to face.  

Link to comment
Share on other sites

Almost.  That snippet I was suggesting is getting and updating regional rotation, not local rotation, because you said that you wanted the cargo to keep facing north.  So your last line should be

llSetLinkPrimitiveParamsFast( iCargoLink, [ PRIM_ROTATION, rCargoUpdate ] );

Your timer will be repeatedly checking to see which way its X axis is pointing and then rotating it to be sure that it's pointing North.  If you'd rather keep some other vector pointing north, just identify the vector and do the same trick.

@Quistess Alpha might have a different approach.  Let's see ...

Link to comment
Share on other sites

At this point I feel it is necessary to share a personal story as I do have a mental block involving vector math:

While I was in college an @$$hole (now ex) boy-friend borrowed my calculator and set it to Base 8 math because he was a Math Major and I guess thought it would be funny to never tell me when he returned it. A professor helped me discover this nearly a full semester later after almost failing my 200 lvl Calculus, Organic Chemistry and Physics classes, passing out from 2 stress headaches (WHILE DRIVING and nearly having a car accident), and a nervous breakdown from thinking I was going to lose all my financial scholarships and fail out of college. 

So, I appreciate the help. 

 

  • Like 1
Link to comment
Share on other sites

Geez, that was a sadistic thing for him to do.  

You can take some comfort in knowing that many people have trouble with vector math and yet still manage to do impressive scripting.  If you make yourself a nice cheat sheet with formulas that you use frequently or refer to someone else's, like the really nifty notes that Tessa put in the LSL Library, you will survive with only mild bruising.

 

  • Like 1
Link to comment
Share on other sites

A couple ways to go about it, here are two of them:

rotation rMyGlobalRotation; // this is the orientation we want to have. (only used in option 1)
default
{
  state_entry()
  {   rMyGlobalRotation = llAxisAngle2Rot(<0,0,1>,PI_BY_TWO); 
      // assuming a 'standard orientation' object points east,
      // rotate 90 degrees counter clockwise to face north.
      llSetTimerEvent(0.2);
  }
  timer()
  {   
    //
    // OPTION 1:
    //   Constant global orientation 
    
    rotation rRoot = llGetRootRotation();
    llSetLinkPrimitiveParamsFast(LINK_THIS,
    [  PRIM_ROT_LOCAL, // PRIM_ROTATION is often borked for child prims.
        rMyGlobalRotation/rRoot
    ]);
    
    //
    // OPTION 2:
    //   Turn by the global comapss angle (when tipped over: inaccurate but less wonky than option 1.)
    
    vector FWD = llRot2Fwd(llGetRootRotation()); // where is the root facing?
    float angle = llAtan2(FWD.y,FWD.x); // angle the root is facing in radians;
        // ^^ 0 radians == East, PI_BY_TWO == North, PI == WEST, -PI_BY_TWO = SOUTH
    rotation turn = llAxisAngle2Rot(<0,0,1>,PI_BY_TWO-angle);
        // ^^ want to face north (PI_BY_TWO)
    llSetLinkPrimitiveParamsFast(LINK_THIS,
    [   PRIM_ROT_LOCAL, turn
    ]);
  }
}

Of course, things change slightly for objects not in 'SL Standard Orientation' (z= up, x= forward East, y = left North)

  • Like 1
Link to comment
Share on other sites

5 hours ago, Rolig Loon said:

rotation rCargoUpdate = llRotBetween(vCargo, <0.0,0.0,PI/2>);

Nothing too wrong with it in this use-case, but I try to not use llRotBetween when writing an example. It usually doesn't do "the intuitive thing" (whatever that might be) when working in 3 dimensions, and if you want to work exclusively in the x-y plane, it might be "better form" to do something like:

rotation rCargoUpdate = llAxisAngle2Rot(<0,0,1>, llAtan2(vLookAt.y,vLookAt.x) - llAtan2(vCargo.y,vCargo.x) ); 

 

Edited by Quistess Alpha
I quoted te wrong thing.
  • Like 2
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 554 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...