diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-03-16 04:12:37 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-03-16 04:12:37 +0300 |
commit | 8522b08e05c31f9fc4b5fee25c64b884593dc180 (patch) | |
tree | 0dd3b66d607ca3e3355d3a9f7311d5088ad28ce3 /source/blender | |
parent | 9ad4cd89c2cdee8d8086f7da9d9b35fdec12366a (diff) |
F-Curve Modifiers: Generator Modifier Code
* Rewrote the Generator modifier to be more efficient and support more options
* A few UI tweaks for this, but the UI for this is still not yet functional though.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 130 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/ipo.c | 50 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_buttons.c | 57 | ||||
-rw-r--r-- | source/blender/editors/space_graph/space_graph.c | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_anim_types.h | 43 |
7 files changed, 210 insertions, 82 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index e73a2e158ad..3b60be396e7 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -6,6 +6,7 @@ #include <math.h> #include <stdio.h> #include <string.h> +#include <float.h> #ifdef HAVE_CONFIG_H #include <config.h> @@ -1119,13 +1120,24 @@ static FModifierTypeInfo FMI_MODNAME = { /* Generator F-Curve Modifier --------------------------- */ +/* Generators available: + * 1) simple polynomial generator: + * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) + * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) + * 2) simple builin 'functions': + * of the form (y = C[0] * fn( C[1]*x + C[2] ) + C[3]) + * where fn() can be any one of: + * sin, cos, tan, ln, sqrt + * 3) expression... + */ + static void fcm_generator_free (FModifier *fcm) { FMod_Generator *data= (FMod_Generator *)fcm->data; /* free polynomial coefficients array */ - if (data->poly_coefficients) - MEM_freeN(data->poly_coefficients); + if (data->coefficients) + MEM_freeN(data->coefficients); } static void fcm_generator_copy (FModifier *fcm, FModifier *src) @@ -1133,9 +1145,9 @@ static void fcm_generator_copy (FModifier *fcm, FModifier *src) FMod_Generator *gen= (FMod_Generator *)fcm->data; FMod_Generator *ogen= (FMod_Generator *)src->data; - /* copy polynomial coefficients array? */ - if (ogen->poly_coefficients) - gen->poly_coefficients= MEM_dupallocN(ogen->poly_coefficients); + /* copy coefficients array? */ + if (ogen->coefficients) + gen->coefficients= MEM_dupallocN(ogen->coefficients); } static void fcm_generator_new_data (void *mdata) @@ -1145,7 +1157,8 @@ static void fcm_generator_new_data (void *mdata) /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */ data->poly_order= 1; - cp= data->poly_coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs"); + data->arraysize= 2; + cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs"); cp[0] = 0; // y-offset cp[1] = 1; // gradient } @@ -1155,26 +1168,113 @@ static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, { FMod_Generator *data= (FMod_Generator *)fcm->data; - /* behaviour depends on mode (NOTE: we don't need to do anything...) */ + /* behaviour depends on mode + * NOTE: the data in its default state is fine too + */ switch (data->mode) { - // TODO: implement factorised polynomial too - case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ + case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ { /* we overwrite cvalue with the sum of the polynomial */ - float value= 0.0f, *cp = NULL; + float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers"); + float value= 0.0f; unsigned int i; + /* for each x^n, precalculate value based on previous one first... this should be + * faster that calling pow() for each entry + */ + for (i=0; i < data->arraysize; i++) { + /* first entry is x^0 = 1, otherwise, calculate based on previous */ + if (i) + powers[i]= powers[i-1] * evaltime; + else + powers[0]= 1; + } + /* for each coefficient, add to value, which we'll write to *cvalue in one go */ - // TODO: could this be more efficient (i.e. without need to recalc pow() everytime) - cp= data->poly_coefficients; - for (i=0; (i <= data->poly_order) && (cp); i++, cp++) - value += (*cp) * (float)pow(evaltime, i); + for (i=0; i < data->arraysize; i++) + value += data->coefficients[i] * powers[i]; - /* only if something changed */ + /* only if something changed, write *cvalue in one go */ + if (data->poly_order) + *cvalue= value; + + /* cleanup */ + if (powers) + MEM_freeN(powers); + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ + { + float value= 1.0f, *cp=NULL; + unsigned int i; + + /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */ + for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) + value *= (cp[0]*evaltime + cp[1]); + + /* only if something changed, write *cvalue in one go */ if (data->poly_order) *cvalue= value; } break; + + case FCM_GENERATOR_FUNCTION: /* builtin function */ + { + double arg= data->coefficients[1]*evaltime + data->coefficients[2]; + double (*fn)(double v) = NULL; + + /* get function pointer to the func to use: + * WARNING: must perform special argument validation hereto guard against crashes + */ + switch (data->func_type) + { + /* simple ones */ + case FCM_GENERATOR_FN_SIN: /* sine wave */ + fn= sin; + break; + case FCM_GENERATOR_FN_COS: /* cosine wave */ + fn= cos; + break; + + /* validation required */ + 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 */ + else + fn= tan; + } + break; + case FCM_GENERATOR_FN_LN: /* natural log */ + { + /* check that value is greater than 1? */ + if (arg > 1.0f) + fn= log; + else + *cvalue= 0.0f; /* no value possible here */ + } + break; + case FCM_GENERATOR_FN_SQRT: /* square root */ + { + /* no negative numbers */ + if (arg > 0.0f) + fn= sqrt; + else + *cvalue= 0.0f; /* no vlaue possible here */ + } + break; + + default: + printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type); + } + + /* execute function callback to set value if appropriate */ + if (fn) + *cvalue= data->coefficients[0]*fn(arg) + data->coefficients[3]; + } + break; #ifndef DISABLE_PYTHON case FCM_GENERATOR_EXPRESSION: /* py-expression */ diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index dbb720fb0bc..b9417ccb467 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1730,53 +1730,5 @@ void do_versions_ipos_to_animato(Main *main) /* free unused drivers from actions + ipos */ free_fcurves(&drivers); - printf("INFO: animato convert done \n"); // xxx debug + printf("INFO: Animato convert done \n"); // xxx debug } - - - -#if 0 // XXX old animation system - -/* ***************************** IPO - DataAPI ********************************* */ - -// !!!!!!!!!!!!!!!!!!!!!!!!!!!! FIXME - BAD CRUFT WARNING !!!!!!!!!!!!!!!!!!!!!!! - -/* These functions here should be replaced eventually by the Data API, as this is - * inflexible duplication... - */ - -/* --------------------- Get Pointer API ----------------------------- */ - - -/* GS reads the memory pointed at in a specific ordering. There are, - * however two definitions for it. I have jotted them down here, both, - * but I think the first one is actually used. The thing is that - * big-endian systems might read this the wrong way round. OTOH, we - * constructed the IDs that are read out with this macro explicitly as - * well. I expect we'll sort it out soon... */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - -/* from misc_util: flip the bytes from x */ -/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ - - -/* general function to get pointer to source/destination data */ -void *get_ipo_poin (ID *id, IpoCurve *icu, int *type) -{ - void *poin= NULL; - MTex *mtex= NULL; - - /* most channels will have float data, but those with other types will override this */ - *type= IPO_FLOAT; - - /* data is divided into 'blocktypes' based on ID-codes */ - // all adr codes put into converters! - - /* return pointer */ - return poin; -} - - -#endif // XXX old animation system diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e7d5fba23c8..c2fd08bd20f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1725,7 +1725,7 @@ static void direct_link_fcurves(FileData *fd, ListBase *list) { FMod_Generator *data= (FMod_Generator *)fcm->data; - data->poly_coefficients= newdataadr(fd, data->poly_coefficients); + data->coefficients= newdataadr(fd, data->coefficients); } break; case FMODIFIER_TYPE_PYTHON: diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 45742b8f020..2adce78c222 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -805,9 +805,9 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) { FMod_Generator *data= (FMod_Generator *)fcm->data; - /* write polynomial coefficients array */ - if (data->poly_coefficients) - writedata(wd, DATA, sizeof(float)*(data->poly_order+1), data->poly_coefficients); + /* write coefficients array */ + if (data->coefficients) + writedata(wd, DATA, sizeof(float)*(data->arraysize), data->coefficients); } break; case FMODIFIER_TYPE_PYTHON: diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 7c078ad184d..c53b6a720de 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -231,8 +231,47 @@ static void do_graph_region_modifier_buttons(bContext *C, void *arg, int event) } } +/* macro for use here to draw background box and set height */ +#define DRAW_BACKDROP(height, h) \ + { \ + height= h; \ + if (active) uiBlockSetCol(block, TH_BUT_ACTION); \ + uiDefBut(block, ROUNDBOX, B_REDR, "", 10-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \ + if (active) uiBlockSetCol(block, TH_AUTO); \ + } + +/* draw settings for generator modifier */ +static void _draw_modifier__generator(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco, short *height, short width, short active, int rb_col) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */ + { + /* we overwrite cvalue with the sum of the polynomial */ + float value= 0.0f, *cp = NULL; + unsigned int i; + + /* draw backdrop */ + DRAW_BACKDROP((*height), 96); + + /* for each coefficient, add to value, which we'll write to *cvalue in one go */ + cp= data->coefficients; + for (i=0; (i < data->arraysize) && (cp); i++, cp++) { + + } + } + break; + +#ifndef DISABLE_PYTHON + case FCM_GENERATOR_EXPRESSION: /* py-expression */ + // TODO... + break; +#endif /* DISABLE_PYTHON */ + } +} + -/* for now, just print name of modifier */ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fcm, int *yco) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); @@ -269,12 +308,16 @@ static void graph_panel_modifier_draw(uiBlock *block, FCurve *fcu, FModifier *fc /* when modifier is expanded, draw settings */ if (fcm->flag & FMODIFIER_FLAG_EXPANDED) { - height= 97; - - /* draw backdrop */ - if (active) uiBlockSetCol(block, TH_BUT_ACTION); - uiDefBut(block, ROUNDBOX, B_REDR, "", 10-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); - if (active) uiBlockSetCol(block, TH_AUTO); + /* draw settings for individual modifiers */ + switch (fcm->type) { + case FMODIFIER_TYPE_GENERATOR: /* Generator */ + _draw_modifier__generator(block, fcu, fcm, yco, &height, width, active, rb_col); + break; + + default: /* unknown type */ + DRAW_BACKDROP(height, 96); + break; + } } /* adjust height for new to start */ diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 9466a0674d1..10ba28dbcac 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -83,7 +83,7 @@ ARegion *graph_has_buttons_region(ScrArea *sa) BLI_insertlinkafter(&sa->regionbase, ar, arnew); arnew->regiontype= RGN_TYPE_UI; - arnew->alignment= RGN_ALIGN_TOP|RGN_SPLIT_PREV; + arnew->alignment= RGN_ALIGN_BOTTOM|RGN_SPLIT_PREV; arnew->flag = RGN_FLAG_HIDDEN; @@ -569,7 +569,7 @@ void ED_spacetype_ipo(void) /* regions: UI buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); art->regionid = RGN_TYPE_UI; - art->minsizey= 160; + art->minsizey= 200; art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= NULL; // graph_region_listener; art->init= graph_buttons_area_init; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 3ce656faf92..f51300e5f7b 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -69,21 +69,37 @@ typedef struct FMod_Generator { /* generator based on PyExpression */ char expression[256]; /* python expression to use as generator */ - /* simple polynomial generator (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... C[n]) */ - float *poly_coefficients; /* array of the coefficients for the polynomial (poly_order + 1 items long) */ - unsigned int poly_order; /* order of the polynomial (i.e. 1 for linear, 2 for quadratic) */ + /* general generator information */ + float *coefficients; /* coefficients array */ + unsigned int arraysize; /* size of the coefficients array */ + + unsigned short poly_order; /* order of polynomial generated (i.e. 1 for linear, 2 for quadratic) */ + short func_type; /* builtin math function eFMod_Generator_Functions */ + + int pad; /* settings */ short flag; /* settings */ - short mode; /* which 'generator' to use */ + short mode; /* which 'generator' to use eFMod_Generator_Modes */ } FMod_Generator; /* generator modes */ enum { FCM_GENERATOR_POLYNOMIAL = 0, + FCM_GENERATOR_POLYNOMIAL_FACTORISED, + FCM_GENERATOR_FUNCTION, FCM_GENERATOR_EXPRESSION, } eFMod_Generator_Modes; +/* 'function' generator types */ +enum { + FCM_GENERATOR_FN_SIN = 0, + FCM_GENERATOR_FN_COS, + FCM_GENERATOR_FN_TAN, + FCM_GENERATOR_FN_SQRT, + FCM_GENERATOR_FN_LN, +} eFMod_Generator_Functions; + /* envelope modifier - envelope data */ typedef struct FCM_EnvelopeData { @@ -444,7 +460,6 @@ enum { * be generic (using various placeholder template tags that will be * replaced with appropriate information from the context). */ -// TODO: how should templates work exactly? For now, we only implement the specific KeyingSets... typedef struct KS_Path { struct KS_Path *next, *prev; @@ -452,6 +467,10 @@ typedef struct KS_Path { ID *id; /* ID block that keyframes are for */ char group[64]; /* name of the group to add to */ + /* relative paths only */ + int idtype; /* ID-type that path can be used on */ + int templates; /* Templates that will be encountered in the path (as set of bitflags) */ + /* all paths */ char *rna_path; /* dynamically (or statically in the case of predefined sets) path */ int array_index; /* index that path affects */ @@ -476,6 +495,20 @@ enum { KSP_GROUP_KSNAME, } eKSP_Grouping; +/* KS_Path->templates (Template Flags) + * + * Templates in paths are used to substitute information from the + * active context into relavent places in the path strings. This + * enum here defines the flags which define which templates are + * required by a path before it can be used + */ +enum { + KSP_TEMPLATE_OBJECT = (1<<0), /* #obj - selected object */ + KSP_TEMPLATE_PCHAN = (1<<1), /* #pch - selected posechannel */ + KSP_TEMPLATE_CONSTRAINT = (1<<2), /* #con - active only */ + KSP_TEMPLATE_NODE = (1<<3), /* #nod - selected node */ +} eKSP_TemplateTypes; + /* ---------------- */ /* KeyingSet definition (ks) |