Jump to content

Problem with Rotation of Linked Objects attached to Avatar's (worn)


Gromlok Landar
 Share

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

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

Recommended Posts

I'm curious about something, I recently made a Pilot's Helmet,  It has a night vision scope and Visor that moves via a recently created HUD on a random channel per Avatar user.  I set the rotations etc with the Helmet off (meaning on the ground) in a Sandbox (Skidz).  When I attach the Helmet to my Skull and try out the buttons (on the HUD) to make the linked objects on my Helmet (attached to my Skull) move, turns out the rotations are seriously off and the objects (linked) are skewed, yet I rez the helmet back on the ground and the links move perfectly as I predicted they would.  When I edit the Helmet to look at the rotations, the x axis shows a rotation of 56.0 while the y and z show 0.00.

Am I missing something here as to the rotations not moving properly ?

Gromlok Landar

Owner: Vortex Industry Designs

Link to comment
Share on other sites

Yes, you are missing something.  Take a very good, long look at http://wiki.secondlife.com/wiki/Rotation#Single_or_Root_Prims_vs_Linked_Prims_vs_Attachments .  When you use llSetRot or the equivalent with SLPPF, the rotation of an attachment's root prim is a local rotation relative to the attachment point.  The rotations of child prims are all local rotations relative to the attachment's root.  In practice, that means you have to use llGetLinkPrimitiveParams first to get the local rotations and then apply whatever corrections are neccesary to child prims to make those rotations relative to the root.

 

Link to comment
Share on other sites

That's what I did, here's the script below:

 

vector close_vec = <0.00060, -0.10685, 0.03051>;
vector open_vec = <0.00060, -0.06425, 0.06505>;
rotation close_rot = <0.31732, -0.00000, -0.00000, 0.94832>;
rotation open_rot = <-0.43837, 0.00000, 0.00000, 0.89880>;
integer open;

rotation Inverse(rotation r)
{
r.x = -r.x;
r.y = -r.y;
r.z = -r.z;
return r;
}

default
{
state_entry()
{
open = FALSE;
}

on_rez(integer sparam)
{
llResetScript();
}



link_message(integer sender, integer num, string str, key id)
{
if (str == "Up") {
open = FALSE;
llSetPrimitiveParams([PRIM_POSITION, close_vec, PRIM_ROTATION, close_rot * Inverse(Inverse(llGetLocalRot())*llGetRot())]);
} else if (str == "Down") {
open = TRUE;
llSetPrimitiveParams([PRIM_POSITION, open_vec, PRIM_ROTATION, open_rot * Inverse(Inverse(llGetLocalRot())*llGetRot())]);
}
}
}

 

Oh I'm new to scripting but I don't have an ego to bruise, so no need to be gentle.

Link to comment
Share on other sites

There are several things to focus on here.  Since you are apparently dealng with a one-prim attachment, you don't need to worry about rotating child prims, so that makes things easier.  First, you are getting the attachment's local rotation with llGetLocalRot(), but you shouldn't be multiplying it by llGetRot(), which is the global rotation of the avatar. After all, you already know that the attachment point will travel with the avatar, so you only need to know the attachment's relative rotation.

Second, there's no need to keep getting the local rotation over and over again.  Get it once, rotate from there when str = "Up", and then reset to the original local rotation when str = "Down". Remember that you should be using PRIM_ROT_LOCAL, not PRIM_ROTATION.

Third, the same thing applies to your local position, which you can get with gLPos = llGetLocalPos, add an offset to, and then reverse the offset when str changes from "Up" to "Down";  Again, remember to use PRIM_POS_LOCAL instead of PRIM_POSITION.  Your open_vec is therefore gLPos + offset*llGetLocalRot(), and close_vec is gLPos - offset*llGetLocalRot().

Fourth, try to avoid using llSetPrimitiveParams, which has a 0.2 second delay.  Use llSetLinkPrimitiveParamsFast, which has no delay. 

Fifth, purely a matter of personal taste, it takes less effort to reverse a rotation by changing the sign on its s component than by changing x, y, and z.   It's also worth noting that you can also reverse the direction in this case by writing

gLRot = ZERO_ROTATION/gLRot    (where gLRot is your stored value of open_rot*llGetLocalRot), so you can toggle

gLRot = ZERO_ROTATION/gLRot;

llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL, gLPos + (offset = -offset)*gLRot,PRIM_ROT_LOCAL,gLRot]);

when str changes from Up to Down and vice versa.

Rotations can be a real bear.  I always have to stop and think carefully every time I work with them, and I am never 100% confident that I have done it right until I can see the results in world.  I think what I just wrote will work, but I have my fingers crossed.

Link to comment
Share on other sites

Actually its 15 mesh prims with a PE of 23 and two mesh prims (Convex Hull) are rotating so yes I'm dealing with Child Prims , I'm looking at what you wrote and will update my scripts and test them to the best of my ability but I'm not holding my breath.  

Update: I managed to get the mesh prims to move and rotate in the direction desired but now I am encountering a problem, seems when I turn left/right or backwards and the prims now rotate in the direction I was initially facing when I set up the rotations/movements.

Thanks

Grom

Link to comment
Share on other sites

Good luck.  That makes it significantly more complicated.  Those child prims are now in the far right column  -- the red box -- in that table at https://wiki.secondlife.com/wiki/Rotation#Single_or_Root_Prims_vs_Linked_Prims_vs_Attachments that I refered you to earlier.  You'll have to apply an extra rotation to each of them, and deal with that rotation as a correction to their position offsets as well.  This makes my head hurt.

  • Like 1
Link to comment
Share on other sites

Hey Welcome to my world, so I've come up with a different scenario, instead of making them physically move and rotate, simply setting it to Alpha works as well.  Though they are still there, it significantly easier to do and gets a similar result.

I keep getting a bounds check error and it seems I did something that the LSL code isn't meant to do for some odd reason.

Working on it and won't stop till it works.

Grom

Link to comment
Share on other sites

Well its not a big problem considering avatar attachments dont count towards the PE of the Land/Sim so you could have 1000 prims linked together and wearing it and still be 0 :)  

Seems the BoundsCheck Error that is coming up is with the random channel listener for the HUD to communicate with the Helmet, go figure.

Grom

Link to comment
Share on other sites

So long as you're content with changing the alpha, that's great (though I think there are, or have been, various issues with switching the alpha on mesh prims), but the formula for actually moving  child prims (attached or unattached)  is, I think, on the lines of 

rotation rot;vector offset = <0.5,0.0,0.0>;integer toggle;default{    state_entry()    {        rot = llEuler2Rot(<0.0,90.0,0.0>*DEG_TO_RAD);    }    touch_start(integer total_number)    {                list li = llGetLinkPrimitiveParams(2,[PRIM_ROT_LOCAL,PRIM_POS_LOCAL]);        rotation local = llList2Rot(li,0);        vector pos = llList2Vector(li,1);        llSetLinkPrimitiveParamsFast(2,[PRIM_POS_LOCAL, pos+offset,PRIM_ROT_LOCAL,rot*local]);        rot.s*=-1;        offset *=-1;    }}

 

  • Like 1
Link to comment
Share on other sites

Many Thanks, I have taken the liberty of looking at that script, seems the main area of focus is Global Rot instead of Local Rot as Rolig mentioned previously but I am seeing the logic behind the script you put here.  I did figure out the Bounds Check Error, my HUD is now communicating on Channel 3611 as is the Chopper's Helmet, the Alpha works like a charm on mesh and I have been constantly testing it for the past 2 days now, haven't had a problem yet even under the most laggiest times (if Laggiest is such a word, if not we'll create that as a new word for now :)  ).  I will look at that script and attempt to make it work one way or the other.

On another note, I have created the HUD which is quite generic at the moment though will go into Photoshop and make the buttons and HUD itself prettier (not really a guy word but oh well) and make it look authentic and original.  However I am looking for guidance as to where to find info on when a HUD button is pressed, it would light up When touched to signify that its in use or has been pressed.  I find that having two buttons for the same object a bit low end.  Example below:

One button is to alpha the visor and one to make it re-appear, alter this so that one button for the visor is used, when its not pressed, the button is green and the visor is visible, pressing the button again on the HUD the button goes red, visor alpha's.

Hope that made sense.  I am so new to scripting but I want to alter this HUD for the Chopper Helmet and my Super Comanche RAH-66E Helicopter HUD as well since both will be included as a package deal and the Helmet separately in case people don't want the Chopper itself.  

Grom

Link to comment
Share on other sites

I would simply use llSetLinkPrimitiveParamsFast to change the HUD button (either its colour or its texture) at the same time you switch the visibility of the helmet prims,  If you change the texture, I would suggest making a single texture with both the red and green buttons on it, and switching their visibility using llOffsetTexture, so you don't risk the hud button turning grey while it loads one or another texture.

Link to comment
Share on other sites

There's a reason why I use a random channel or want to, if 2 people have the same helmet and HUD, should one decide to raise their visor, the visor would raise on both helmets via one HUD.  I am trying to use:

 integer channel = (integer)("0x"+llGetSubString((string)llGetOwner(),-16,-1)) ;

yet its still communicating on channel 0 :(

Pat

Link to comment
Share on other sites

That's because llGetSubString((string)llGetOwner(),-16,-1) is not an integer.  When you try to evaluate it as one, with its includied hyphens, the answer you get is zero.  Hence channel 0.  Don't use the entire UUID.  Not only that, you should use a negative integer for communicating between objects, so try

(integer) ("0xF" + llGetSubString(llGetOwner(),0,6))

as I suggested eaarrlier.  Even working with a seven character substring of a UUID, you'll have plenty of "random" channels to play with.  The probablity of crosstalk is pretty minimal.

Link to comment
Share on other sites

Two ways of avoiding cross-talk would be either, in the helmet, testing for 

if(llGetOwnerKey(id)==llGetOwner()){}

 in the listen event, or (and preferably), having the hud say something like

llRegionSayTo(llGetOwner(),some_channel,message);

 which should ensure that only items listening on some_channel that the owner is wearing receive the message.

Link to comment
Share on other sites

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