Tattooshop Posted August 31, 2021 Share Posted August 31, 2021 Hello! 🖐️ I'm trying to make such a billboard, you've probably all seen one where several prismatic objects with parts of the texture rotate at an angle of 120 degrees (except the root) with a slight delay, one after the other at a certain interval. Wondering how this can be done? (Creating the model itself everything is clear.) Thank's for any help! Link to comment Share on other sites More sharing options...
Xiija Posted August 31, 2021 Share Posted August 31, 2021 (edited) just guessing, but mebbe something like... one texture offset 7 different ways, or 7 textures. a link message of fwd or back, and different delays for rotating each child depending on the direction. hmmm... Edited August 31, 2021 by Xiija 1 Link to comment Share on other sites More sharing options...
Fenix Eldritch Posted August 31, 2021 Share Posted August 31, 2021 (edited) Since each element moves in sequence rather than simultaneously, I imagine you'll want a loop to iterate over each prism, setting the local rotation via llSetLinkPrimitiveParams. You could have a single global variable to keep track of what general orientation the parts should be at (120, 240, 360) and apply it to each element - then update it after finishing the loop. Place all that in a timer with an interval of however long you want the sign to display a single completed side. If you want the elements to move more slowly, then you'll have to make multiple calls to llSetLinkPrimitiveParams to rotate each element in smaller steps one each loop iteration. Using the regular llSetLinkPrimitiveParams instead of the fast variant my be preferable due to the built in delay. Lastly, if you carefully build the model such that each element is linked in ascending sequence, then it simplifies the loop logic, as you can use the same loop-control variable as the link number reference. Edited August 31, 2021 by Fenix Eldritch 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted August 31, 2021 Author Share Posted August 31, 2021 (edited) 6 minutes ago, Xiija said: just guessing, but mebbe something like... one texture offset 7 different ways, or 7 textures. a link message of fwd or back, and different delays for rotating each child depending on the direction. hmmm... Thank you! So I've started with single linked* prim to test... but it doesn't move default { touch_start(integer total_number) { llSetTimerEvent(1.0); } timer() { llSetLinkPrimitiveParamsFast(2, [PRIM_ROT_LOCAL, llEuler2Rot( <0.0, 0.0, 120.0> * DEG_TO_RAD ) * llGetLocalRot()]); } } Edited August 31, 2021 by Tattooshop Link to comment Share on other sites More sharing options...
Tattooshop Posted August 31, 2021 Author Share Posted August 31, 2021 11 minutes ago, Fenix Eldritch said: Since each element moves in sequence rather than simultaneously, I imagine you'll want a loop to iterate over each prism, setting the local rotation via llSetLinkPrimitiveParams. You could have a single global variable to keep track of what general orientation the parts should be at (120, 240, 360) and update it after finishing the loop. Place all that in a timer with an interval of however long you want the sign to display a single side. If you want the elements to move more slowly, then you'll have to make multiple calls to llSetLinkPrimitiveParams to rotate each element in smaller steps one each loop iteration. Using the regular llSetLinkPrimitiveParams instead of the fast variant my be preferable due to the built in delay. Lastly, if you carefully build the model such that each element is linked in ascending sequence, then it simplifies the loop logic, as you can use the same loop-control variable as the link number reference. Thank you! Here is what I have at the moment. Looks, of course, a little strange. I have an idea, but I don't know how to do it - add a list of primitives to rotate here and apply parameters to each item of the list? If it makes sense touch_start(integer total_number) { llSetTimerEvent(15.0); // Full cycle } timer() { llSetLinkPrimitiveParams(2, [PRIM_ROT_LOCAL, llEuler2Rot( <0.0, 0.0, 120.0> * DEG_TO_RAD ) * llGetLocalRot()]); llSleep(5); // Per image llSetLinkPrimitiveParams(2, [PRIM_ROT_LOCAL, llEuler2Rot( <0.0, 0.0, 240.0> * DEG_TO_RAD ) * llGetLocalRot()]); llSleep(5); llSetLinkPrimitiveParams(2, [PRIM_ROT_LOCAL, llEuler2Rot( <0.0, 0.0, 360.0> * DEG_TO_RAD ) * llGetLocalRot()]); llSleep(5); } Link to comment Share on other sites More sharing options...
Tattooshop Posted August 31, 2021 Author Share Posted August 31, 2021 I think the list needs to be squeezed in here llSetLinkPrimitiveParams(LIST?, [PRIM_ROT_LOCAL, llEuler2Rot( <0.0, 0.0, 120.0> * DEG_TO_RAD ) * llGetLocalRot()]); Link to comment Share on other sites More sharing options...
Tattooshop Posted August 31, 2021 Author Share Posted August 31, 2021 (edited) 25 minutes ago, Tattooshop said: I think the list needs to be squeezed in here llSetLinkPrimitiveParams(LIST?, [PRIM_ROT_LOCAL, llEuler2Rot( <0.0, 0.0, 120.0> * DEG_TO_RAD ) * llGetLocalRot()]); and how to make a delay between the elements, because this way they will rotate at the same time ... There will be about 20 such elements, so the list is really needed here (?) otherwise the script will be just gigantic! Edited August 31, 2021 by Tattooshop Link to comment Share on other sites More sharing options...
Fenix Eldritch Posted August 31, 2021 Share Posted August 31, 2021 (edited) 3 hours ago, Tattooshop said: I think the list needs to be squeezed in here llSetLinkPrimitiveParams(LIST?, [PRIM_ROT_LOCAL, llEuler2Rot( <0.0, 0.0, 120.0> * DEG_TO_RAD ) * llGetLocalRot()]); That is not how the function works. Please see the wiki page on how to properly use the function. The first parameter is an integer and as such, can only target a single prim or specific sets as allowed by the special LINK_* constants. If you want to target a subset of prims within the linkset with the same function call, you wold use PRIM_LINK_TARGET within the parameters list. But that's not what you appear to want to do. As said earlier, you indicated you want to move each element one at a time. Therefore it makes more sense to use a single call to llSetLinkPrimitiveParams, targeting just one prim. You would place the function call inside something like a for-loop and use the loop control variable as the input for which link number to target. Also, you don't want to complete a full 360 in the same timer event. The way I understand it is that you begin with all elements at 0 rotation. This effectively makes the sign showing one complete image. You start the timer for however long you want that image to remain (15 seconds from you last example). Then when the timer event happens, you update the rotation variable to 120 and being your for-loop to apply that new rotation variable to all elements - again one at a time, via the loop. So the loop will start at 2 and go for 20 iterations (just as an example, assuming your sign consists of the root plus the 20 elements and nothing else). Each iteration will just target link number X. After the loop completes, the timer event is over and the script idles until 15 seconds elapses and the timer starts again. As before, it updates the global rotation variable to 360, and then performs that loop again, this time updating each element to the new rotation. And so on, and so on. You should also check in the timer to see if the global rotation variable is greater than or equal to 360 and if so, set it back to 0. Does this make sense? Edited August 31, 2021 by Fenix Eldritch minor clarification and typos 1 Link to comment Share on other sites More sharing options...
Quistess Alpha Posted August 31, 2021 Share Posted August 31, 2021 My 2 cents: I'm a bit too disillusioned to help you with the loop logic, but to rotate a linked object 90 degrees about its local z-axis: rotate_linked_object(integer link,vector axis,float angle) { // angle in specified in degrees for demonstration. // personally I always try to keep things in radians if I can help it though. rotation apply = llAxisAngle2Rot(axis,DEG_TO_RAD*angle); rotation local = llList2Rot(llGetLinkPrimitiveParams(link,[PRIM_ROT_LOCAL]),0); // note that PRIM_ROTATION is a bit broken for linked prims, so be sure to use PRIM_ROT_LOCAL. llSetLinkPrimitiveParamsFast(link, [ PRIM_ROT_LOCAL, apply*local // left multiply for a rotation in the local coordinate space of the prim, // if you want to rotate about the root's coordinate system, use local*apply ]); } default { touch_start(integer i) { // rotate link 2 90 degrees about z-axis: rotate_linked_object(2,<0,0,1>,90); } } (untested) 1 Link to comment Share on other sites More sharing options...
Xiija Posted August 31, 2021 Share Posted August 31, 2021 @Tattooshop here is an example for the rotation bit, changes all but the root... . integer tog; rotation rot_90; update() { integer prims = llGetObjectPrimCount( llGetKey() ); integer x = 2; for( ; x <= prims; ++x) { vector ang = <0,0,90>; vector rad = ang * DEG_TO_RAD; rot_90 = llEuler2Rot(rad); list y = llGetLinkPrimitiveParams( x, [PRIM_ROT_LOCAL]); rotation currRot = llList2Rot( y,0); llSetLinkPrimitiveParamsFast( x , [ PRIM_ROT_LOCAL, currRot * rot_90 ]); llSleep(0.25); } } default { state_entry() { } touch_start( integer num) { if( tog = !tog) { llSetTimerEvent(0.1); llOwnerSay("ON"); } else { llSetTimerEvent(0.0); llOwnerSay("OFF"); } } timer() { llSetTimerEvent(10.0); update(); } } 2 1 Link to comment Share on other sites More sharing options...
Tattooshop Posted September 1, 2021 Author Share Posted September 1, 2021 13 hours ago, Xiija said: @Tattooshop here is an example for the rotation bit, changes all but the root... . integer tog; rotation rot_90; update() { integer prims = llGetObjectPrimCount( llGetKey() ); integer x = 2; for( ; x <= prims; ++x) { vector ang = <0,0,90>; vector rad = ang * DEG_TO_RAD; rot_90 = llEuler2Rot(rad); list y = llGetLinkPrimitiveParams( x, [PRIM_ROT_LOCAL]); rotation currRot = llList2Rot( y,0); llSetLinkPrimitiveParamsFast( x , [ PRIM_ROT_LOCAL, currRot * rot_90 ]); llSleep(0.25); } } default { state_entry() { } touch_start( integer num) { if( tog = !tog) { llSetTimerEvent(0.1); llOwnerSay("ON"); } else { llSetTimerEvent(0.0); llOwnerSay("OFF"); } } timer() { llSetTimerEvent(10.0); update(); } } Thank you so much!!! You are genius! This is perhaps the most satisfying thing I've seen in SL! As for me, you did a real feat, the script is wonderful! It is already a pleasure to just watch them turn over one by one. Thank you! 👍 1 Link to comment Share on other sites More sharing options...
Quistess Alpha Posted September 1, 2021 Share Posted September 1, 2021 Looks great, although the uneven spacing bothers me a bit; if it were me I'd unlink, and with everything still selected use the align tool (with shift held down) to move the pieces perfectly flush with each other. 1 Link to comment Share on other sites More sharing options...
Nova Convair Posted September 1, 2021 Share Posted September 1, 2021 A comment about the geometry: In SL you can rotate squares put next to each other of course, but if it's supposed to work like a RL board you need triangles with 3x60° The op's example shows triangles with 1x90° and 2x45° - that will not work. It's necessary to mesh the triangle elements with the axis in the center. It's probably possible to bend a prim but the axis will not be in the center then and the rotations would be very painful. 🙃 1 Link to comment Share on other sites More sharing options...
Quistess Alpha Posted September 1, 2021 Share Posted September 1, 2021 (edited) 3 minutes ago, Nova Convair said: It's probably possible to bend a prim but the axis will not be in the center then and the rotations would be very painful. 🙃 Um, you do know that prisms are a basic prim type, no? A perfect equilateral triangle cross-section is the default with its axis in the center. Edited September 1, 2021 by Quistess Alpha 1 Link to comment Share on other sites More sharing options...
Nova Convair Posted September 1, 2021 Share Posted September 1, 2021 1 minute ago, Quistess Alpha said: Um, you do know that prisms are a basic prim type, no? A perfect equilateral triangle is the default with its axis in the center. Show me one - 3x60° triangle - rotation axes in the center. I will have a look when I get on later. Although I have never seen one I know there are shapes I've never tried. 1 Link to comment Share on other sites More sharing options...
Fenix Eldritch Posted September 1, 2021 Share Posted September 1, 2021 Like Quistess said: it's the prim type "Prism". By default the X and Y taper is set to 1.0 which results in a tetrahedron, but if you set the tapers to 0.0, you get the desired prism. 1 1 Link to comment Share on other sites More sharing options...
Nova Convair Posted September 2, 2021 Share Posted September 2, 2021 Oh cool 😁 Guess I forgot some details about prims. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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