F-Curve Modifiers: Experimental 'Additive' option for Generator Modifiers

This setting means that instead of blindly replacing the existing values, the generator modifier will instead apply its effects on top of any existing modifiers (and/or curve data). 
Thus, it is now possible to apply effects such sin/cos-based oscillations on top of keyframed motion.
This commit is contained in:
2009-03-26 11:12:39 +00:00
parent d93fd9ffc1
commit c7d82ec96e
3 changed files with 53 additions and 19 deletions

View File

@@ -1277,8 +1277,12 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
value += data->coefficients[i] * powers[i];
/* only if something changed, write *cvalue in one go */
if (data->poly_order)
*cvalue= value;
if (data->poly_order) {
if (data->flag & FCM_GENERATOR_ADDITIVE)
*cvalue += value;
else
*cvalue= value;
}
/* cleanup */
if (powers)
@@ -1296,8 +1300,12 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
value *= (cp[0]*evaltime + cp[1]);
/* only if something changed, write *cvalue in one go */
if (data->poly_order)
*cvalue= value;
if (data->poly_order) {
if (data->flag & FCM_GENERATOR_ADDITIVE)
*cvalue += value;
else
*cvalue= value;
}
}
break;
@@ -1323,8 +1331,10 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
case FCM_GENERATOR_FN_TAN: /* tangent wave */
{
/* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */
if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0)
*cvalue= 0.0f; /* no value possible here */
if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) {
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
*cvalue = 0.0f; /* no value possible here */
}
else
fn= tan;
}
@@ -1332,19 +1342,25 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
case FCM_GENERATOR_FN_LN: /* natural log */
{
/* check that value is greater than 1? */
if (arg > 1.0f)
if (arg > 1.0f) {
fn= log;
else
*cvalue= 0.0f; /* no value possible here */
}
else {
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
*cvalue = 0.0f; /* no value possible here */
}
}
break;
case FCM_GENERATOR_FN_SQRT: /* square root */
{
/* no negative numbers */
if (arg > 0.0f)
if (arg > 0.0f) {
fn= sqrt;
else
*cvalue= 0.0f; /* no vlaue possible here */
}
else {
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
*cvalue = 0.0f; /* no value possible here */
}
}
break;
@@ -1353,8 +1369,14 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue,
}
/* execute function callback to set value if appropriate */
if (fn)
*cvalue= data->coefficients[0]*fn(arg) + data->coefficients[3];
if (fn) {
float value= data->coefficients[0]*fn(arg) + data->coefficients[3];
if (data->flag & FCM_GENERATOR_ADDITIVE)
*cvalue += value;
else
*cvalue= value;
}
}
break;
@@ -1446,6 +1468,7 @@ static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, f
}
else {
/* evaltime occurs somewhere between segments */
// TODO: implement binary search for this to make it faster?
for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) {
/* evaltime occurs within the interval defined by these two envelope points */
if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) {

View File

@@ -284,7 +284,7 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm
uiBut *but;
/* set the height */
(*height) = 70;
(*height) = 90;
switch (data->mode) {
case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
(*height) += 20*(data->poly_order+1) + 35;
@@ -302,9 +302,14 @@ static void draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm
/* basic settings (backdrop + mode selector + some padding) */
//DRAW_BACKDROP((*height)); // XXX buggy...
but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm.");
uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
cy -= 35;
uiBlockBeginAlign(block);
but= uiDefButS(block, MENU, B_FMODIFIER_REDRAW, gen_mode, 10,cy,width-30,19, &data->mode, 0, 0, 0, 0, "Selects type of generator algorithm.");
uiButSetFunc(but, validate_fmodifier_cb, fcu, fcm);
cy -= 20;
uiDefButBitS(block, TOG, FCM_GENERATOR_ADDITIVE, B_FMODIFIER_REDRAW, "Additive", 10,cy,width-30,19, &data->flag, 0, 0, 0, 0, "Values generated by this modifier are applied on top of the existing values instead of overwriting them");
cy -= 35;
uiBlockEndAlign(block);
/* now add settings for individual modes */
switch (data->mode) {

View File

@@ -91,6 +91,12 @@ enum {
FCM_GENERATOR_EXPRESSION,
} eFMod_Generator_Modes;
/* generator flags */
enum {
/* generator works in conjunction with other modifiers (i.e. doesn't replace those before it) */
FCM_GENERATOR_ADDITIVE = (1<<0),
} eFMod_Generator_Flags;
/* 'function' generator types */
enum {
FCM_GENERATOR_FN_SIN = 0,
@@ -231,7 +237,7 @@ typedef struct FCurve {
/* motion data */
BezTriple *bezt; /* user-editable keyframes (array) */
FPoint *fpt; /* 'baked/imported' motion samples (array) */
int totvert; /* total number of points which define the curve (i.e. size of arrays in FPoints) */
unsigned int totvert; /* total number of points which define the curve (i.e. size of arrays in FPoints) */
/* value cache + settings */
float curval; /* value stored from last time curve was evaluated */