Blender  V2.93
anim_motion_paths.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "MEM_guardedalloc.h"
22 
23 #include <stdlib.h>
24 
25 #include "BLI_dlrbTree.h"
26 #include "BLI_listbase.h"
27 #include "BLI_math.h"
28 
29 #include "DNA_anim_types.h"
30 #include "DNA_armature_types.h"
31 #include "DNA_scene_types.h"
32 
33 #include "BKE_action.h"
34 #include "BKE_anim_data.h"
35 #include "BKE_main.h"
36 #include "BKE_scene.h"
37 
38 #include "DEG_depsgraph.h"
39 #include "DEG_depsgraph_build.h"
40 #include "DEG_depsgraph_query.h"
41 
42 #include "GPU_batch.h"
43 #include "GPU_vertex_buffer.h"
44 
45 #include "ED_anim_api.h"
46 #include "ED_keyframes_draw.h"
47 
48 #include "CLG_log.h"
49 
50 static CLG_LogRef LOG = {"ed.anim.motion_paths"};
51 
52 /* Motion path needing to be baked (mpt) */
53 typedef struct MPathTarget {
54  struct MPathTarget *next, *prev;
55 
56  bMotionPath *mpath; /* motion path in question */
57 
58  DLRBT_Tree keys; /* temp, to know where the keyframes are */
59 
60  /* Original (Source Objects) */
61  Object *ob; /* source object */
62  bPoseChannel *pchan; /* source posechannel (if applicable) */
63 
64  /* "Evaluated" Copies (these come from the background COW copy
65  * that provide all the coordinates we want to save off). */
66  Object *ob_eval; /* evaluated object */
68 
69 /* ........ */
70 
71 /* update scene for current frame */
73 {
75 }
76 
78  Scene *scene,
79  ViewLayer *view_layer,
80  ListBase *targets)
81 {
82  /* Allocate dependency graph. */
84 
85  /* Make a flat array of IDs for the DEG API. */
86  const int num_ids = BLI_listbase_count(targets);
87  ID **ids = MEM_malloc_arrayN(sizeof(ID *), num_ids, "animviz IDS");
88  int current_id_index = 0;
89  for (MPathTarget *mpt = targets->first; mpt != NULL; mpt = mpt->next) {
90  ids[current_id_index++] = &mpt->ob->id;
91  }
92 
93  /* Build graph from all requested IDs. */
94  DEG_graph_build_from_ids(depsgraph, ids, num_ids);
95  MEM_freeN(ids);
96 
97  /* Update once so we can access pointers of evaluated animation data. */
99  return depsgraph;
100 }
101 
102 /* get list of motion paths to be baked for the given object
103  * - assumes the given list is ready to be used
104  */
105 /* TODO: it would be nice in future to be able to update objects dependent on these bones too? */
107 {
108  MPathTarget *mpt;
109 
110  /* object itself first */
111  if ((ob->avs.recalc & ANIMVIZ_RECALC_PATHS) && (ob->mpath)) {
112  /* new target for object */
113  mpt = MEM_callocN(sizeof(MPathTarget), "MPathTarget Ob");
114  BLI_addtail(targets, mpt);
115 
116  mpt->mpath = ob->mpath;
117  mpt->ob = ob;
118  }
119 
120  /* bones */
121  if ((ob->pose) && (ob->pose->avs.recalc & ANIMVIZ_RECALC_PATHS)) {
122  bArmature *arm = ob->data;
124 
125  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
126  if ((pchan->bone) && (arm->layer & pchan->bone->layer) && (pchan->mpath)) {
127  /* new target for bone */
128  mpt = MEM_callocN(sizeof(MPathTarget), "MPathTarget PoseBone");
129  BLI_addtail(targets, mpt);
130 
131  mpt->mpath = pchan->mpath;
132  mpt->ob = ob;
133  mpt->pchan = pchan;
134  }
135  }
136  }
137 }
138 
139 /* ........ */
140 
141 /* perform baking for the targets on the current frame */
142 static void motionpaths_calc_bake_targets(ListBase *targets, int cframe)
143 {
144  MPathTarget *mpt;
145 
146  /* for each target, check if it can be baked on the current frame */
147  for (mpt = targets->first; mpt; mpt = mpt->next) {
148  bMotionPath *mpath = mpt->mpath;
149 
150  /* current frame must be within the range the cache works for
151  * - is inclusive of the first frame, but not the last otherwise we get buffer overruns
152  */
153  if ((cframe < mpath->start_frame) || (cframe >= mpath->end_frame)) {
154  continue;
155  }
156 
157  /* get the relevant cache vert to write to */
158  bMotionPathVert *mpv = mpath->points + (cframe - mpath->start_frame);
159 
160  Object *ob_eval = mpt->ob_eval;
161 
162  /* Lookup evaluated pose channel, here because the depsgraph
163  * evaluation can change them so they are not cached in mpt. */
164  bPoseChannel *pchan_eval = NULL;
165  if (mpt->pchan) {
166  pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, mpt->pchan->name);
167  }
168 
169  /* pose-channel or object path baking? */
170  if (pchan_eval) {
171  /* heads or tails */
173  copy_v3_v3(mpv->co, pchan_eval->pose_head);
174  }
175  else {
176  copy_v3_v3(mpv->co, pchan_eval->pose_tail);
177  }
178 
179  /* result must be in worldspace */
180  mul_m4_v3(ob_eval->obmat, mpv->co);
181  }
182  else {
183  /* worldspace object location */
184  copy_v3_v3(mpv->co, ob_eval->obmat[3]);
185  }
186 
187  float mframe = (float)(cframe);
188 
189  /* Tag if it's a keyframe */
190  if (BLI_dlrbTree_search_exact(&mpt->keys, compare_ak_cfraPtr, &mframe)) {
191  mpv->flag |= MOTIONPATH_VERT_KEY;
192  }
193  else {
194  mpv->flag &= ~MOTIONPATH_VERT_KEY;
195  }
196 
197  /* Incremental update on evaluated object if possible, for fast updating
198  * while dragging in transform. */
199  bMotionPath *mpath_eval = NULL;
200  if (mpt->pchan) {
201  mpath_eval = (pchan_eval) ? pchan_eval->mpath : NULL;
202  }
203  else {
204  mpath_eval = ob_eval->mpath;
205  }
206 
207  if (mpath_eval && mpath_eval->length == mpath->length) {
208  bMotionPathVert *mpv_eval = mpath_eval->points + (cframe - mpath_eval->start_frame);
209  *mpv_eval = *mpv;
210 
212  GPU_BATCH_DISCARD_SAFE(mpath_eval->batch_line);
214  }
215  }
216 }
217 
218 /* Get pointer to animviz settings for the given target. */
220 {
221  if (mpt->pchan != NULL) {
222  return &mpt->ob->pose->avs;
223  }
224  return &mpt->ob->avs;
225 }
226 
227 static void motionpath_get_global_framerange(ListBase *targets, int *r_sfra, int *r_efra)
228 {
229  *r_sfra = INT_MAX;
230  *r_efra = INT_MIN;
231  LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
232  *r_sfra = min_ii(*r_sfra, mpt->mpath->start_frame);
233  *r_efra = max_ii(*r_efra, mpt->mpath->end_frame);
234  }
235 }
236 
237 static int motionpath_get_prev_keyframe(MPathTarget *mpt, DLRBT_Tree *fcu_keys, int current_frame)
238 {
239  if (current_frame <= mpt->mpath->start_frame) {
240  return mpt->mpath->start_frame;
241  }
242 
243  float current_frame_float = current_frame;
244  DLRBT_Node *node = BLI_dlrbTree_search_prev(fcu_keys, compare_ak_cfraPtr, &current_frame_float);
245  if (node == NULL) {
246  return mpt->mpath->start_frame;
247  }
248 
249  ActKeyColumn *key_data = (ActKeyColumn *)node;
250  return key_data->cfra;
251 }
252 
254  DLRBT_Tree *fcu_keys,
255  int current_frame)
256 {
257  int frame = motionpath_get_prev_keyframe(mpt, fcu_keys, current_frame);
258  return motionpath_get_prev_keyframe(mpt, fcu_keys, frame);
259 }
260 
261 static int motionpath_get_next_keyframe(MPathTarget *mpt, DLRBT_Tree *fcu_keys, int current_frame)
262 {
263  if (current_frame >= mpt->mpath->end_frame) {
264  return mpt->mpath->end_frame;
265  }
266 
267  float current_frame_float = current_frame;
268  DLRBT_Node *node = BLI_dlrbTree_search_next(fcu_keys, compare_ak_cfraPtr, &current_frame_float);
269  if (node == NULL) {
270  return mpt->mpath->end_frame;
271  }
272 
273  ActKeyColumn *key_data = (ActKeyColumn *)node;
274  return key_data->cfra;
275 }
276 
278  DLRBT_Tree *fcu_keys,
279  int current_frame)
280 {
281  int frame = motionpath_get_next_keyframe(mpt, fcu_keys, current_frame);
282  return motionpath_get_next_keyframe(mpt, fcu_keys, frame);
283 }
284 
286  AnimData *adt,
287  ListBase *fcurve_list)
288 {
289  if (adt == NULL || fcurve_list == NULL) {
290  return false;
291  }
292  /* NOTE: We might needed to do a full frame range update if there is a specific setup of NLA
293  * or drivers or modifiers on the f-curves. */
294  return true;
295 }
296 
298  AnimData *adt,
299  ListBase *fcurve_list,
300  int current_frame,
301  int *r_sfra,
302  int *r_efra)
303 {
304  *r_sfra = INT_MAX;
305  *r_efra = INT_MIN;
306 
307  /* If the current frame is outside of the configured motion path range we ignore update of this
308  * motion path by using invalid frame range where start frame is above the end frame. */
309  if (current_frame < mpt->mpath->start_frame || current_frame > mpt->mpath->end_frame) {
310  return;
311  }
312 
313  /* Similar to the case when there is only a single keyframe: need to update en entire range to
314  * a constant value. */
315  if (!motionpath_check_can_use_keyframe_range(mpt, adt, fcurve_list)) {
316  *r_sfra = mpt->mpath->start_frame;
317  *r_efra = mpt->mpath->end_frame;
318  return;
319  }
320 
321  /* NOTE: Iterate over individual f-curves, and check their keyframes individually and pick a
322  * widest range from them. This is because it's possible to have more narrow keyframe on a
323  * channel which wasn't edited.
324  * Could be optimized further by storing some flags about which channels has been modified so
325  * we ignore all others (which can potentially make an update range unnecessary wide). */
326  for (FCurve *fcu = fcurve_list->first; fcu != NULL; fcu = fcu->next) {
327  DLRBT_Tree fcu_keys;
328  BLI_dlrbTree_init(&fcu_keys);
329  fcurve_to_keylist(adt, fcu, &fcu_keys, 0);
330 
331  int fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, &fcu_keys, current_frame);
332  int fcu_efra = motionpath_get_next_next_keyframe(mpt, &fcu_keys, current_frame);
333 
334  /* Extend range further, since acceleration compensation propagates even further away. */
335  if (fcu->auto_smoothing != FCURVE_SMOOTH_NONE) {
336  fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, &fcu_keys, fcu_sfra);
337  fcu_efra = motionpath_get_next_next_keyframe(mpt, &fcu_keys, fcu_efra);
338  }
339 
340  if (fcu_sfra <= fcu_efra) {
341  *r_sfra = min_ii(*r_sfra, fcu_sfra);
342  *r_efra = max_ii(*r_efra, fcu_efra);
343  }
344 
345  BLI_dlrbTree_free(&fcu_keys);
346  }
347 }
348 
350 {
351  LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
352  BLI_dlrbTree_free(&mpt->keys);
353  }
354 }
355 
356 /* Perform baking of the given object's and/or its bones' transforms to motion paths
357  * - scene: current scene
358  * - ob: object whose flagged motionpaths should get calculated
359  * - recalc: whether we need to
360  */
361 /* TODO: include reports pointer? */
363  Main *bmain,
364  Scene *scene,
365  ListBase *targets,
366  eAnimvizCalcRange range,
367  bool restore)
368 {
369  /* Sanity check. */
370  if (ELEM(NULL, targets, targets->first)) {
371  return;
372  }
373 
374  const int cfra = CFRA;
375  int sfra = INT_MAX, efra = INT_MIN;
376  switch (range) {
378  motionpath_get_global_framerange(targets, &sfra, &efra);
379  if (sfra > efra) {
380  return;
381  }
382  if (cfra < sfra || cfra > efra) {
383  return;
384  }
385  sfra = efra = cfra;
386  break;
388  /* Nothing to do here, will be handled later when iterating through the targets. */
389  break;
391  motionpath_get_global_framerange(targets, &sfra, &efra);
392  if (sfra > efra) {
393  return;
394  }
395  break;
396  }
397 
398  /* get copies of objects/bones to get the calculated results from
399  * (for copy-on-write evaluation), so that we actually get some results
400  */
401 
402  /* TODO: Create a copy of background depsgraph that only contain these entities,
403  * and only evaluates them.
404  *
405  * For until that is done we force dependency graph to not be active, so we don't lose unkeyed
406  * changes during updating the motion path.
407  * This still doesn't include unkeyed changes to the path itself, but allows to have updates in
408  * an environment when auto-keying and pose paste is used. */
409 
410  const bool is_active_depsgraph = DEG_is_active(depsgraph);
411  if (is_active_depsgraph) {
413  }
414 
415  LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
416  mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob);
417 
418  AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
419 
420  /* build list of all keyframes in active action for object or pchan */
421  BLI_dlrbTree_init(&mpt->keys);
422 
423  ListBase *fcurve_list = NULL;
424  if (adt) {
425  /* get pointer to animviz settings for each target */
427 
428  /* it is assumed that keyframes for bones are all grouped in a single group
429  * unless an option is set to always use the whole action
430  */
431  if ((mpt->pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
432  bActionGroup *agrp = BKE_action_group_find_name(adt->action, mpt->pchan->name);
433 
434  if (agrp) {
435  fcurve_list = &agrp->channels;
436  agroup_to_keylist(adt, agrp, &mpt->keys, 0);
437  }
438  }
439  else {
440  fcurve_list = &adt->action->curves;
441  action_to_keylist(adt, adt->action, &mpt->keys, 0);
442  }
443  }
444 
445  if (range == ANIMVIZ_CALC_RANGE_CHANGED) {
446  int mpt_sfra, mpt_efra;
447  motionpath_calculate_update_range(mpt, adt, fcurve_list, cfra, &mpt_sfra, &mpt_efra);
448  if (mpt_sfra <= mpt_efra) {
449  sfra = min_ii(sfra, mpt_sfra);
450  efra = max_ii(efra, mpt_efra);
451  }
452  }
453  }
454 
455  if (sfra > efra) {
457  return;
458  }
459 
460  /* calculate path over requested range */
461  CLOG_INFO(&LOG,
462  1,
463  "Calculating MotionPaths between frames %d - %d (%d frames)",
464  sfra,
465  efra,
466  efra - sfra + 1);
467  for (CFRA = sfra; CFRA <= efra; CFRA++) {
468  if (range == ANIMVIZ_CALC_RANGE_CURRENT_FRAME) {
469  /* For current frame, only update tagged. */
471  }
472  else {
473  /* Update relevant data for new frame. */
475  }
476 
477  /* perform baking for targets */
479  }
480 
481  /* reset original environment */
482  /* NOTE: We don't always need to reevaluate the main scene, as the depsgraph
483  * may be a temporary one that works on a subset of the data.
484  * We always have to restore the current frame though. */
485  CFRA = cfra;
486  if (range != ANIMVIZ_CALC_RANGE_CURRENT_FRAME && restore) {
488  }
489 
490  if (is_active_depsgraph) {
492  }
493 
494  /* clear recalc flags from targets */
495  LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
496  bMotionPath *mpath = mpt->mpath;
497 
498  /* get pointer to animviz settings for each target */
500 
501  /* clear the flag requesting recalculation of targets */
502  avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
503 
504  /* Clean temp data */
505  BLI_dlrbTree_free(&mpt->keys);
506 
507  /* Free previous batches to force update. */
511  }
512 }
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
struct bActionGroup * BKE_action_group_find_name(struct bAction *act, const char name[])
Definition: action.c:579
struct AnimData * BKE_animdata_from_id(struct ID *id)
Definition: anim_data.c:96
void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.c:2713
void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph)
Definition: scene.c:2794
void BLI_dlrbTree_init(DLRBT_Tree *tree)
Definition: DLRB_tree.c:40
DLRBT_Node * BLI_dlrbTree_search_exact(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data)
Definition: DLRB_tree.c:177
void BLI_dlrbTree_free(DLRBT_Tree *tree)
Definition: DLRB_tree.c:66
DLRBT_Node * BLI_dlrbTree_search_next(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data)
Definition: DLRB_tree.c:256
DLRBT_Node * BLI_dlrbTree_search_prev(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, void *search_data)
Definition: DLRB_tree.c:225
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
#define ELEM(...)
#define CLOG_INFO(clg_ref, level,...)
Definition: CLG_log.h:201
Depsgraph * DEG_graph_new(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, eEvaluationMode mode)
Definition: depsgraph.cc:281
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:331
void DEG_make_active(struct Depsgraph *depsgraph)
Definition: depsgraph.cc:344
@ DAG_EVAL_VIEWPORT
Definition: DEG_depsgraph.h:61
void DEG_make_inactive(struct Depsgraph *depsgraph)
Definition: depsgraph.cc:351
void DEG_graph_build_from_ids(struct Depsgraph *graph, struct ID **ids, const int num_ids)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ MOTIONPATH_VERT_KEY
@ MOTIONPATH_VIEW_KFACT
@ ANIMVIZ_RECALC_PATHS
@ MOTIONPATH_FLAG_BHEAD
@ FCURVE_SMOOTH_NONE
#define CFRA
eAnimvizCalcRange
Definition: ED_anim_api.h:873
@ ANIMVIZ_CALC_RANGE_FULL
Definition: ED_anim_api.h:881
@ ANIMVIZ_CALC_RANGE_CURRENT_FRAME
Definition: ED_anim_api.h:875
@ ANIMVIZ_CALC_RANGE_CHANGED
Definition: ED_anim_api.h:878
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition: GPU_batch.h:199
#define GPU_VERTBUF_DISCARD_SAFE(verts)
Read Guarded memory(de)allocation.
static void motionpaths_calc_bake_targets(ListBase *targets, int cframe)
static void motionpath_get_global_framerange(ListBase *targets, int *r_sfra, int *r_efra)
void animviz_calc_motionpaths(Depsgraph *depsgraph, Main *bmain, Scene *scene, ListBase *targets, eAnimvizCalcRange range, bool restore)
void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
static int motionpath_get_prev_prev_keyframe(MPathTarget *mpt, DLRBT_Tree *fcu_keys, int current_frame)
static int motionpath_get_prev_keyframe(MPathTarget *mpt, DLRBT_Tree *fcu_keys, int current_frame)
Depsgraph * animviz_depsgraph_build(Main *bmain, Scene *scene, ViewLayer *view_layer, ListBase *targets)
static bool motionpath_check_can_use_keyframe_range(MPathTarget *UNUSED(mpt), AnimData *adt, ListBase *fcurve_list)
static void motionpath_calculate_update_range(MPathTarget *mpt, AnimData *adt, ListBase *fcurve_list, int current_frame, int *r_sfra, int *r_efra)
static void motionpaths_calc_update_scene(struct Depsgraph *depsgraph)
static CLG_LogRef LOG
struct MPathTarget MPathTarget
static int motionpath_get_next_next_keyframe(MPathTarget *mpt, DLRBT_Tree *fcu_keys, int current_frame)
static void motionpath_free_free_tree_data(ListBase *targets)
static int motionpath_get_next_keyframe(MPathTarget *mpt, DLRBT_Tree *fcu_keys, int current_frame)
static bAnimVizSettings * animviz_target_settings_get(MPathTarget *mpt)
OperationNode * node
Scene scene
const Depsgraph * depsgraph
void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, int saction_flag)
short compare_ak_cfraPtr(void *node, void *data)
void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, int saction_flag)
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, int saction_flag)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
bAction * action
Definition: DNA_ID.h:273
void * first
Definition: DNA_listBase.h:47
DLRBT_Tree keys
bPoseChannel * pchan
struct MPathTarget * next
bMotionPath * mpath
Object * ob_eval
struct MPathTarget * prev
Definition: BKE_main.h:116
struct bPose * pose
bMotionPath * mpath
float obmat[4][4]
void * data
bAnimVizSettings avs
ListBase curves
unsigned int layer
struct GPUVertBuf * points_vbo
bMotionPathVert * points
struct GPUBatch * batch_points
struct GPUBatch * batch_line
struct Bone * bone
bMotionPath * mpath
float pose_head[3]
float pose_tail[3]
struct bPoseChannel * next
ListBase chanbase
bAnimVizSettings avs