From e72c6f191f296ee772562b00b5de72688ca6f4cf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 10 Sep 2013 12:46:18 +0000 Subject: [PATCH] Tweaks to plane track - Do plane re-evaluation only when transform is actually done. Before this re-evaluation happened on every mouse move. - Added a flag "Auto Keyframe" for the plane track, which does: * If Auto Keyframe is enabled, then every manual edit of the plane will create a new keyframe at current frame and update plane motion between current frame and previous/next keyframe. This now also implies blending detected motion with neighbor keyframes, so there's no jump happening. No automatic update on manual point tracks edit will happen. * If auto Keyframe is disabled, then no keyframes are adding to the plane and every plane tweak will re-evaluate in on the whole frame range. In this case manual tweaks to point tracks and re-tracking them implies plane re-evaluation. --- release/scripts/startup/bl_ui/space_clip.py | 1 + source/blender/blenkernel/BKE_tracking.h | 2 + source/blender/blenkernel/intern/tracking.c | 82 ++++++++++++++++++- .../blender/editors/space_clip/tracking_ops.c | 39 ++++++++- .../editors/transform/transform_conversions.c | 52 ++++++++++-- .../editors/transform/transform_generics.c | 11 --- source/blender/makesdna/DNA_tracking_types.h | 5 +- source/blender/makesrna/intern/rna_tracking.c | 6 ++ 8 files changed, 171 insertions(+), 27 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 746128eb2c5..540b707cf93 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -601,6 +601,7 @@ class CLIP_PT_plane_track(CLIP_PT_tracking_panel, Panel): return layout.prop(active_track, "name") + layout.prop(active_track, "use_auto_keying") class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel): diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 51946da3857..a860378a35f 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -211,6 +211,8 @@ void BKE_tracking_context_free(struct MovieTrackingContext *context); void BKE_tracking_context_sync(struct MovieTrackingContext *context); void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context, struct MovieClipUser *user); bool BKE_tracking_context_step(struct MovieTrackingContext *context); +void BKE_tracking_context_finish(struct MovieTrackingContext *context); + void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool backwards); /* **** Plane tracking **** */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 899827fc464..1525ded0dd8 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -2498,7 +2498,7 @@ typedef struct MovieTrackingContext { MovieClip *clip; int clip_flag; - int frames; + int frames, first_frame; bool first_time; MovieTrackingSettings settings; @@ -2538,6 +2538,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u context->backwards = backwards; context->sync_frame = user->framenr; context->first_time = true; + context->first_frame = user->framenr; context->sequence = sequence; /* count */ @@ -3114,6 +3115,44 @@ bool BKE_tracking_context_step(MovieTrackingContext *context) return ok; } +void BKE_tracking_context_finish(MovieTrackingContext *context) +{ + MovieClip *clip = context->clip; + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); + MovieTrackingPlaneTrack *plane_track; + int map_size = tracks_map_get_size(context->tracks_map); + + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = plane_track->next) + { + if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { + int i; + for (i = 0; i < map_size; i++) { + TrackContext *track_context = NULL; + MovieTrackingTrack *track, *old_track; + bool do_update = false; + int j; + + tracks_map_get_indexed_element(context->tracks_map, i, &track, (void **)&track_context); + + old_track = BLI_ghash_lookup(context->tracks_map->hash, track); + for (j = 0; j < plane_track->point_tracksnr; j++) { + if (plane_track->point_tracks[j] == old_track) { + do_update = true; + break; + } + } + + if (do_update) { + BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame); + break; + } + } + } + } +} + /* Refine marker's position using previously known keyframe. * Direction of searching for a keyframe depends on backwards flag, * which means if backwards is false, previous keyframe will be as @@ -3246,9 +3285,30 @@ BLI_INLINE void mat3f_from_mat3d(float mat_float[3][3], double mat_double[3][3]) static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track, int start_frame, int direction) { MovieTrackingPlaneMarker *start_plane_marker = BKE_tracking_plane_marker_get(plane_track, start_frame); + MovieTrackingPlaneMarker *keyframe_plane_marker = NULL; MovieTrackingPlaneMarker new_plane_marker; int current_frame, frame_delta = direction > 0 ? 1 : -1; + if (plane_track->flag & PLANE_TRACK_AUTOKEY) { + /* Find a keyframe in given direction. */ + for (current_frame = start_frame; ; current_frame += frame_delta) { + MovieTrackingPlaneMarker *next_plane_marker = + BKE_tracking_plane_marker_get_exact(plane_track, current_frame + frame_delta); + + if (next_plane_marker == NULL) { + break; + } + + if ((next_plane_marker->flag & PLANE_MARKER_TRACKED) == 0) { + keyframe_plane_marker = next_plane_marker; + break; + } + } + } + else { + start_plane_marker->flag |= PLANE_MARKER_TRACKED; + } + new_plane_marker = *start_plane_marker; new_plane_marker.flag |= PLANE_MARKER_TRACKED; @@ -3262,7 +3322,10 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac /* As soon as we meet keyframed plane, we stop updating the sequence. */ if (next_plane_marker && (next_plane_marker->flag & PLANE_MARKER_TRACKED) == 0) { - break; + /* Don't override keyframes if track is in auto-keyframe mode */ + if (plane_track->flag & PLANE_TRACK_AUTOKEY) { + break; + } } num_correspondences = @@ -3296,6 +3359,21 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac new_plane_marker.framenr = current_frame + frame_delta; + if (keyframe_plane_marker && + next_plane_marker && + (plane_track->flag & PLANE_TRACK_AUTOKEY)) + { + float fac = ((float) next_plane_marker->framenr - start_plane_marker->framenr) + / ((float) keyframe_plane_marker->framenr - start_plane_marker->framenr); + + fac = 3*fac*fac - 2*fac*fac*fac; + + for (i = 0; i < 4; i++) { + interp_v2_v2v2(new_plane_marker.corners[i], new_plane_marker.corners[i], + next_plane_marker->corners[i], fac); + } + } + BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker); MEM_freeN(x1); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 70158c23e25..59101b24ad8 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -812,6 +812,32 @@ static void cancel_mouse_slide(SlideMarkerData *data) } } +static void apply_mouse_slide(bContext *C, SlideMarkerData *data) +{ + if (data->area == TRACK_AREA_POINT) { + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTrackingPlaneTrack *plane_track; + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); + int framenr = ED_space_clip_get_clip_frame_number(sc); + + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = plane_track->next) + { + if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { + int i; + for (i = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] == data->track) { + BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); + break; + } + } + } + } + } +} + static void free_slide_data(SlideMarkerData *data) { if (data->old_markers) @@ -1007,6 +1033,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event) case LEFTMOUSE: if (event->val == KM_RELEASE) { + apply_mouse_slide(C, op->customdata); free_slide_data(op->customdata); show_cursor(C); @@ -1267,7 +1294,7 @@ static void track_markers_updatejob(void *tmv) BKE_tracking_context_sync(tmj->context); } -static void track_markers_freejob(void *tmv) +static void track_markers_endjob(void *tmv) { TrackMarkersJob *tmj = (TrackMarkersJob *)tmv; @@ -1276,10 +1303,15 @@ static void track_markers_freejob(void *tmv) ED_update_for_newframe(tmj->main, tmj->scene, 0); BKE_tracking_context_sync(tmj->context); - BKE_tracking_context_free(tmj->context); + BKE_tracking_context_finish(tmj->context); WM_main_add_notifier(NC_SCENE | ND_FRAME, tmj->scene); +} +static void track_markers_freejob(void *tmv) +{ + TrackMarkersJob *tmj = (TrackMarkersJob *)tmv; + BKE_tracking_context_free(tmj->context); MEM_freeN(tmj); } @@ -1333,6 +1365,7 @@ static int track_markers_exec(bContext *C, wmOperator *op) } BKE_tracking_context_sync(context); + BKE_tracking_context_finish(context); BKE_tracking_context_free(context); /* update scene current frame to the lastes tracked frame */ @@ -1389,7 +1422,7 @@ static int track_markers_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS else WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | NA_EVALUATED, 0); - WM_jobs_callbacks(wm_job, track_markers_startjob, NULL, track_markers_updatejob, NULL); + WM_jobs_callbacks(wm_job, track_markers_startjob, NULL, track_markers_updatejob, track_markers_endjob); G.is_break = FALSE; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 73c0b3c0ff4..deda46cfe4f 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5250,6 +5250,48 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o } } +static void special_aftertrans_update__movieclip(bContext *C, TransInfo *t) +{ + SpaceClip *sc = t->sa->spacedata.first; + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTrackingPlaneTrack *plane_track; + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); + int framenr = ED_space_clip_get_clip_frame_number(sc); + + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = plane_track->next) + { + bool do_update = false; + + do_update |= (plane_track->flag & SELECT) != 0; + if (do_update == false) { + if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { + int i; + for (i = 0; i < plane_track->point_tracksnr; i++) { + MovieTrackingTrack *track = plane_track->point_tracks[i]; + + if (TRACK_VIEW_SELECTED(sc, track)) { + do_update = true; + break; + } + } + } + } + + if (do_update) { + BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); + } + } + + if (t->scene->nodetree) { + /* tracks can be used for stabilization nodes, + * flush update for such nodes */ + nodeUpdateID(t->scene->nodetree, &clip->id); + WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL); + } +} + static void special_aftertrans_update__mask(bContext *C, TransInfo *t) { Mask *mask = NULL; @@ -5405,15 +5447,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_CLIP) { if (t->options & CTX_MOVIECLIP) { - SpaceClip *sc = t->sa->spacedata.first; - MovieClip *clip = ED_space_clip_get_clip(sc); - - if (t->scene->nodetree) { - /* tracks can be used for stabilization nodes, - * flush update for such nodes */ - nodeUpdateID(t->scene->nodetree, &clip->id); - WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL); - } + special_aftertrans_update__movieclip(C, t); } else if (t->options & CTX_MASK) { special_aftertrans_update__mask(C, t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 359f6425126..5c8e3f9e58f 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -659,9 +659,7 @@ static void recalcData_spaceclip(TransInfo *t) if (ED_space_clip_check_show_trackedit(sc)) { MovieClip *clip = ED_space_clip_get_clip(sc); ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); - ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); MovieTrackingTrack *track; - MovieTrackingPlaneTrack *plane_track; int framenr = ED_space_clip_get_clip_frame_number(sc); flushTransTracking(t); @@ -692,15 +690,6 @@ static void recalcData_spaceclip(TransInfo *t) track = track->next; } - for (plane_track = plane_tracks_base->first; - plane_track; - plane_track = plane_track->next) - { - if (plane_track->flag & SELECT) { - BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); - } - } - DAG_id_tag_update(&clip->id, 0); } else if (t->options & CTX_MASK) { diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index f81ac4dab06..3eafbee1bad 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -481,8 +481,9 @@ enum { /* MovieTrackingPlaneTrack->flag */ enum { - PLANE_TRACK_HIDDEN = (1 << 1), - PLANE_TRACK_LOCKED = (1 << 2), + PLANE_TRACK_HIDDEN = (1 << 1), + PLANE_TRACK_LOCKED = (1 << 2), + PLANE_TRACK_AUTOKEY = (1 << 3), }; #endif /* __DNA_TRACKING_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index fc71be75d3c..f4c003cfe6c 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -1460,6 +1460,12 @@ static void rna_def_trackingPlaneTrack(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); RNA_def_property_ui_text(prop, "Select", "Plane track is selected"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + + /* auto keyframing */ + prop = RNA_def_property(srna, "use_auto_keying", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PLANE_TRACK_AUTOKEY); + RNA_def_property_ui_text(prop, "Auto Keyframe", "Automatic keyframe insertion when moving plane corners"); + RNA_def_property_ui_icon(prop, ICON_REC, 0); } static void rna_def_trackingStabilization(BlenderRNA *brna)