Blender V4.3
anim_motion_paths.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
11#include <cstdlib>
12
13#include "BLI_dlrbTree.h"
14#include "BLI_listbase.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_matrix.hh"
17
18#include "DNA_anim_types.h"
19#include "DNA_armature_types.h"
20#include "DNA_scene_types.h"
21
22#include "BKE_action.hh"
23#include "BKE_anim_data.hh"
24#include "BKE_main.hh"
25#include "BKE_scene.hh"
26
27#include "DEG_depsgraph.hh"
30
31#include "GPU_batch.hh"
32#include "GPU_vertex_buffer.hh"
33
34#include "ED_anim_api.hh"
36
37#include "ANIM_action_legacy.hh"
39
40#include "CLG_log.h"
41
42static CLG_LogRef LOG = {"ed.anim.motion_paths"};
43
44/* Motion path needing to be baked (mpt) */
47
48 bMotionPath *mpath; /* motion path in question */
49
50 AnimKeylist *keylist; /* temp, to know where the keyframes are */
51
52 /* Original (Source Objects) */
53 Object *ob; /* source object */
54 bPoseChannel *pchan; /* source posechannel (if applicable) */
55
56 /* "Evaluated" Copies (these come from the background evaluated copy
57 * that provide all the coordinates we want to save off). */
58 Object *ob_eval; /* evaluated object */
59};
60
61/* ........ */
62
63/* update scene for current frame */
68
69Depsgraph *animviz_depsgraph_build(Main *bmain,
70 Scene *scene,
71 ViewLayer *view_layer,
72 ListBase *targets)
73{
74 /* Allocate dependency graph. */
75 Depsgraph *depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_VIEWPORT);
76
77 /* Make a flat array of IDs for the DEG API. */
78 const int num_ids = BLI_listbase_count(targets);
79 blender::Array<ID *> ids(num_ids);
80 int current_id_index = 0;
81 for (MPathTarget *mpt = static_cast<MPathTarget *>(targets->first); mpt != nullptr;
82 mpt = mpt->next)
83 {
84 ids[current_id_index++] = &mpt->ob->id;
85 }
86
87 /* Build graph from all requested IDs. */
89
90 /* Update once so we can access pointers of evaluated animation data. */
92 return depsgraph;
93}
94
96{
97 /* TODO: it would be nice in future to be able to update objects dependent on these bones too? */
98
99 MPathTarget *mpt;
100
101 /* object itself first */
102 if ((ob->avs.recalc & ANIMVIZ_RECALC_PATHS) && (ob->mpath)) {
103 /* new target for object */
104 mpt = static_cast<MPathTarget *>(MEM_callocN(sizeof(MPathTarget), "MPathTarget Ob"));
105 BLI_addtail(targets, mpt);
106
107 mpt->mpath = ob->mpath;
108 mpt->ob = ob;
109 }
110
111 /* bones */
112 if ((ob->pose) && (ob->pose->avs.recalc & ANIMVIZ_RECALC_PATHS)) {
113 bArmature *arm = static_cast<bArmature *>(ob->data);
114 LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
115 if ((pchan->bone) && ANIM_bonecoll_is_visible_pchan(arm, pchan) && (pchan->mpath)) {
116 /* new target for bone */
117 mpt = static_cast<MPathTarget *>(MEM_callocN(sizeof(MPathTarget), "MPathTarget PoseBone"));
118 BLI_addtail(targets, mpt);
119
120 mpt->mpath = pchan->mpath;
121 mpt->ob = ob;
122 mpt->pchan = pchan;
123 }
124 }
125 }
126}
127
128/* ........ */
129
130/* perform baking for the targets on the current frame */
132 int cframe,
133 Depsgraph *depsgraph,
134 Object *camera)
135{
136 using namespace blender;
137 /* for each target, check if it can be baked on the current frame */
138 LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
139 bMotionPath *mpath = mpt->mpath;
140
141 /* current frame must be within the range the cache works for
142 * - is inclusive of the first frame, but not the last otherwise we get buffer overruns
143 */
144 if ((cframe < mpath->start_frame) || (cframe >= mpath->end_frame)) {
145 continue;
146 }
147
148 /* get the relevant cache vert to write to */
149 bMotionPathVert *mpv = mpath->points + (cframe - mpath->start_frame);
150
151 Object *ob_eval = mpt->ob_eval;
152
153 /* Lookup evaluated pose channel, here because the depsgraph
154 * evaluation can change them so they are not cached in mpt. */
155 bPoseChannel *pchan_eval = nullptr;
156 if (mpt->pchan) {
157 pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, mpt->pchan->name);
158 }
159
160 /* pose-channel or object path baking? */
161 if (pchan_eval) {
162 /* heads or tails */
163 if (mpath->flag & MOTIONPATH_FLAG_BHEAD) {
164 copy_v3_v3(mpv->co, pchan_eval->pose_head);
165 }
166 else {
167 copy_v3_v3(mpv->co, pchan_eval->pose_tail);
168 }
169
170 /* Result must be in world-space. */
171 mul_m4_v3(ob_eval->object_to_world().ptr(), mpv->co);
172 }
173 else {
174 /* World-space object location. */
175 copy_v3_v3(mpv->co, ob_eval->object_to_world().location());
176 }
177
178 if (mpath->flag & MOTIONPATH_FLAG_BAKE_CAMERA && camera) {
180 /* Convert point to camera space. */
181 float3 co_camera_space = math::transform_point(cam_eval->world_to_object(), float3(mpv->co));
182 copy_v3_v3(mpv->co, co_camera_space);
183 }
184
185 float mframe = float(cframe);
186
187 /* Tag if it's a keyframe */
188 if (ED_keylist_find_exact(mpt->keylist, mframe)) {
190 }
191 else {
193 }
194
195 /* Incremental update on evaluated object if possible, for fast updating
196 * while dragging in transform. */
197 bMotionPath *mpath_eval = nullptr;
198 if (mpt->pchan) {
199 mpath_eval = (pchan_eval) ? pchan_eval->mpath : nullptr;
200 }
201 else {
202 mpath_eval = ob_eval->mpath;
203 }
204
205 if (mpath_eval && mpath_eval->length == mpath->length) {
206 bMotionPathVert *mpv_eval = mpath_eval->points + (cframe - mpath_eval->start_frame);
207 *mpv_eval = *mpv;
208
212 }
213 }
214}
215
216/* Get pointer to animviz settings for the given target. */
218{
219 if (mpt->pchan != nullptr) {
220 return &mpt->ob->pose->avs;
221 }
222 return &mpt->ob->avs;
223}
224
225static void motionpath_get_global_framerange(ListBase *targets, int *r_sfra, int *r_efra)
226{
227 *r_sfra = INT_MAX;
228 *r_efra = INT_MIN;
229 LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
230 *r_sfra = min_ii(*r_sfra, mpt->mpath->start_frame);
231 *r_efra = max_ii(*r_efra, mpt->mpath->end_frame);
232 }
233}
234
235/* TODO(jbakker): Remove complexity, keylists are ordered. */
236static int motionpath_get_prev_keyframe(MPathTarget *mpt, AnimKeylist *keylist, int current_frame)
237{
238 if (current_frame <= mpt->mpath->start_frame) {
239 return mpt->mpath->start_frame;
240 }
241
242 float current_frame_float = current_frame;
243 const ActKeyColumn *ak = ED_keylist_find_prev(keylist, current_frame_float);
244 if (ak == nullptr) {
245 return mpt->mpath->start_frame;
246 }
247
248 return ak->cfra;
249}
250
252 AnimKeylist *keylist,
253 int current_frame)
254{
255 int frame = motionpath_get_prev_keyframe(mpt, keylist, current_frame);
256 return motionpath_get_prev_keyframe(mpt, keylist, frame);
257}
258
259static int motionpath_get_next_keyframe(MPathTarget *mpt, AnimKeylist *keylist, int current_frame)
260{
261 if (current_frame >= mpt->mpath->end_frame) {
262 return mpt->mpath->end_frame;
263 }
264
265 float current_frame_float = current_frame;
266 const ActKeyColumn *ak = ED_keylist_find_next(keylist, current_frame_float);
267 if (ak == nullptr) {
268 return mpt->mpath->end_frame;
269 }
270
271 return ak->cfra;
272}
273
275 AnimKeylist *keylist,
276 int current_frame)
277{
278 int frame = motionpath_get_next_keyframe(mpt, keylist, current_frame);
279 return motionpath_get_next_keyframe(mpt, keylist, frame);
280}
281
283 AnimData *adt,
284 ListBase *fcurve_list)
285{
286 if (adt == nullptr || fcurve_list == nullptr) {
287 return false;
288 }
289 /* NOTE: We might needed to do a full frame range update if there is a specific setup of NLA
290 * or drivers or modifiers on the f-curves. */
291 return true;
292}
293
295 AnimData *adt,
296 ListBase *fcurve_list,
297 int current_frame,
298 int *r_sfra,
299 int *r_efra)
300{
301 *r_sfra = INT_MAX;
302 *r_efra = INT_MIN;
303
304 /* If the current frame is outside of the configured motion path range we ignore update of this
305 * motion path by using invalid frame range where start frame is above the end frame. */
306 if (current_frame < mpt->mpath->start_frame || current_frame > mpt->mpath->end_frame) {
307 return;
308 }
309
310 /* Similar to the case when there is only a single keyframe: need to update en entire range to
311 * a constant value. */
312 if (!motionpath_check_can_use_keyframe_range(mpt, adt, fcurve_list)) {
313 *r_sfra = mpt->mpath->start_frame;
314 *r_efra = mpt->mpath->end_frame;
315 return;
316 }
317
318 /* NOTE: Iterate over individual f-curves, and check their keyframes individually and pick a
319 * widest range from them. This is because it's possible to have more narrow keyframe on a
320 * channel which wasn't edited.
321 * Could be optimized further by storing some flags about which channels has been modified so
322 * we ignore all others (which can potentially make an update range unnecessary wide). */
323 for (FCurve *fcu = static_cast<FCurve *>(fcurve_list->first); fcu != nullptr; fcu = fcu->next) {
324 AnimKeylist *keylist = ED_keylist_create();
325 fcurve_to_keylist(adt, fcu, keylist, 0, {-FLT_MAX, FLT_MAX});
327
328 int fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, keylist, current_frame);
329 int fcu_efra = motionpath_get_next_next_keyframe(mpt, keylist, current_frame);
330
331 /* Extend range further, since acceleration compensation propagates even further away. */
332 if (fcu->auto_smoothing != FCURVE_SMOOTH_NONE) {
333 fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, keylist, fcu_sfra);
334 fcu_efra = motionpath_get_next_next_keyframe(mpt, keylist, fcu_efra);
335 }
336
337 if (fcu_sfra <= fcu_efra) {
338 *r_sfra = min_ii(*r_sfra, fcu_sfra);
339 *r_efra = max_ii(*r_efra, fcu_efra);
340 }
341
342 ED_keylist_free(keylist);
343 }
344}
345
347{
348 LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
349 ED_keylist_free(mpt->keylist);
350 }
351}
352
354{
355 bAnimVizSettings *avs = ob->mode == OB_MODE_POSE ? &ob->pose->avs : &ob->avs;
356
358 /* Don't touch manually-determined ranges. */
359 return;
360 }
361
362 const bool has_action = ob->adt && ob->adt->action;
363 if (avs->path_range == MOTIONPATH_RANGE_SCENE || !has_action ||
365 {
366 /* Default to the scene (preview) range if there is no animation data to
367 * find selected keys in. */
368 avs->path_sf = PSFRA;
369 avs->path_ef = PEFRA;
370 return;
371 }
372
373 AnimKeylist *keylist = ED_keylist_create();
375 fcurve_to_keylist(ob->adt, fcu, keylist, 0, {-FLT_MAX, FLT_MAX});
376 }
377
378 Range2f frame_range;
379 switch (avs->path_range) {
381 if (ED_keylist_selected_keys_frame_range(keylist, &frame_range)) {
382 break;
383 }
384 ATTR_FALLTHROUGH; /* Fall through if there were no selected keys found. */
386 ED_keylist_all_keys_frame_range(keylist, &frame_range);
387 break;
390 BLI_assert_msg(false, "This should not happen, function should have exited earlier.");
391 };
392
393 avs->path_sf = frame_range.min;
394 avs->path_ef = frame_range.max;
395
396 ED_keylist_free(keylist);
397}
398
400 Main *bmain,
401 Scene *scene,
402 ListBase *targets,
403 eAnimvizCalcRange range,
404 bool restore)
405{
406 /* TODO: include reports pointer? */
407
408 /* Sanity check. */
409 if (ELEM(nullptr, targets, targets->first)) {
410 return;
411 }
412
413 const int cfra = scene->r.cfra;
414 int sfra = INT_MAX, efra = INT_MIN;
415 switch (range) {
417 motionpath_get_global_framerange(targets, &sfra, &efra);
418 if (sfra > efra) {
419 return;
420 }
421 if (cfra < sfra || cfra > efra) {
422 return;
423 }
424 sfra = efra = cfra;
425 break;
427 /* Nothing to do here, will be handled later when iterating through the targets. */
428 break;
430 motionpath_get_global_framerange(targets, &sfra, &efra);
431 if (sfra > efra) {
432 return;
433 }
434 break;
435 }
436
437 /* get copies of objects/bones to get the calculated results from
438 * (for copy-on-evaluation), so that we actually get some results
439 */
440
441 /* TODO: Create a copy of background depsgraph that only contain these entities,
442 * and only evaluates them.
443 *
444 * For until that is done we force dependency graph to not be active, so we don't lose unkeyed
445 * changes during updating the motion path.
446 * This still doesn't include unkeyed changes to the path itself, but allows to have updates in
447 * an environment when auto-keying and pose paste is used. */
448
449 const bool is_active_depsgraph = DEG_is_active(depsgraph);
450 if (is_active_depsgraph) {
452 }
453
454 LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
455 mpt->ob_eval = DEG_get_evaluated_object(depsgraph, mpt->ob);
456
457 AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
458
459 /* build list of all keyframes in active action for object or pchan */
460 mpt->keylist = ED_keylist_create();
461
462 ListBase *fcurve_list = nullptr;
463 if (adt) {
464 /* get pointer to animviz settings for each target */
466
467 /* it is assumed that keyframes for bones are all grouped in a single group
468 * unless an option is set to always use the whole action
469 */
470 if ((mpt->pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
471 bActionGroup *agrp = BKE_action_group_find_name(adt->action, mpt->pchan->name);
472
473 if (agrp) {
474 fcurve_list = &agrp->channels;
475 action_group_to_keylist(adt, agrp, mpt->keylist, 0, {-FLT_MAX, FLT_MAX});
476 }
477 }
478 else {
479 fcurve_list = &adt->action->curves;
480 action_to_keylist(adt, adt->action, mpt->keylist, 0, {-FLT_MAX, FLT_MAX});
481 }
482 }
484
485 if (range == ANIMVIZ_CALC_RANGE_CHANGED) {
486 int mpt_sfra, mpt_efra;
487 motionpath_calculate_update_range(mpt, adt, fcurve_list, cfra, &mpt_sfra, &mpt_efra);
488 if (mpt_sfra <= mpt_efra) {
489 sfra = min_ii(sfra, mpt_sfra);
490 efra = max_ii(efra, mpt_efra);
491 }
492 }
493 }
494
495 if (sfra > efra) {
497 return;
498 }
499
500 /* calculate path over requested range */
501 CLOG_INFO(&LOG,
502 1,
503 "Calculating MotionPaths between frames %d - %d (%d frames)",
504 sfra,
505 efra,
506 efra - sfra + 1);
507 for (scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) {
509 /* For current frame, only update tagged. */
511 }
512 else {
513 /* Update relevant data for new frame. */
515 }
516
517 /* perform baking for targets */
518 motionpaths_calc_bake_targets(targets, scene->r.cfra, depsgraph, scene->camera);
519 }
520
521 /* reset original environment */
522 /* NOTE: We don't always need to reevaluate the main scene, as the depsgraph
523 * may be a temporary one that works on a subset of the data.
524 * We always have to restore the current frame though. */
525 scene->r.cfra = cfra;
526 if (range != ANIMVIZ_CALC_RANGE_CURRENT_FRAME && restore) {
528 }
529
530 if (is_active_depsgraph) {
532 }
533
534 /* clear recalc flags from targets */
535 LISTBASE_FOREACH (MPathTarget *, mpt, targets) {
536 bMotionPath *mpath = mpt->mpath;
537
538 /* get pointer to animviz settings for each target */
540
541 /* clear the flag requesting recalculation of targets */
543
544 /* Clean temp data */
545 ED_keylist_free(mpt->keylist);
546
547 /* Free previous batches to force update. */
551 }
552}
Functions for backward compatibility with the legacy Action API.
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
bool ANIM_bonecoll_is_visible_pchan(const bArmature *armature, const bPoseChannel *pchan)
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
bActionGroup * BKE_action_group_find_name(bAction *act, const char name[])
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2568
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
Definition scene.cc:2647
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define ATTR_FALLTHROUGH
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc: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])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define ELEM(...)
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
@ DAG_EVAL_VIEWPORT
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:273
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:318
void DEG_make_inactive(Depsgraph *depsgraph)
Definition depsgraph.cc:338
void DEG_make_active(Depsgraph *depsgraph)
Definition depsgraph.cc:331
void DEG_graph_build_from_ids(Depsgraph *graph, blender::Span< ID * > ids)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ MOTIONPATH_VERT_KEY
@ MOTIONPATH_VIEW_KFACT
@ MOTIONPATH_RANGE_KEYS_ALL
@ MOTIONPATH_RANGE_KEYS_SELECTED
@ MOTIONPATH_RANGE_SCENE
@ MOTIONPATH_RANGE_MANUAL
@ ANIMVIZ_RECALC_PATHS
@ MOTIONPATH_FLAG_BAKE_CAMERA
@ MOTIONPATH_FLAG_BHEAD
@ FCURVE_SMOOTH_NONE
@ OB_MODE_POSE
#define PSFRA
#define PEFRA
eAnimvizCalcRange
@ ANIMVIZ_CALC_RANGE_FULL
@ ANIMVIZ_CALC_RANGE_CURRENT_FRAME
@ ANIMVIZ_CALC_RANGE_CHANGED
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition GPU_batch.hh:205
#define GPU_VERTBUF_DISCARD_SAFE(verts)
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
static void motionpaths_calc_bake_targets(ListBase *targets, int cframe, Depsgraph *depsgraph, Object *camera)
static void motionpath_get_global_framerange(ListBase *targets, int *r_sfra, int *r_efra)
static bool motionpath_check_can_use_keyframe_range(MPathTarget *, AnimData *adt, ListBase *fcurve_list)
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, AnimKeylist *keylist, int current_frame)
static int motionpath_get_prev_keyframe(MPathTarget *mpt, AnimKeylist *keylist, int current_frame)
static int motionpath_get_next_next_keyframe(MPathTarget *mpt, AnimKeylist *keylist, int current_frame)
void animviz_motionpath_compute_range(Object *ob, Scene *scene)
static bAnimVizSettings * animviz_target_settings_get(MPathTarget *mpt)
static void motionpaths_calc_update_scene(Depsgraph *depsgraph)
static int motionpath_get_next_keyframe(MPathTarget *mpt, AnimKeylist *keylist, int current_frame)
static void motionpath_calculate_update_range(MPathTarget *mpt, AnimData *adt, ListBase *fcurve_list, int current_frame, int *r_sfra, int *r_efra)
Depsgraph * animviz_depsgraph_build(Main *bmain, Scene *scene, ViewLayer *view_layer, ListBase *targets)
static void motionpath_free_free_tree_data(ListBase *targets)
BPy_StructRNA * depsgraph
draw_view in_light_buf[] float
const ActKeyColumn * ED_keylist_find_prev(const AnimKeylist *keylist, const float cfra)
bool ED_keylist_selected_keys_frame_range(const AnimKeylist *keylist, Range2f *r_frame_range)
void ED_keylist_prepare_for_direct_access(AnimKeylist *keylist)
bool ED_keylist_all_keys_frame_range(const AnimKeylist *keylist, Range2f *r_frame_range)
AnimKeylist * ED_keylist_create()
void ED_keylist_free(AnimKeylist *keylist)
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, AnimKeylist *keylist, const int saction_flag, blender::float2 range)
const ActKeyColumn * ED_keylist_find_next(const AnimKeylist *keylist, const float cfra)
const ActKeyColumn * ED_keylist_find_exact(const AnimKeylist *keylist, const float cfra)
void action_to_keylist(AnimData *adt, bAction *dna_action, AnimKeylist *keylist, const int saction_flag, blender::float2 range)
void action_group_to_keylist(AnimData *adt, bActionGroup *agrp, AnimKeylist *keylist, const int saction_flag, blender::float2 range)
#define LOG(severity)
Definition log.h:33
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
Vector< FCurve * > fcurves_for_assigned_action(AnimData *adt)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
#define FLT_MAX
Definition stdcycles.h:14
bAction * action
struct FCurve * next
void * first
AnimKeylist * keylist
bPoseChannel * pchan
MPathTarget * next
MPathTarget * prev
bMotionPath * mpath
struct bPose * pose
bMotionPath * mpath
struct AnimData * adt
bAnimVizSettings avs
float min
Definition BLI_range.h:16
float max
Definition BLI_range.h:17
struct RenderData r
struct Object * camera
ListBase curves
GPUBatchHandle * batch_line
bMotionPathVert * points
GPUVertBufHandle * points_vbo
GPUBatchHandle * batch_points
bMotionPath * mpath
ListBase chanbase
bAnimVizSettings avs