Oscillator the script
This is a final proof of concept, with a wobbly bridge. The setup is box_1 to generate the impulses, and the controlled oscillator is the magnet; the magnet has a weight map on the bridge:
The box has zrotate on constant interp, so any change in value generates an impulse to the oscillator. Linear and split interpolations work too, but are more points to key, and I'm lazy. This has just 7 impulses via box_1.
Result is this.... NOTE: anyone with polluted mind will remember, this is a BRIDGE, it even has bricks for people to remember that... it's not, err.. something else... or something other else.. or another something else, so whatever you thought, this is not... this is a wobbly bridge! (I could have demo'd with long hair, but it's late and I'm sleepy):
Hmm... I should have added some trees and flowers, and maybe an oxen cart passing over it to make sure people recogize it as a wobbly bridge, and not put their imagination to work...
I should have added some fish underneath, and a duck or two... but I have no ducks in my arsenal!
Hmmm.... I actually can make this script quite generic. Forget the assumptions about parenting and distances and whatnots. I can just get impulses from deltas in X/Y/Z and rotX/Y/Z from a control prop.
Every prop has a X/Y/Z and a rotX/Y/Z. So I can just ignore everything about parenting and whatnots, and just make the script search for pairs of objects called
Make the targets X/Y/Z and rotX/Y/Z on Oscillator_n to be zero (the user can add whatever offset they want by parenting Oscillator_n to something). So whenever the world X/Y/Z or rot X/Y/Z changes in Control_n, that's an impulse and will get the associated values in Oscillator_n to wobble down to zero. Due to the nature of the differences equation, whatever constant values are in Control_n, the oscillator will go down to zero.
The advantage of this method is that the same object can be impacted by multiple oscillators, say one for slow oscillations, one for fast oscillations.
Also I can allow the user to create its own Control_n by renaming some prop or body part to be Control_n (and then default some values for K and W), or use a script that create Control_n cubes with parameters K and W for finer control.
That way it should be pretty generic. So, 3 scripts (or 3 buttons in a script):
(a) Add Control and Oscillator
(b) Run Oscillators
(c) Clear Oscillators
This is looking nice indeed. :)
Darn it... if Poser allowed a parameter with a string value instead of just numbers, I could allow the user to indicate which parameter on which prop they want to plug in the oscillator. This would make this really generic, as then a parameter like "SwingBack" for the hair could also be controlled by an oscillator.
But, alas, no such luck, so chances are the oscillators are always going to be magnets (unless one wants to go in complicated linking of dependent parameters, like back "SwingBack" to be dependent on the xRotation of some off-screen object. But I find creating these dependencies difficult, as there's no linear dependency that just says value0 at input0, value1 at input1 and that's it; the training thing for dependent parameters is too much hassle for me).
Hmmm.... one thing one could do is this... forget about rotations. Script "Add control" creates a big plane named Controllers, then a child small short box inside named Control_n. It's a child so that the user can move the controls out of the way.
The small short box works as a slide. Slide X left or right, it will cause an impulse on the target. The short box has the K and W parameters, and also Amplitude.
The link to the oscillator is done inside Add control. It presents a dropdown of all actors; once selected an actor, it presents another dropdown with parameters in that actor. Once that's selected, it creates a parameter "Oscillator_n" in the actor, then calls the function
AddValueOperation(kValueOpTypeCodeDELTAADD, pointer to Oscillator_n parameter)
in the target parameter. That makes Oscillator_n to be the master for whatever parameter the user wants. That allows oscillation of pretty much anything, from position to rotations to scales to morphs. Just slide the control and voila the target parameter oscillates adding around whatever value the user has in that parameter.
Actually don't need to create the Oscillator_n in the actor, with polution to its timeline. I understand that a parameter can be a master for parameters in other actors... so Oscillator_n can be a parameter in the Control_n box...I think...
Grrr.. have to redo my math on this.. I took a shortcut and ended up confusing the values; the right equation with no shortcuts is
x''(n) + 2.k.w0.x'(n) + w0^2.x(n) = 0
x"(n) = (x'(n)-x'(n-1))/h = (x(n)-2x(n-1)+x(n-2))/h^2
x'(n) = (x(n)-x(n-1))/h
h = 1/frame rate
[x(n)-2x(n-1)+x(n-2)]/h^2 + 2.k.w0[x(n)-x(n-1]/h + w0^2.x(n) = 0
[x(n)-2x(n-1)+x(n-2)] + 2.k.w0.h.[x(n)-x(n-1]/h + h^2.w0^2.x(n) = 0
[x(n+1)-2x(n)+x(n-1)] + 2.k.w0.h.[x(n+1)-x(n)] + h^2.w0^2.x(n+1) = 0
(1+2.k.w0.h+h^2.w0^2)x(n+1) = (2+2.k.w0.h)x(n) + (-1)x(n-1)
x(n+1) = (A.x(n)-B.x(n-1))/C
A = 2+2.k.w0.h
B = 1
C = 1+2.k.w0.h+2.wo^2)
Oh well... good old Euler method diverges for that guy... Trying again before change to say Runge-Kutta.
x' = u
u' = - 2kwu - w2x
x(n+1) = x(n) + h.u(n)
u(n+1) = u(n) - h.( 2.k.w.u(n) + w2.x(n))
Actually I think that's good enough for a toy. Nobody is trying to send a man to space with this. That second form is better behaved, although it can diverge too. The input is an impulse in the handler on frame 1 with change in X of 0.07. As Poser coordinates are tiny, I added a "Force" parameter that multiplies that input, so I set it to 10 for x10, making the input 0.7.
At 12 fps, a value of w = 20 yields oscillations with a period of about 3.5 frames; that's extremely tight for numerical methods, as a sinusoid in 3.5 frames is pretty much a seesaw, but it behaves itself. With K=0.9 it yields some 10 oscillations or so, so that's good enough.
At w=8 it yields a nice sinusoid with period of about 8 frames; with longer period the curve is much better behaved. But one gets to adjust the K for the desired period, as the thing diverges easily, thanks to old Euler method from 1700s.
So I'm leaving this as is. If I have time in the future I'll modify that to use Runge-Kutta, but I haven't looked at that in 30 years or so, so I'm not extremely inspired to do that now.
Hmm... I'm going to add a special case for very fast cycles, which diverge the equation. I'm going to add an exception for w=-1. That will just make
x(n+1) = -K*x(n)
That way one can make very fast dampened triangular oscillations with period = 2. That's pretty useful at 12 fps. Could even think of a case with period = 4...how to write that.. hmm...
x(n+2) = -K*x(n)
as a difference equation.. hmm...
x(n+1) = Ax(n) + Bu(n)
u(n+1) = Cx(n) + Du(n)
x(n+2) = Ax(n+1)+Bu(n+1) = Ax(n+1)+BCx(n)+BDu(n) = -Kx(n)
A = 0, D = 0, BC = -K
x(n+1) = u(n)
u(n+1) = -Kx(n)
hmm... wonder if that will work...
Demo of Oscillator v0.01:
In this Demo Andy doesn't have a single keyframe. Poinger The Oscillator script created 2 handlers (pink and green boxes) that are linked to Andy's head side-to-side (pink one), and Andy's forearm side-to-side (green one).
Whenever the handlers move in either X or Y direction that generates a dampened impulse that adds to whatever values Andy has in in these parameters, so one can still pose Andy as before with no interference.
The pink handler is set with Force = 200, K = 0.9, W = -1 (that's a forced triangular wave oscillator with period = 2; try W=-2 too). The green handler is set with Force = 300, K=0.6, W=12 (that's a sinusoidal with period of about 6 frames.
W is frequency; higher W means faster oscillations; don't set it too high or you'll break the simulator (can't oscillate at more fps than the frame rate). K is dampening; K=1.0 or >1.0 means critical dampened (it doesn't oscillate, it just comes back to the original position with an impule), K = 0.8 to 0.99 means lotsa dampening; K = 0.2 to 0.5 means very little dampening; K = 0.0 to 0.2 will tend to break the simulator.
If you try to simulate and the thing flies away, it means you've set either a too large W or too small K. If the simulation gives nothing, the force may be too small for you to see the effect, trying increasing the force. Trial and error will get the initial adjustments to whatever parameter this is controlling.
This controls ANY parameter in any figure or actor. It can be position, rotation, morph, lighting, etc...
Oh, the script has 3 buttons:
(a) Create Oscillator to create a new handler and link it a parameter
(b) Oscillate! to calculate the oscillations
(c) Clear Oscillations to remove all that jabberwocking to allow the user to pose again without all these moving parts.
The ControlPanel prop can be placed anywhere. It has no effect, and is the parent of the boxy handlers. Only movements on the boxy handlers have any effect.
Download from here: