Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/anim.c')
-rw-r--r--source/blender/blenkernel/intern/anim.c223
1 files changed, 132 insertions, 91 deletions
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index b3c6fb4f3a9..07b8b69bc70 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -35,6 +35,7 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_dlrbTree.h"
#include "BLT_translation.h"
@@ -43,18 +44,29 @@
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
+#include "BKE_anim.h"
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_scene.h"
-#include "BKE_anim.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+#include "DEG_depsgraph_build.h"
+
+#include "GPU_batch.h"
+
// XXX bad level call...
+extern short compare_ak_cfraPtr(void *node, void *data);
+extern void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
+extern void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* --------------------- */
/* forward declarations */
@@ -102,6 +114,10 @@ void animviz_free_motionpath_cache(bMotionPath *mpath)
if (mpath->points)
MEM_freeN(mpath->points);
+ GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
+ GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
+ GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
+
/* reset the relevant parameters */
mpath->points = NULL;
mpath->length = 0;
@@ -125,6 +141,27 @@ void animviz_free_motionpath(bMotionPath *mpath)
/* ------------------- */
+/* Make a copy of motionpath data, so that viewing with copy on write works */
+bMotionPath *animviz_copy_motionpath(const bMotionPath *mpath_src)
+{
+ bMotionPath *mpath_dst;
+
+ if (mpath_src == NULL)
+ return NULL;
+
+ mpath_dst = MEM_dupallocN(mpath_src);
+ mpath_dst->points = MEM_dupallocN(mpath_src->points);
+
+ /* should get recreated on draw... */
+ mpath_dst->points_vbo = NULL;
+ mpath_dst->batch_line = NULL;
+ mpath_dst->batch_points = NULL;
+
+ return mpath_dst;
+}
+
+/* ------------------- */
+
/**
* Setup motion paths for the given data.
* \note Only used when explicitly calculating paths on bones which may/may not be consider already
@@ -207,7 +244,7 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Objec
mpath->color[1] = 0.0;
mpath->color[2] = 0.0;
- mpath->line_thickness = 1;
+ mpath->line_thickness = 2;
mpath->flag |= MOTIONPATH_FLAG_LINES; /* draw lines by default */
/* allocate a cache */
@@ -228,8 +265,16 @@ typedef struct MPathTarget {
bMotionPath *mpath; /* motion path in question */
+ DLRBT_Tree keys; /* temp, to know where the keyframes are */
+
+ /* Original (Source Objects) */
Object *ob; /* source object */
bPoseChannel *pchan; /* source posechannel (if applicable) */
+
+ /* "Evaluated" Copies (these come from the background COW copie
+ * that provide all the coordinates we want to save off)
+ */
+ Object *ob_eval; /* evaluated object */
} MPathTarget;
/* ........ */
@@ -273,88 +318,21 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* ........ */
-/* Note on evaluation optimizations:
- * Optimization's 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,
- * disable the ifdef (i.e. 1 -> 0) and comment out the call to motionpaths_calc_optimise_depsgraph()
- */
-
-/* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */
-static void motionpaths_calc_optimise_depsgraph(Main *bmain, 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;
-
- /* we really don't need to continue anymore once this happens, but this line might really 'break' */
- break;
- }
- }
- }
-
- /* "brew me a list that's sorted a bit faster now depsy" */
- DAG_scene_relations_rebuild(bmain, scene);
-}
-
/* update scene for current frame */
-static void motionpaths_calc_update_scene(Main *bmain, Scene *scene)
+static void motionpaths_calc_update_scene(Main *bmain,
+ struct Depsgraph *depsgraph)
{
-#if 1 // 'production' optimizations always on
- /* rigid body simulation needs complete update to work correctly for now */
- /* RB_TODO investigate if we could avoid updating everything */
- if (BKE_scene_check_rigidbody_active(scene)) {
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
- }
- else { /* otherwise we can optimize by restricting updates */
- Base *base, *last = NULL;
-
- /* only stuff that moves or needs display still */
- DAG_scene_update_flags(bmain, scene, scene->lay, true, false);
-
- /* find the last object with the tag
- * - all those afterwards are assumed to not be relevant for our calculations
- */
- /* optimize 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 */
- BKE_object_handle_update(bmain, bmain->eval_ctx, 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
+ /* 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!
+ *
+ * TODO(segey): Bring back partial updates, which became impossible
+ * with the new depsgraph due to unsorted nature of bases.
+ *
+ * TODO(sergey): Use evaluation context dedicated to motion paths.
*/
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); /* XXX this is the best way we can get anything moving */
-#endif
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
/* ........ */
@@ -372,28 +350,45 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* current frame must be within the range the cache works for
* - is inclusive of the first frame, but not the last otherwise we get buffer overruns
*/
- if ((CFRA < mpath->start_frame) || (CFRA >= mpath->end_frame))
+ if ((CFRA < mpath->start_frame) || (CFRA >= mpath->end_frame)) {
continue;
+ }
/* get the relevant cache vert to write to */
mpv = mpath->points + (CFRA - mpath->start_frame);
- /* pose-channel or object path baking? */
+ Object *ob_eval = mpt->ob_eval;
+
+ /* Lookup evaluated pose channel, here because the depsgraph
+ * evaluation can change them so they are not cached in mpt. */
+ bPoseChannel *pchan_eval = NULL;
if (mpt->pchan) {
+ pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, mpt->pchan->name);
+ }
+
+ /* pose-channel or object path baking? */
+ if (pchan_eval) {
/* heads or tails */
if (mpath->flag & MOTIONPATH_FLAG_BHEAD) {
- copy_v3_v3(mpv->co, mpt->pchan->pose_head);
+ copy_v3_v3(mpv->co, pchan_eval->pose_head);
}
else {
- copy_v3_v3(mpv->co, mpt->pchan->pose_tail);
+ copy_v3_v3(mpv->co, pchan_eval->pose_tail);
}
/* result must be in worldspace */
- mul_m4_v3(mpt->ob->obmat, mpv->co);
+ mul_m4_v3(ob_eval->obmat, mpv->co);
}
else {
/* worldspace object location */
- copy_v3_v3(mpv->co, mpt->ob->obmat[3]);
+ copy_v3_v3(mpv->co, ob_eval->obmat[3]);
+ }
+
+ float mframe = (float)(CFRA);
+
+ /* Tag if it's a keyframe */
+ if (BLI_dlrbTree_search_exact(&mpt->keys, compare_ak_cfraPtr, &mframe)) {
+ mpv->flag |= MOTIONPATH_VERT_KEY;
}
}
}
@@ -404,7 +399,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
* - recalc: whether we need to
*/
/* TODO: include reports pointer? */
-void animviz_calc_motionpaths(Main *bmain, Scene *scene, ListBase *targets)
+ void animviz_calc_motionpaths(Depsgraph *depsgraph, Main *bmain, Scene *scene, ListBase *targets)
{
MPathTarget *mpt;
int sfra, efra;
@@ -428,26 +423,64 @@ void animviz_calc_motionpaths(Main *bmain, Scene *scene, ListBase *targets)
}
if (efra <= sfra) return;
- /* optimize the depsgraph for faster updates */
- /* TODO: whether this is used should depend on some setting for the level of optimizations used */
- motionpaths_calc_optimise_depsgraph(bmain, scene, targets);
+
+ /* get copies of objects/bones to get the calculated results from
+ * (for copy-on-write evaluation), so that we actually get some results
+ */
+ // TODO: Create a copy of background depsgraph that only contain these entities, and only evaluates them..
+ for (mpt = targets->first; mpt; mpt = mpt->next) {
+ mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob);
+
+ AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
+
+ /* build list of all keyframes in active action for object or pchan */
+ BLI_dlrbTree_init(&mpt->keys);
+
+ if (adt) {
+ bAnimVizSettings *avs;
+
+ /* get pointer to animviz settings for each target */
+ if (mpt->pchan)
+ avs = &mpt->ob->pose->avs;
+ else
+ avs = &mpt->ob->avs;
+
+ /* it is assumed that keyframes for bones are all grouped in a single group
+ * unless an option is set to always use the whole action
+ */
+ if ((mpt->pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
+ bActionGroup *agrp = BKE_action_group_find_name(adt->action, mpt->pchan->name);
+
+ if (agrp) {
+ agroup_to_keylist(adt, agrp, &mpt->keys, NULL);
+ BLI_dlrbTree_linkedlist_sync(&mpt->keys);
+ }
+ }
+ else {
+ action_to_keylist(adt, adt->action, &mpt->keys, NULL);
+ BLI_dlrbTree_linkedlist_sync(&mpt->keys);
+ }
+ }
+ }
/* calculate path over requested range */
for (CFRA = sfra; CFRA <= efra; CFRA++) {
/* update relevant data for new frame */
- motionpaths_calc_update_scene(bmain, scene);
+ motionpaths_calc_update_scene(bmain, depsgraph);
/* perform baking for targets */
motionpaths_calc_bake_targets(scene, targets);
}
/* reset original environment */
+ // XXX: Soon to be obsolete
CFRA = cfra;
- motionpaths_calc_update_scene(bmain, scene);
+ motionpaths_calc_update_scene(bmain, depsgraph);
/* clear recalc flags from targets */
for (mpt = targets->first; mpt; mpt = mpt->next) {
bAnimVizSettings *avs;
+ bMotionPath *mpath = mpt->mpath;
/* get pointer to animviz settings for each target */
if (mpt->pchan)
@@ -457,6 +490,14 @@ void animviz_calc_motionpaths(Main *bmain, Scene *scene, ListBase *targets)
/* clear the flag requesting recalculation of targets */
avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
+
+ /* Clean temp data */
+ BLI_dlrbTree_free(&mpt->keys);
+
+ /* Free previous batches to force update. */
+ GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
+ GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
+ GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
}
}