diff options
author | Joshua Leung <aligorith@gmail.com> | 2010-05-21 16:17:34 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2010-05-21 16:17:34 +0400 |
commit | 391c5fba71a2bbb68598c168dcb6e0651924a001 (patch) | |
tree | 54865b5db324082c08363ea3d6cc77b414f57ccc | |
parent | d5316387a4177bc850153de2c4f93375d2cc3b80 (diff) |
Motion Paths: Experimental optimisations from joeedh for speeding up the calculation process
This works by tricking the depsgraph into giving us a smaller list of objects to evaluate, with all the necessary objects + their dependencies at the start of the list.
On any complicated setup where non-object parameters need to be referred to (i.e. by drivers) to affect an object's transform, these optimisations will fail and the old (slower) method is still the best way (modify the ifdef and comment out the optimise depsgraph call to do so). However, we'll assume that these aren't too common in real productions, so things should be fine with these fixes. If there really is a need for both, then global options to control these things could follow.
-rw-r--r-- | source/blender/blenkernel/intern/anim.c | 92 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 5 |
3 files changed, 88 insertions, 11 deletions
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index e2ee4c27c31..9ef52c24e8b 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -252,6 +252,82 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets) /* ........ */ +/* Note on evaluation optimisations: + * Optimisations currently used here play tricks with the depsgraph in order to try and + * evaluate as few objects as strictly necessary to get nicer performance under standard + * production conditions. For those people who really need the accurate version, + */ + +/* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */ +static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) +{ + Base *base, *baseNext; + MPathTarget *mpt; + + /* make sure our temp-tag isn't already in use */ + for (base= scene->base.first; base; base= base->next) + base->object->flag &= ~BA_TEMP_TAG; + + /* for each target, dump its object to the start of the list if it wasn't moved already */ + for (mpt= targets->first; mpt; mpt= mpt->next) { + for (base=scene->base.first; base; base=baseNext) { + baseNext = base->next; + + if ((base->object == mpt->ob) && !(mpt->ob->flag & BA_TEMP_TAG)) { + BLI_remlink(&scene->base, base); + BLI_addhead(&scene->base, base); + + mpt->ob->flag |= BA_TEMP_TAG; + break; // we really don't need to continue anymore once this happens, but this line might really 'break' + } + } + } + + /* "brew me a list that's sorted a bit faster now depsy" */ + DAG_scene_sort(scene); +} + +/* update scene for current frame */ +static void motionpaths_calc_update_scene(Scene *scene) +{ +#if 1 // 'production' optimisations always on + Base *base, *last=NULL; + + /* only stuff that moves or needs display still */ + DAG_scene_update_flags(scene, scene->lay); + + /* find the last object with the tag + * - all those afterwards are assumed to not be relevant for our calculations + */ + // optimise further by moving out... + for (base=scene->base.first; base; base=base->next) { + if (base->object->flag & BA_TEMP_TAG) + last = base; + } + + /* perform updates for tagged objects */ + // XXX: this will break if rigs depend on scene or other data that + // is animated but not attached to/updatable from objects + for (base=scene->base.first; base; base=base->next) { + /* update this object */ + object_handle_update(scene, base->object); + + /* if this is the last one we need to update, let's stop to save some time */ + if (base == last) + break; + } +#else // original, 'always correct' version + /* do all updates + * - if this is too slow, resort to using a more efficient way + * that doesn't force complete update, but for now, this is the + * most accurate way! + */ + scene_update_for_newframe(scene, scene->lay); // XXX this is the best way we can get anything moving +#endif +} + +/* ........ */ + /* perform baking for the targets on the current frame */ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) { @@ -313,7 +389,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) // TODO: this method could be improved... // 1) max range for standard baking - // 2) minimum range for recalc baking (i.e. between keyfames, but how?) + // 2) minimum range for recalc baking (i.e. between keyframes, but how?) for (mpt= targets->first; mpt; mpt= mpt->next) { /* try to increase area to do (only as much as needed) */ sfra= MIN2(sfra, mpt->mpath->start_frame); @@ -321,14 +397,14 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) } if (efra <= sfra) return; + /* optimise the depsgraph for faster updates */ + // TODO: whether this is used should depend on some setting for the level of optimisations used + motionpaths_calc_optimise_depsgraph(scene, targets); + /* calculate path over requested range */ for (CFRA=sfra; CFRA<=efra; CFRA++) { - /* do all updates - * - if this is too slow, resort to using a more efficient way - * that doesn't force complete update, but for now, this is the - * most accurate way! - */ - scene_update_for_newframe(scene, scene->lay); // XXX this is the best way we can get anything moving + /* update relevant data for new frame */ + motionpaths_calc_update_scene(scene); /* perform baking for targets */ motionpaths_calc_bake_targets(scene, targets); @@ -336,7 +412,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) /* reset original environment */ CFRA= cfra; - scene_update_for_newframe(scene, scene->lay); // XXX this is the best way we can get anything moving + motionpaths_calc_update_scene(scene); /* clear recalc flags from targets */ for (mpt= targets->first; mpt; mpt= mpt->next) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9e20d3cfec3..499631ff755 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4499,7 +4499,7 @@ static void clear_trans_object_base_flags(TransInfo *t) if(base->flag & BA_WAS_SEL) base->flag |= SELECT; - base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO|BA_TRANSFORM_CHILD|BA_TRANSFORM_PARENT); + base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_TEMP_TAG|BA_TRANSFORM_CHILD|BA_TRANSFORM_PARENT); } } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index f50909e641b..9649b8351a6 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -412,14 +412,15 @@ extern Object workob; #define BA_HAS_RECALC_OB 4 #define BA_HAS_RECALC_DATA 8 - // XXX DEPRECEATED SETTING... -#define BA_DO_IPO 32 + /* NOTE: this was used as a proper setting in past, so nullify before using */ +#define BA_TEMP_TAG 32 #define BA_FROMSET 128 #define BA_TRANSFORM_CHILD 256 /* child of a transformed object */ #define BA_TRANSFORM_PARENT 8192 /* parent of a transformed object */ + /* an initial attempt as making selection more specific! */ #define BA_DESELECT 0 #define BA_SELECT 1 |