diff options
author | Joshua Leung <aligorith@gmail.com> | 2010-01-08 01:54:05 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2010-01-08 01:54:05 +0300 |
commit | f3a6474537155e60f5db2a101b5ba11e20860307 (patch) | |
tree | e86f41c6d1e353fa9c08a32d8d1cf0deba7561ad /source/blender/blenkernel/intern/anim.c | |
parent | 79bb5419cc4f7bd372e3c611f8b4e2741bb7dc51 (diff) |
Animation Visualisation Cleanups - Part 2:
* Finished baking code for motion paths, generalising it so that it works for both Objects and Bones.
It is based on the old code for baking bones, although I have modified the updating code to use a more 'correct' method of updating dependencies. However, this may turn out to be too slow, and another API method should be added for that...
* Moved some of the old version-patching code for animviz settings out of the drawing functions, instead doing this on the version patching proper.
* Added RNA support for the new AnimViz types, and included RNA access via their users too. The old settings have still been left in for now, since there are still some things not ready to use yet.
----
* F-Curve's with sample points (i.e. sounds to F-Curves) now perform linear interpolation between sample points instead of using constant interpolation.
Diffstat (limited to 'source/blender/blenkernel/intern/anim.c')
-rw-r--r-- | source/blender/blenkernel/intern/anim.c | 161 |
1 files changed, 153 insertions, 8 deletions
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index a7d1ac10195..507fc520a85 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -44,6 +44,7 @@ #include "DNA_anim_types.h" #include "DNA_action_types.h" +#include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_effect_types.h" #include "DNA_group_types.h" @@ -72,6 +73,7 @@ #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_scene.h" #include "BKE_utildefines.h" #ifdef HAVE_CONFIG_H @@ -178,14 +180,21 @@ bMotionPath *animviz_verify_motionpaths(Scene *scene, Object *ob, bPoseChannel * dst= &ob->mpath; } - /* if there is already a motionpath, just return that... */ - // TODO: maybe we should validate the settings in this case - if (*dst != NULL) - return *dst; + /* if there is already a motionpath, just return that, + * but provided it's settings are ok + */ + if (*dst != NULL) { + mpath= *dst; - /* create a new motionpath, and assign it */ - mpath= MEM_callocN(sizeof(bMotionPath), "bMotionPath"); - *dst= mpath; + /* if range is not invalid, and/or length is set ok, just return */ + if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) + return mpath; + } + else { + /* create a new motionpath, and assign it */ + mpath= MEM_callocN(sizeof(bMotionPath), "bMotionPath"); + *dst= mpath; + } /* set settings from the viz settings */ mpath->start_frame= avs->path_sf; @@ -203,15 +212,151 @@ bMotionPath *animviz_verify_motionpaths(Scene *scene, Object *ob, bPoseChannel * return mpath; } +/* ------------------- */ + +/* Motion path needing to be baked (mpt) */ +typedef struct MPathTarget { + struct MPathTarget *next, *prev; + + bMotionPath *mpath; /* motion path in question */ + + Object *ob; /* source object */ + bPoseChannel *pchan; /* source posechannel (if applicable) */ +} MPathTarget; + +/* ........ */ + +/* get list of motion paths to be baked (assumes the list is ready to be used) */ +static void motionpaths_get_bake_targets(Object *ob, ListBase *targets) +{ + MPathTarget *mpt; + + /* object itself first */ + if ((ob->avs.recalc & ANIMVIZ_RECALC_PATHS) && (ob->mpath)) { + /* new target for object */ + mpt= MEM_callocN(sizeof(MPathTarget), "MPathTarget Ob"); + BLI_addtail(targets, mpt); + + mpt->mpath= ob->mpath; + mpt->ob= ob; + } + + /* bones */ + if ((ob->pose) && (ob->pose->avs.recalc & ANIMVIZ_RECALC_PATHS)) { + bArmature *arm= ob->data; + bPoseChannel *pchan; + + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (arm->layer & pchan->bone->layer) && (pchan->mpath)) { + /* new target for bone */ + mpt= MEM_callocN(sizeof(MPathTarget), "MPathTarget PoseBone"); + BLI_addtail(targets, mpt); + + mpt->mpath= pchan->mpath; + mpt->ob= ob; + mpt->pchan= pchan; + } + } + } +} + +/* perform baking for the targets on the current frame */ +static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) +{ + MPathTarget *mpt; + + /* for each target, check if it can be baked on the current frame */ + for (mpt= targets->first; mpt; mpt= mpt->next) { + bMotionPath *mpath= mpt->mpath; + bMotionPathVert *mpv; + + /* current frame must be within the range the cache works for */ + if (IN_RANGE(CFRA, mpath->start_frame, mpath->end_frame) == 0) + continue; + + /* get the relevant cache vert to write to */ + mpv= mpath->points + (CFRA - mpath->start_frame); + + /* pose-channel or object path baking? */ + if (mpt->pchan) { + /* heads or tails */ + if (mpath->flag & MOTIONPATH_FLAG_BHEAD) { + VECCOPY(mpv->co, mpt->pchan->pose_head); + } + else { + VECCOPY(mpv->co, mpt->pchan->pose_tail); + } + + /* result must be in worldspace */ + mul_m4_v3(mpt->ob->obmat, mpv->co); + } + else { + /* worldspace object location */ + VECCOPY(mpv->co, mpt->ob->obmat[3]); + } + } +} + +/* ........ */ /* Perform baking of the given object's and/or its bones' transforms to motion paths * - scene: current scene * - ob: object whose flagged motionpaths should get calculated * - recalc: whether we need to */ +// TODO: include reports pointer? void animviz_calc_motionpaths(Scene *scene, Object *ob) { - + ListBase targets = {NULL, NULL}; + MPathTarget *mpt; + int sfra, efra; + int cfra; + + /* sanity checks */ + if (ob == NULL) + return; + + /* get motion paths to affect */ + motionpaths_get_bake_targets(ob, &targets); + + if (targets.first == NULL) + return; + + /* set frame values */ + cfra = CFRA; + sfra = efra = cfra; + + 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); + efra= MAX2(efra, mpt->mpath->end_frame); + } + if (efra <= sfra) return; + + /* 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, ob->lay); // XXX is the layer flag too restrictive? + + /* perform baking for targets */ + motionpaths_calc_bake_targets(scene, &targets); + } + + /* reset original environment */ + CFRA= cfra; + scene_update_for_newframe(scene, ob->lay); // XXX is the layer flag too restrictive? + + // TODO: make an API call for this too? + ob->avs.recalc &= ~ANIMVIZ_RECALC_PATHS; + if (ob->pose) + ob->pose->avs.recalc &= ~ANIMVIZ_RECALC_PATHS; + + /* free temp data */ + BLI_freelistN(&targets); } /* ******************************************************************** */ |