102 lines
2.7 KiB
C
102 lines
2.7 KiB
C
|
typedef struct
|
||
|
{
|
||
|
// variables
|
||
|
double ripple_frequency,
|
||
|
ripple_velocity,
|
||
|
ripple_amplitude,
|
||
|
ripple_centerx,
|
||
|
ripple_centery,
|
||
|
ripple_phase,
|
||
|
ripple_scale;
|
||
|
|
||
|
// private stuff
|
||
|
double f, a, p, s, is,
|
||
|
vxp, pxa, pixa;
|
||
|
} Variables;
|
||
|
|
||
|
#define _USE_MATH_DEFINES
|
||
|
#include "apoplugin.h"
|
||
|
|
||
|
APO_PLUGIN("ripple");
|
||
|
APO_VARIABLES(
|
||
|
// wave function frequency
|
||
|
VAR_REAL(ripple_frequency, 2.0),
|
||
|
|
||
|
// wave velocity
|
||
|
VAR_REAL(ripple_velocity, 1.0),
|
||
|
|
||
|
// wave amplitude
|
||
|
VAR_REAL(ripple_amplitude, 0.5),
|
||
|
|
||
|
// origin of the ripple (x,y)
|
||
|
VAR_REAL(ripple_centerx, 0.0),
|
||
|
VAR_REAL(ripple_centery, 0.0),
|
||
|
|
||
|
// wave phase / interpolation coefficient
|
||
|
VAR_REAL(ripple_phase, 0.0),
|
||
|
|
||
|
// ripple scale
|
||
|
VAR_REAL(ripple_scale, 1.0)
|
||
|
);
|
||
|
|
||
|
int PluginVarPrepare(Variation* vp)
|
||
|
{
|
||
|
// some variables are settled in another range for edit comfort
|
||
|
// - transform them
|
||
|
VAR(f) = VAR(ripple_frequency) * 5;
|
||
|
VAR(a) = VAR(ripple_amplitude) * 0.01;
|
||
|
VAR(p) = VAR(ripple_phase) * M_2PI - M_PI;
|
||
|
|
||
|
// scale must not be zero
|
||
|
VAR(s) = VAR(ripple_scale) == 0 ? EPS : VAR(ripple_scale);
|
||
|
|
||
|
// we will need the inverse scale
|
||
|
VAR(is) = 1 / VAR(s);
|
||
|
|
||
|
// pre-multiply velocity+phase, phase+amplitude and (PI-phase)+amplitude
|
||
|
VAR(vxp) = VAR(ripple_velocity) * VAR(p);
|
||
|
VAR(pxa) = VAR(p) * VAR(a);
|
||
|
VAR(pixa) = (M_PI - VAR(p)) * VAR(a);
|
||
|
|
||
|
// done
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
inline double lerp(double a, double b, double p) { return a + (b - a) * p; }
|
||
|
|
||
|
int PluginVarCalc(Variation* vp)
|
||
|
{
|
||
|
//align input x, y to given center and multiply with scale
|
||
|
double x = (FTx * VAR(s)) - VAR(ripple_centerx),
|
||
|
y = (FTy * VAR(s)) + VAR(ripple_centery);
|
||
|
|
||
|
// calculate distance from center but constrain it to EPS
|
||
|
double d = MAX(EPS, sqrt(sqr(x) * sqr(y)));
|
||
|
|
||
|
// normalize (x,y)
|
||
|
double nx = x / d,
|
||
|
ny = y / d;
|
||
|
|
||
|
// calculate cosine wave with given frequency, velocity
|
||
|
// and phase based on the distance to center
|
||
|
double wave = cos(VAR(f) * d - VAR(vxp));
|
||
|
|
||
|
// calculate the wave offsets
|
||
|
double d1 = wave * VAR(pxa) + d,
|
||
|
d2 = wave * VAR(pixa) + d;
|
||
|
|
||
|
// we got two offsets, so we also got two new positions (u,v)
|
||
|
double u1 = (VAR(ripple_centerx) + nx * d1),
|
||
|
v1 = (-VAR(ripple_centery) + ny * d1);
|
||
|
double u2 = (VAR(ripple_centerx) + nx * d2),
|
||
|
v2 = (-VAR(ripple_centery) + ny * d2);
|
||
|
|
||
|
// interpolate the two positions by the given phase and
|
||
|
// invert the multiplication with scale from before
|
||
|
FPx = VVAR * (lerp(u1, u2, VAR(p))) * VAR(is);
|
||
|
FPy = VVAR * (lerp(v1, v2, VAR(p))) * VAR(is);
|
||
|
|
||
|
// done
|
||
|
return TRUE;
|
||
|
}
|