WayneScott Posted November 30, 2019 Share Posted November 30, 2019 I want a steam engine with a particular aesthetic, and couldn't find it on the MP, so I started building it ... which is half the fun anyway :) I have it built, and started scripting the moving parts. I'm cutting myself a fair bit of slack by having the flywheel attached to a 'hidden' camshaft (i.e. there is no camshaft, but you can't tell that because it's enclosed) but I really want a visible piston shaft, with noticeable movement. Given that I've scripted the rest of the moving parts to permit me to vary the speed (which is all just llTargetOmega() anyway), the ability to change the rate that the cylindrical prim (piston shaft) is moving back and forth along it's axis is a must. I've moved prims in the past, using llSetPos(), but that doesn't let me control the rate of movement. Research has turned up llSetKeyframedMotion() and llMoveToTarget() ... but I don't see any way to control the rate of movement with them suitably. I'd appreciate it if someone could point me in the right direction, or even tell me what I want is impossible because it's 4 am and my brain is starting to leak out of my ears. On that note, I'm going to bed. TIA for any assistance :) Link to comment Share on other sites More sharing options...
Qie Niangao Posted November 30, 2019 Share Posted November 30, 2019 (edited) llSetKeyframedMotion and llMoveToTarget are useful for moving entire objects but the goal here seems to be moving parts of an object, for which the PRIM_POS_LOCAL parameter of llSetLinkPrimitiveParamsFast() is most suited. To control the speed of motion you'll vary the distance moved per update, the number of timer()-triggered updates per second, or both. Keep in mind that, like llSetPos(), each update is a separate function call and a separate message from sim to viewer, which means a lot more lag than the simple fire-and-forget llTargetOmega(), so it's good practice to keep that timer as slow as possible while maintaining acceptably smooth motion. A relatively recent thread has some potentially relevant sample code for a different application of oscillating motion. [EDIT: I have only a vague sense of the object under development, but you may be satisfied using texture animation to "move" which of several "piston shaft" positions is opaque. That can be a whole lot less laggy and the speed is easily controlled by the rate parameter of llSetTextureAnim().] Edited November 30, 2019 by Qie Niangao 1 Link to comment Share on other sites More sharing options...
Profaitchikenz Haiku Posted November 30, 2019 Share Posted November 30, 2019 (edited) In order to have both the reciprocating motion of a piston rod and the proper motion of the coupling and connecting rods you are going to have to learn puppeteering. This is done by using llSetLinkPrimitiveParamsFast to move the components several times a second. I have a steam engine where the wheels rotate, the coupling rods move with them, and puffs of steam occur four times each wheel revolution. All the positions of the components were worked out and are stored in lists so that there is no need to do any calculations whilst in motion. The locomotive moves by a pre-calculated amount for each change which is the fraction of the wheel circumference divided by the number of spokes, since each animation frame is based on the driving wheels rotating enough for one spoke to move to the next spoke position. ETA Qie's point about the timer interval is important, in order to have a smooth-looking locomotive from the inside of the attached carriage you will need a quite fast timer, Edited November 30, 2019 by Profaitchikenz Haiku 1 Link to comment Share on other sites More sharing options...
Rolig Loon Posted November 30, 2019 Share Posted November 30, 2019 (edited) The design challenge here is how to relate the rotary motion of the wheel to the reciprocal motion of the camshaft. Unlike in RL, where the camshaft's forward thrust drives the wheel, you'll have to translate the smooth rotation of the wheel into the pulsing movement of the shaft -- whose velocity changes as the sine of the rotational angle of the wheel. My mind isn't up to the mathematics on a Saturday morning, but I would be inclined to model the problem in a set of integral steps -- a loop -- in which you calculate the position and rotation of the camshaft with every 10 or 20 degree rotation of the wheel and then apply it new values of PRIM_POS_LOCAL and PRIM_ROT_LOCAL with llSetLinkPrimitiveParamsFast. Edit: What Prof said ^^ Edited November 30, 2019 by Rolig Loon 1 Link to comment Share on other sites More sharing options...
KT Kingsley Posted November 30, 2019 Share Posted November 30, 2019 (edited) Qie mentions llSetTextureAnim. Maybe using this function in frame mode might work here if, say, 16 256 x 256 frames would make an acceptable effect. Edited November 30, 2019 by KT Kingsley 1 Link to comment Share on other sites More sharing options...
WayneScott Posted December 1, 2019 Author Share Posted December 1, 2019 I wrote a long reply, and then my browser crashed ... and I want to get back to the code so I'll go with a shorter version. The device in question is a small, not more than 2 meters long, almost opulent looking object which you would see in a fairly luxurious steampunk setting. So it's a static engine and I don't have to worry about the issues that would be noticeable with something large like a locomotive (eg the surges at startup, etc). The motion of the piston shaft is, at this stage, a little less than 0.5 meters and represents the only linear motion on the entire linkset. I would have loved to include a camshaft and connecting rod (having seen some amazing engines in-world) I decided that the script load represented by that was just too much. And, to be honest, the mental toll of trying to synchronise the motions of piston, conrod, and camshaft would definitely be beyond me. 6 hours ago, Qie Niangao said: llSetKeyframedMotion and llMoveToTarget are useful for moving entire objects but the goal here seems to be moving parts of an object, for which the PRIM_POS_LOCAL parameter of llSetLinkPrimitiveParamsFast() is most suited. To control the speed of motion you'll vary the distance moved per update, the number of timer()-triggered updates per second, or both. [EDIT: I have only a vague sense of the object under development, but you may be satisfied using texture animation to "move" which of several "piston shaft" positions is opaque. That can be a whole lot less laggy and the speed is easily controlled by the rate parameter of llSetTextureAnim().] 6 hours ago, Profaitchikenz Haiku said: In order to have both the reciprocating motion of a piston rod and the proper motion of the coupling and connecting rods you are going to have to learn puppeteering. This is done by using llSetLinkPrimitiveParamsFast to move the components several times a second. 6 hours ago, Rolig Loon said: I would be inclined to model the problem in a set of integral steps -- a loop -- in which you calculate the position and rotation of the camshaft with every 10 or 20 degree rotation of the wheel and then apply it new values of PRIM_POS_LOCAL and PRIM_ROT_LOCAL with llSetLinkPrimitiveParamsFast. Edit: What Prof said ^^ 6 hours ago, KT Kingsley said: Qie mentions llSetTextureAnim. Maybe using this function in frame mode might work here if, say, 16 256 x 256 frames would make an acceptable effect. We definitely have a consensus :) I'll look at the use of llSetLinkPrimitiveParamsFast(). I may have to fall back on a texture animation, although I don't want to as the piston shaft I've made is specifically designed to have 'physical' features to make the motion more apparent, and I'd have to remove them and it would detract from the build. Thanks everyone for your very helpful advice. :D Link to comment Share on other sites More sharing options...
Lucia Nightfire Posted December 1, 2019 Share Posted December 1, 2019 The entire application could be done with rigged mesh and a single animation using bone translation, all in Animesh format and use nearly 0.001ms of script time. Link to comment Share on other sites More sharing options...
Profaitchikenz Haiku Posted December 1, 2019 Share Posted December 1, 2019 7 hours ago, Lucia Nightfire said: a single animation using bone translation This is how the steam engines in the train simulators are done, yes. Looking at the OP's more detailed description, a static power plant is going to be much easier than a railway engine as there is no need to adjust the inworld position. Texture animation to simulate the piston rod is a possibility of the engine is always running at constant speed and there is sufficient framework around to prevent an observer wandering around to view it from a different persective. Thing Grandfather clock, where the pendulum is only visible through the glass in the door at the front. Link to comment Share on other sites More sharing options...
Qie Niangao Posted December 1, 2019 Share Posted December 1, 2019 I mentioned Animesh in the thread cited above, but it was for (what at least seemed to be) a low land-impact decoration, so I dismissed that option as impractical for that application. In contrast the object here is likely to need nearly the minimum Animesh land impact, but the complexity is that the speed of the moving parts needs to be continuously adjustable by the user; maybe this could be adequately reflected in Animesh by a range of different-speed animations, or maybe in a sequence of script-timed static poses (but that's back to timer() events). Anyway, it would be a project. Just for clarity, the animated texture thing I suggested is not a flat image of a piston moving back and forth. Rather it's using texture animation to affect which part of a mesh is opaque, where each part is a full-formed piston (or whatever is moving around). So a single frame of the animation has stripes corresponding to the striped UV map, each stripe corresponding to one of the pistons; the full texture is a sequence of those frames, and played as looped, ping-pong cel animation to look like a single piston moving back and forth. Like llTargetOmega() this uses zero script time (for a set speed), but it does dramatically constrain the complexity of the piston's surface texture, and multiplies the geometric complexity of the moving part by as many "frames" as it takes to look like smooth motion (fine for a simple piston, but a problem for a complex moving shape). Link to comment Share on other sites More sharing options...
OptimoMaximo Posted December 1, 2019 Share Posted December 1, 2019 10 hours ago, Lucia Nightfire said: The entire application could be done with rigged mesh and a single animation using bone translation This can be achieved with rotation only also, assuming both wheel and piston are one single piece and with a nice animation setup of constraints. This limits the build's size adjustability though and for resizing, if needed, a different set of animesh parts would be required 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