Add curve decimate in the graph editor

Added a animation curve decimate operator in the graph editor

Reviewed By: Sybren

Differential Revision: http://developer.blender.org/D4841
This commit is contained in:
Sebastian Parborg 2019-11-21 11:58:35 +01:00
parent 122ba774e0
commit 8bc57e5b91
6 changed files with 126 additions and 0 deletions

View File

@ -285,6 +285,7 @@ class GRAPH_MT_key(Menu):
layout.operator_menu_enum("graph.easing_type", "type", text="Easing Type")
layout.separator()
layout.operator("graph.decimate")
layout.operator("graph.clean").channels = False
layout.operator("graph.clean", text="Clean Channels").channels = True
layout.operator("graph.smooth")

View File

@ -31,12 +31,14 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_string_utils.h"
#include "BLI_math.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_action.h"
#include "BKE_curve.h"
#include "BKE_fcurve.h"
#include "BKE_report.h"
#include "BKE_main.h"
@ -326,6 +328,54 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
/* ---------------- */
/**
* F-Curve 'decimate' function that removes a certain ratio of curve
* points that will affect the curves overall shape the least.
*/
void decimate_fcurve(bAnimListElem *ale, float remove_ratio)
{
FCurve *fcu = (FCurve *)ale->key_data;
/* Check if the curve actually has any points */
if (fcu == NULL || fcu->bezt == NULL || fcu->totvert == 0) {
return;
}
const int target_fcurve_verts = max_ii(2, fcu->totvert - fcu->totvert * remove_ratio);
BezTriple *old_bezts = fcu->bezt;
if (target_fcurve_verts != fcu->totvert) {
/* We don't want to limit the decimation to a certain error margin */
const float error_sq_max = FLT_MAX;
BKE_curve_decimate_bezt_array(fcu->bezt,
fcu->totvert,
12, /* 12 is the resolution of graph editor curves */
false,
SELECT,
BEZT_FLAG_TEMP_TAG,
error_sq_max,
target_fcurve_verts);
}
uint old_totvert = fcu->totvert;
fcu->bezt = NULL;
fcu->totvert = 0;
for (int i = 0; i < old_totvert; i++) {
BezTriple *bezt = (old_bezts + i);
if ((bezt->f2 & BEZT_FLAG_TEMP_TAG) == 0) {
insert_bezt_fcurve(fcu, bezt, 0);
}
}
/* now free the memory used by the old BezTriples */
if (old_bezts) {
MEM_freeN(old_bezts);
}
}
/* ---------------- */
/* temp struct used for smooth_fcurve */
typedef struct tSmooth_Bezt {
float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */

View File

@ -303,6 +303,7 @@ void clean_fcurve(struct bAnimContext *ac,
struct bAnimListElem *ale,
float thresh,
bool cleardefault);
void decimate_fcurve(struct bAnimListElem *ale, float remove_ratio);
void smooth_fcurve(struct FCurve *fcu);
void sample_fcurve(struct FCurve *fcu);

View File

@ -1298,6 +1298,78 @@ void GRAPH_OT_clean(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "channels", false, "Channels", "");
}
/* ******************** Decimate Keyframes Operator ************************* */
static void decimate_graph_keys(bAnimContext *ac, float remove_ratio)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT |
ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through filtered data and clean curves */
for (ale = anim_data.first; ale; ale = ale->next) {
decimate_fcurve(ale, remove_ratio);
ale->update |= ANIM_UPDATE_DEFAULT;
}
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
static int graphkeys_decimate_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
float remove_ratio;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
}
remove_ratio = RNA_float_get(op->ptr, "remove_ratio");
decimate_graph_keys(&ac, remove_ratio);
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
void GRAPH_OT_decimate(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Decimate Keyframes";
ot->idname = "GRAPH_OT_decimate";
ot->description =
"Decimate F-Curves by removing keyframes that influence the curve shape the least";
/* api callbacks */
ot->exec = graphkeys_decimate_exec;
ot->poll = graphop_editable_keyframes_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
ot->prop = RNA_def_float_percentage(ot->srna,
"remove_ratio",
1.0f / 3.0f,
0.0f,
1.0f,
"Remove",
"The percentage of keyframes to remove",
0.0f,
1.0f);
}
/* ******************** Bake F-Curve Operator *********************** */
/* This operator bakes the data of the selected F-Curves to F-Points */

View File

@ -99,6 +99,7 @@ void GRAPH_OT_paste(struct wmOperatorType *ot);
void GRAPH_OT_duplicate(struct wmOperatorType *ot);
void GRAPH_OT_delete(struct wmOperatorType *ot);
void GRAPH_OT_clean(struct wmOperatorType *ot);
void GRAPH_OT_decimate(struct wmOperatorType *ot);
void GRAPH_OT_sample(struct wmOperatorType *ot);
void GRAPH_OT_bake(struct wmOperatorType *ot);
void GRAPH_OT_sound_bake(struct wmOperatorType *ot);

View File

@ -461,6 +461,7 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_sound_bake);
WM_operatortype_append(GRAPH_OT_smooth);
WM_operatortype_append(GRAPH_OT_clean);
WM_operatortype_append(GRAPH_OT_decimate);
WM_operatortype_append(GRAPH_OT_euler_filter);
WM_operatortype_append(GRAPH_OT_delete);
WM_operatortype_append(GRAPH_OT_duplicate);