Tweaks to plane track
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 10 Sep 2013 12:46:18 +0000 (12:46 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 10 Sep 2013 12:46:18 +0000 (12:46 +0000)
- 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
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/tracking.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/intern/rna_tracking.c

index 746128eb2c545100af2218fe821cb390624d60c9..540b707cf932c91b0c323c38e3dc76288c4350b6 100644 (file)
@@ -601,6 +601,7 @@ class CLIP_PT_plane_track(CLIP_PT_tracking_panel, Panel):
             return
 
         layout.prop(active_track, "name")
             return
 
         layout.prop(active_track, "name")
+        layout.prop(active_track, "use_auto_keying")
 
 
 class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel):
 
 
 class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel):
index 51946da3857ca49910d60e782613767a81399e82..a860378a35fa1fcac0375732fb078d4067afce11 100644 (file)
@@ -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_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 **** */
 void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool backwards);
 
 /* **** Plane tracking **** */
index 899827fc464ba59fa19298cec794afd0f9f164d9..1525ded0dd8a43be7ef86b7aab3f39a957276aad 100644 (file)
@@ -2498,7 +2498,7 @@ typedef struct MovieTrackingContext {
        MovieClip *clip;
        int clip_flag;
 
        MovieClip *clip;
        int clip_flag;
 
-       int frames;
+       int frames, first_frame;
        bool first_time;
 
        MovieTrackingSettings settings;
        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->backwards = backwards;
        context->sync_frame = user->framenr;
        context->first_time = true;
+       context->first_frame = user->framenr;
        context->sequence = sequence;
 
        /* count */
        context->sequence = sequence;
 
        /* count */
@@ -3114,6 +3115,44 @@ bool BKE_tracking_context_step(MovieTrackingContext *context)
        return ok;
 }
 
        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
 /* 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);
 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;
 
        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;
 
        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) {
 
                /* 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 =
                }
 
                num_correspondences =
@@ -3296,6 +3359,21 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac
 
                new_plane_marker.framenr = current_frame + frame_delta;
 
 
                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);
                BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker);
 
                MEM_freeN(x1);
index 70158c23e25bf325bf0112325789116b94008aa4..59101b24ad81748ea41c09ede3c9fda8c8479942 100644 (file)
@@ -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)
 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) {
 
                case LEFTMOUSE:
                        if (event->val == KM_RELEASE) {
+                               apply_mouse_slide(C, op->customdata);
                                free_slide_data(op->customdata);
 
                                show_cursor(C);
                                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);
 }
 
        BKE_tracking_context_sync(tmj->context);
 }
 
-static void track_markers_freejob(void *tmv)
+static void track_markers_endjob(void *tmv)
 {
        TrackMarkersJob *tmj = (TrackMarkersJob *)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);
        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);
 
        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);
 }
 
        MEM_freeN(tmj);
 }
 
@@ -1333,6 +1365,7 @@ static int track_markers_exec(bContext *C, wmOperator *op)
        }
 
        BKE_tracking_context_sync(context);
        }
 
        BKE_tracking_context_sync(context);
+       BKE_tracking_context_finish(context);
        BKE_tracking_context_free(context);
 
        /* update scene current frame to the lastes tracked frame */
        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);
 
        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;
 
 
        G.is_break = FALSE;
 
index 73c0b3c0ff4e6ee3768989fda3def49f98142f66..deda46cfe4f12b9c59301c58ad97eedf8f7e3793 100644 (file)
@@ -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;
 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) {
        }
        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);
                }
                else if (t->options & CTX_MASK) {
                        special_aftertrans_update__mask(C, t);
index 359f6425126f7d9890ef8bcc32d40f052739ec13..5c8e3f9e58f26392b1ff12b82eda3ff92ee391b6 100644 (file)
@@ -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);
        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;
                MovieTrackingTrack *track;
-               MovieTrackingPlaneTrack *plane_track;
                int framenr = ED_space_clip_get_clip_frame_number(sc);
 
                flushTransTracking(t);
                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;
                }
 
                        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) {
                DAG_id_tag_update(&clip->id, 0);
        }
        else if (t->options & CTX_MASK) {
index f81ac4dab0642e473ffbc66d48b27344a54ceba5..3eafbee1bad56d20699f84a89a46b1dccb16d047 100644 (file)
@@ -481,8 +481,9 @@ enum {
 
 /* MovieTrackingPlaneTrack->flag */
 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__ */
 };
 
 #endif  /* __DNA_TRACKING_TYPES_H__ */
index fc71be75d3cabc7562fd992fa4e4b023de139427..f4c003cfe6cf955d132ca0cdc63a4839b636f019 100644 (file)
@@ -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);
        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)
 }
 
 static void rna_def_trackingStabilization(BlenderRNA *brna)