Jump to content

Script n00b needs a Lid Rotation Script


Sy Beck
 Share

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

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

Recommended Posts

After trying to meddle with numerous example scripts and reading numerous posts of people wanting a lid rotation script I am throwing myself prostrate here for help.

My problem is that I made a mesh pedal bin weighing in at 1 LI, but I paid no aforethought to scripting the lid opening thinking that I would just drop a hinge door script in.  However, as many before me have found, and the smart people here already know, this is far from ideal or good practice.  The door script I used meant I had to break up the mesh into 3 parts, which increased the LI to 3.  Also, if I was to go forward from here using that script (a Paskis door hinge script) then I would have to package the item as a coalesced object, which again is not ideal.

I have tried to use various example scripts I have found on the electric interwebz to no avail, as looking at them for me is like trying to translate Manadarin while drunk and I only feel competent in one of those aspects.

So can anybody point me to a script where I can clearly see the lines/language where I have to change the values to make the rotation work how I want it to or even point me to Marketplace product, which will do the same?

So what do I want it to do?  

The picture below shows the model as it presently is and I've colour-coded it to represent the various parts with Yellow being the root prim, Blue is link 2 and Red is link 3.  Ideally I want to rejoin yellow and blue as one object and have the lid rotate around what is now yellow on the X axis and raise up by 70 degrees with a simple Touch to open and close and smooth animation.  Barring that then any script that would enable me to link all 3 objects and not have to package it as a coalesced object.



Please bear in mind in any responses what I said about LSL looking and reading like Manadarin...I meant it.  Also, if this kind of script is some arcane and closely guarded trick of the scripters (scriptors?) of SL then please PM me or IM me inworld to discuss commissioning a full perms version as I see myself wanting to use this kind of script many times in the future.

Many thanks in advance, Sy.

Link to comment
Share on other sites

If you have read numerous posts here, you have probably seen https://community.secondlife.com/t5/LSL-Scripting/Rotate-a-Mesh-Prim/m-p/2910994 .  If not, do it now.  Unless you want to redo your mesh model properly, with an offset edge, you will probably find that the method Innula Zenovka recommends in that thread is your best bet.

Link to comment
Share on other sites

Alternatively, you might want to follow the procedure described in this tutorial, and re-upload your mesh.   

 

It's not complicated to use a script to move the point about which the lid rotates -- as Rolig says, I posted a demonstration -- but since you're clearly more comfortable making meshes than writing scripts, you might find this method easier.

 

Link to comment
Share on other sites

If I had a dollar for everytime I've read yours, Innula's or Void's posts on door/lid rotations these last few days then I would be a happy and moderately more richer man. :matte-motes-big-grin:

So this is an example of my lameness in understanding LSL re Innula's script.  Where in this do I change from a 90 degree rotation on Z to a 70 degree rotation on X when I don't even see 90 or Z in the line where she comments it's a 90 degree Z rotation?  

 

integer intSwing =90;rotation rotSwing;vector vOffset;default{    state_entry()    {              vector size = llGetScale();       vOffset = <(size.x*-0.5),(size.y*-0.5),0.0>;//open away from someone standing in front of face 2 -- that is, in front of the prim -- hinged on the left.    }    touch_start(integer total_number)    {         list l = llGetPrimitiveParams([PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);         vector v = llList2Vector(l,0);         rotation r = llList2Rot(l,1);         llSetPrimitiveParams([PRIM_POS_LOCAL,v+(vOffset-vOffset * rotSwing)*r,         PRIM_ROT_LOCAL,rotSwing*r]);         rotSwing.s*=-1;             }}

P.S. I would agree that it would be simpler to go back and add in a plane to move the origin, but I did want to explore this avenue for what now seems a masochistic intent.

Link to comment
Share on other sites

This is what I should have done yes!  But fools rush into doors that suddenly don't open as intended!  As I said in my post to Rolig, I've drawn myself into this thinking I would easily find a script to save me the time to go back and do that.  I am a very good example of a bad example I know.  :matte-motes-bashful:

Link to comment
Share on other sites


Sy Beck wrote:

If I had a dollar for everytime I've read yours, Innula's or Void's posts on door/lid rotations these last few days then I would be a happy and moderately more richer man. :matte-motes-big-grin:

So this is an example of my lameness in understanding LSL re Innula's script.  Where in this do I change from a 90 degree rotation on Z to a 70 degree rotation on X when I don't even see 90 or Z in the line where she comments it's a 90 degree Z rotation?  

 
integer intSwing =90;rotation rotSwing;vector vOffset;default{    state_entry()    {              vector size = llGetScale();       vOffset = <(size.x*-0.5),(size.y*-0.5),0.0>;//open away from someone standing in front of face 2 -- that is, in front of the prim -- hinged on the left.    }    touch_start(integer total_number)    {         list l = llGetPrimitiveParams([PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);         vector v = llList2Vector(l,0);         rotation r = llList2Rot(l,1);         llSetPrimitiveParams([PRIM_POS_LOCAL,v+(vOffset-vOffset * rotSwing)*r,         PRIM_ROT_LOCAL,rotSwing*r]);         rotSwing.s*=-1;             }}

P.S. I would agree that it would be simpler to go back and add in a plane to move the origin, but I did want to explore this avenue for what now seems a masochistic intent.

intSwing = 90; Here's your 90°.

Vectors are <X,Y,Z>, so <0.0, 0.0, float(intswing)> has the rotation on the Z-axis, in degrees. 

To shift to X, you'd write...

<(float)intSwing, 0.0, 0.0>

And llEuler2Rot() wants radians.

*DEG_TO_RAD converts that vector to radians.

I'd have declared swing as a float from the start, thereby avoiding the (float) typecast. And because I'm lazy, I'd only use decimal points when they're needed. So you'd want...

float swing = 70;

and

rotSwing = llEuler2Rot(<swing,0,0>*DEG_TO_RAD); //70 degress on the x

Link to comment
Share on other sites

Thanks Maddy that's clarified that for me (honestly) so I thank you for that and I edited it and tested it and all is hunky dory, but it advances me no further than the Paskis door script that I'm already using.  What I need is to be able to link all three together yet only have the lid and hinge rotate.  

I extracted some knowledge while reading through all the various posts elsewhere where it said that I need a script function that would identify the linked parts in my mesh to be rotated so that the bin container, in this case, would remain stationary while only the lid and hinge revolved in sync.

I'm guessing that's the code that I need to hammer into Innula's script?  If so what is it, where is it and can I just add it in or does it need to be integrated by somebody who knows what they are doing i.e. not me.

And once again thanks to all of you.

And to anyone reading this in the future, just build the offset in the model.

Link to comment
Share on other sites

I'm no expert, but lsl rotation calls always operate on a prim's axis. If that's not where you want it (and it isn't), you have only two choices.

1) Attach the prim to a root prim hinge located at the desired rotation point. As you already know, this forces you to create a coalesced object, as rotating the root prim rotates the entire linkset. You could try to rotate the garbage bin in the opposite direction, cancelling out the root rotation, but that would require the bin to have its center at the hinge location, and I'll guess that's not the case, just as it's not the case for the lid.

2) Both rotate and translate the lid. This could be done entirely from the bin, needing no hinge prim. And it would require you to know precisely where the lid's actual center is, and to work out the trigonometry for both the translation and rotation of its center.

I think I might do this by assembling the lid/bin in-world in the closed position (you've already done that). Write down the locations and rotations of both the bin and lid. Make sure the bin is aligned so the hinge is pointing exactly along the X (or Y) axis, so that your lid rotation is around only that axis.

Next, move the lid to your desired open position. Again, record the position and rotation of the lid. If you subtract the position of the bin from the position of the lid, you have the offset between them. If you subtract the rotations, you have the relative rotations between them. Those are the endpoints of the path you want the lid to follow when it opens/closes. Now you have a choice. You can either scratch your head and work out the math for intermediate points. The rotation is easy, just divide your 70 degrees by the number of steps you want in the lid opening action. The translation is harder, as you're tracing a 70 degree arc of the lid's center about the hinge position.

I'd skip all that hard thinking and just open the lid in 10 degree increments, moving it with the editor each time to get the hinge point back where I want it. Record the lid's position. Do that until you have all eight positions from open to closed.

Now, gather up all those positions and make then relative to the bin by subtracting the bin position from each measurement. Key all those offsets and rotations into...

http://wiki.secondlife.com/wiki/LlSetKeyframedMotion

That will smoothly animate the lid between your keyframes. Seven steps might be enough to fool the eye. If not, you can fiddle with more intermediate positions, or you could plot the relative positions in Excel and see that they're tracing a circle, then work out the math to generate the exact curve and pull as many points from that as needed to get a smooth animation.

Good luck, I'm glad it's you doing this and not me! I've got windows to paint here in RL.

;-).

ETA: llSetKeyframedMotion takes a list of relative motions, each referenced to the previous position of the object. So only the first keyframe contains the offset from the bin to the lid (ETA oops! wrong!), each subsequent step takes the offset from the previous lid position. So amend my instructions accordingly. After each manual move of the lid, record the change in location from the previous move. If you move the lid 10° each time, that part of each keyframe will always be 10°. The script would be contained in the lid, setting it's starting keyframe relative to the bin (the first measurement you made).

And everything I've said is nonsense if llSetKeyframeMotion can't move only one prim in a linkset. I've only used it to move a single prim object. If that's so, then you'll have to use all those position/rotation measurements to fill multiple calls to llSetLinkPrimitiveParamsFast() by a script in the bin.

I really am glad you're the one doing this.

ETA2: Ack, I think you'd initially move the lid into position relative to the bin via llSetPos() and llSetRot(), and then use llSetKeyframedMotion() after that. The two methods I've described would both use the measured keyframes, but one of the them (llSKFM) would want each keyframe relative to the previous keyframe (script is in the lid) and the llSLPPF method would want all keyframes relative to the bin (script is in the bin).

Link to comment
Share on other sites

My example script was written for a single mesh item.  

As far as I'm concerned, one of the huge advantages of using mesh for this sort of build rather than prims or sculpties is that you can make a single mesh containing all the components of the door (lid, whatever) and move them as one unit rather than have to try to move two or three child prims separately.

That's because if the limits inherent in SL -- it's very difficult indeed to move three child prims about and keep them together while they're moving.   The lid will look OK when it's open or shut, but not while it's moving from one position to the other.   The door and the handle are likely to drift apart while in motion and then re-assemble themselves when they stop.

What you're asking is to be shown how to use a method I'd use only if there's really no alternative, because it's complex and the end results don't usually justify the extra effort.  

 

Link to comment
Share on other sites

Yeah, if you really can script movement of parts of a single mesh object, that's how I'd do it, even if that send me back to Blender. Outside of using llSetKeyframedMotion(), I've never been able to script simultaneous translation and rotation in a way that looked right to me. So I'd do what's needed to move a mesh section axis where it needs to be.

Link to comment
Share on other sites


Madelaine McMasters wrote:

 
A lot of hard work

Good luck, I'm glad it's you doing this and not me! I've got windows to paint here in RL.

;-).

 

I think I would rather watch the paint dry on your windows :matte-motes-big-grin:

 

Thanks anyway Maddy.  As I said earlier I've fallen down an intellectual rabbit hole pursuing this with what I thought would be a quick workaround for a 10 minute job that I should have done in Maya/Blender, but curiosity has led me this far and now no further.  

/me grumbles off

Link to comment
Share on other sites

If you have to move several child prims together by script, then the best way I know to do it is record their local positions and rotations in both the open and closed states, and then hard-code them in the script.

Then you use llSetLinkPrimitiveParamsFast(LINK_SET,[PRIM_LINK_TARGET, doorLinkNumber, PRIM_POS_LOCAL, some vector, PRIM_ROT_LOCAL, some rotation, PRIM_LINK_TARGET, handleLinkNumber, PRIM_POS_LOCAL, some vector, PRIM_ROT_LOCAL, some rotation. ....]);

Then you leave it to SL and people's GPUs to interpolate the movment between the open and closed positions as best they can.    However, that's not something I do if I can avoid it -- remaking the mesh almost always results in a better-looking solution.

 

Link to comment
Share on other sites


Innula Zenovka wrote:

 

What you're asking is to be shown how to use a method I'd use only if there's really no alternative, because it's complex and the end results don't usually justify the extra effort.  

 

I totally agree and as I just said to Maddy I fell down a rabbit hole instead of just doing the correct thing and going back to the model, which I shall do this evening.

It was interesting though ploughing through all of yours, Rolig's and Void's posts over the years concerning this subject and led me to wonder why it's not possible to import a new pivot point for a object into SL or even have a script that could relocate it inworld.  I can see how it might cause problems interacting with existing scripts/objects, but surely that could be overcome by having two identifiers such as "prim centre" and "rotation centre".  However, as I have undoubtedly proven this field of expertise is beyond me.

Thanks for your help Innula.

Link to comment
Share on other sites

The problem with recording open/closed states and letting the GPU interpolate is that, while the rotation will be fine, the translation will be along a line and not an arc. That's why I recommended creating at least a few waypoints between open and closed.

It's been ages since I've scripted anything, but llSKFM was a huge improvement over llSLPPF in a swinging price tag on a string I once made. I tried scripting it by feeding waypoints to llSLPPF and there was always something not quite right about the result. I think I noticed that, even though rotation and translation were both specified in each call, there was a sight time gap between the operations. My llSKFM price tag made me happy.

Link to comment
Share on other sites

For the sake of 30 odd mins in Blender and re importing and trying to do a botched job which  the rotation wll look awfull does not make sense. A botched job never hides and allways has a huge sign above it. Best rembered lessons in life like this is "i will never get caught out again"

Link to comment
Share on other sites


Sy Beck wrote:


Innula Zenovka wrote:

 

What you're asking is to be shown how to use a method I'd use only if there's really no alternative, because it's complex and the end results don't usually justify the extra effort.  

 

I totally agree and as I just said to Maddy I fell down a rabbit hole instead of just doing the correct thing and going back to the model, which I shall do this evening.

It was interesting though ploughing through all of yours, Rolig's and Void's posts over the years concerning this subject and led me to wonder why it's not possible to import a new pivot point for a object into SL or even have a script that could relocate it inworld.  I can see how it might cause problems interacting with existing scripts/objects, but surely that could be overcome by having two identifiers such as "prim centre" and "rotation centre".  However, as I have undoubtedly proven this field of expertise is beyond me.

Thanks for your help Innula.

That's why I prefaced my reply with "Unless you want to redo your mesh model properly, with an offset edge ... "  There are good, straightforward ways to rotate doors and box lids, but the scripting gets more and more complex as you have child prims and odd geometries to deal with.  It's SO much easier if you simply start with a well-made model that already has a hinge edge defined. 

The problem is basically geometry.  Rotation is always assumed to be around one of an object's primary axes (X, Y, Z), which intersect at the object's center ("prim centre" in your terms).  You can't change that fundamental geometry, so any script has to calculate where the hinge axis that you want to rotate around is supposed to be (your "rotation centre").  If the object is a single, unlinked prim, the calculation is trivial.  You can see where it is supposed to be.  As soon as you have other prims hanging on, though, it becomes a non-trivial calculation -- and it's one that you have to repeat for every child prim in the linkset, so that they move together. Innula and I avoid doing that unless we have no other choice. After you have scripted a few dozen doors using different methods, you finally get a feel for how this all works, but it' s never simple.  The only way to force it to be simple is to mess with the basic geometry  -- which is why we have each said that your smartest move is to rebuild the mesh.

Link to comment
Share on other sites

It was doors that got me involved in scripting in the first place, as it happens.

This was back before Void showed us all how to do it properly, and I had got sick of paying what then seemed a lot of money for door scripts that never quite worked how I wanted them to.

I'll learn how do it myself, I thought.  How difficult can it be to open and close a  door, after all?

I soon found out!

Link to comment
Share on other sites

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