Camera tracking integration
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 29 Jul 2011 15:25:00 +0000 (15:25 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 29 Jul 2011 15:25:00 +0000 (15:25 +0000)
===========================

Implemented 2D stabilization:

- Based on average point of several tracks.
- Tracks for stabilization are controllable from
  "2D stabilization" panel.
- Implemented autoscaling. Could fail if average point is
  too close to frame boundary.
- Background clip in 3D viewport and MovieClip input
  compositor nodes are using stable shot.

Some internal weak things:
- Stable shots aren't cached in moviecache. There is
  only one "slot" for stable shot inside stabilization
  structure.
- This could fail if several threads are requested different
  frames (for example when starting playback, pause to make
  Nodes Editor trigger refresh, continue playback).
- Due to it shouldn't crash i decided to implement better
  caching for stable shots a bit later.

20 files changed:
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/BKE_movieclip.h
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_clip.h
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_editor.c
source/blender/editors/space_clip/clip_intern.h
source/blender/editors/space_clip/clip_ops.c
source/blender/editors/space_clip/space_clip.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/intern/rna_tracking.c
source/blender/nodes/intern/CMP_nodes/CMP_movieclip.c
source/blender/nodes/intern/CMP_util.h

index 7531881a142149922f6c39bc84f0e088ccc854be..94ed91204256a08fed5daa883ba74f3c604e71ff 100644 (file)
@@ -350,6 +350,44 @@ class CLIP_PT_display(bpy.types.Panel):
             layout.prop(clip, "display_aspect", text="")
 
 
+class CLIP_PT_stabilization(bpy.types.Panel):
+    bl_space_type = 'CLIP_EDITOR'
+    bl_region_type = 'UI'
+    bl_label = "2D Stabilization"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        sc = context.space_data
+
+        return sc.clip
+
+    def draw_header(self, context):
+        sc = context.space_data
+        tracking = sc.clip.tracking
+        stab = tracking.stabilization
+
+        self.layout.prop(stab, "use_2d_stabilization", text="")
+
+    def draw(self, context):
+        layout = self.layout
+        sc = context.space_data
+        tracking = sc.clip.tracking
+        stab = tracking.stabilization
+
+        layout.active = stab.use_2d_stabilization
+
+        layout.prop(stab, "use_autoscale")
+
+        row = layout.row()
+        row.template_list(stab, "tracks", stab, "active_track_index", rows=3)
+
+        sub = row.column(align=True)
+        sub.operator("clip.stabilize_2d_add", icon='ZOOMIN', text="")
+        sub.operator("clip.stabilize_2d_remove", icon='ZOOMOUT', text="")
+        sub.menu('CLIP_MT_stabilize_2d_specials', text="", icon="DOWNARROW_HLT")
+
+
 class CLIP_PT_footage(bpy.types.Panel):
     bl_space_type = 'CLIP_EDITOR'
     bl_region_type = 'UI'
@@ -588,5 +626,14 @@ class CLIP_MT_track_color_specials(bpy.types.Menu):
         layout.operator('clip.track_copy_color', icon='COPY_ID')
 
 
+class CLIP_MT_stabilize_2d_specials(bpy.types.Menu):
+    bl_label = "Track Color Specials"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator('clip.stabilize_2d_select')
+
+
 if __name__ == "__main__":  # only for live edit.
     bpy.utils.register_module(__name__)
index 43424f0c236940b5cce607d1e9fcd50e52d1f534..0dcdc0662abc4a0486b9d50d3001ab66724165b3 100644 (file)
@@ -48,6 +48,7 @@ struct MovieClip *BKE_add_movieclip_file(const char *name);
 void BKE_movieclip_reload(struct MovieClip *clip);
 
 struct ImBuf *BKE_movieclip_acquire_ibuf(struct MovieClip *clip, struct MovieClipUser *user);
+struct ImBuf *BKE_movieclip_acquire_stable_ibuf(struct MovieClip *clip, struct MovieClipUser *user, float mat[4][4]);
 void BKE_movieclip_acquire_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height);
 int BKE_movieclip_has_frame(struct MovieClip *clip, struct MovieClipUser *user);
 void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr);
index 2956e10025141a0820a10c364f04ac9339d7c763..b864fbe6bec9bd2ab0798bf28f6917b276c0b1a3 100644 (file)
@@ -87,6 +87,8 @@ void BKE_tracking_detect(struct MovieTracking *tracking, struct ImBuf *imbuf, in
 
 struct MovieTrackingTrack *BKE_tracking_indexed_bundle(struct MovieTracking *tracking, int bundlenr);
 
+struct ImBuf *BKE_tracking_stabelize_shot(struct MovieTracking *tracking, int framenr, struct ImBuf *ibuf, float mat[4][4]);
+
 #define TRACK_SELECTED(track)                          (((track->flag&TRACK_HIDDEN)==0) && ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT))
 #define TRACK_AREA_SELECTED(track, area)       (((track->flag&TRACK_HIDDEN)==0) && ((area)==TRACK_AREA_POINT?(track)->flag&SELECT : ((area)==TRACK_AREA_PAT?(track)->pat_flag&SELECT:(track)->search_flag&SELECT)))
 
index d9613e4faa0233d68c270b982fbcc148132a7637..eff476b1db694b8b6679cacdbab9f8431c6fce12 100644 (file)
@@ -2482,6 +2482,8 @@ static void dag_id_flush_update(Scene *sce, ID *id)
                }
 
                if(idtype == ID_MC) {
+                       bNode *node;
+
                        for(obt=bmain->object.first; obt; obt= obt->id.next){
                                bConstraint *con;
                                for (con = obt->constraints.first; con; con=con->next) {
@@ -2492,6 +2494,12 @@ static void dag_id_flush_update(Scene *sce, ID *id)
                                        }
                                }
                        }
+
+                       for(node= sce->nodetree->nodes.first; node; node= node->next) {
+                               if(node->id==id) {
+                                       NodeTagChanged(sce->nodetree, node);
+                               }
+                       }
                }
 
                /* camera's matrix is used to orient reconstructed stuff,
index 8bb94764d6bda5cd6edeff4633b3476d955deb24..d39ec2110306f26f6720b52d4c0dee90e3388e68 100644 (file)
@@ -321,6 +321,42 @@ ImBuf *BKE_movieclip_acquire_ibuf(MovieClip *clip, MovieClipUser *user)
        return ibuf;
 }
 
+ImBuf *BKE_movieclip_acquire_stable_ibuf(MovieClip *clip, MovieClipUser *user, float mat[4][4])
+{
+       ImBuf *ibuf, *stableibuf;
+       int framenr= user?user->framenr:clip->lastframe;
+
+       ibuf= BKE_movieclip_acquire_ibuf(clip, user);
+
+       if(clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) {
+               MovieTrackingStabilization *stab= &clip->tracking.stabilization;
+
+               BLI_lock_thread(LOCK_MOVIECLIP);
+
+               if(user->framenr!=stab->framenr)
+                       stab->ibufok= 0;
+
+               stableibuf= BKE_tracking_stabelize_shot(&clip->tracking, framenr, ibuf, mat);
+
+               stab->framenr= user->framenr;
+
+               BLI_unlock_thread(LOCK_MOVIECLIP);
+       } else {
+               if(mat)
+                       unit_m4(mat);
+
+               stableibuf= ibuf;
+       }
+
+       if(stableibuf!=ibuf) {
+               IMB_freeImBuf(ibuf);
+               ibuf= stableibuf;
+       }
+
+       return ibuf;
+
+}
+
 int BKE_movieclip_has_frame(MovieClip *clip, MovieClipUser *user)
 {
        ImBuf *ibuf= BKE_movieclip_acquire_ibuf(clip, user);
@@ -389,6 +425,9 @@ void BKE_movieclip_reload(MovieClip *clip)
        /* clear cache */
        free_buffers(clip);
 
+       clip->tracking.stabilization.ok= 0;
+       clip->tracking.stabilization.ibufok= 0;
+
        /* update clip source */
        if(BLI_testextensie_array(clip->name, imb_ext_movie)) clip->source= MCLIP_SRC_MOVIE;
        else clip->source= MCLIP_SRC_SEQUENCE;
index 542049d70f4ed6377a998a6faeaa91f4d2bcd6f5..865df33f0435f6eafe3991dade627c7e1bb2e091 100644 (file)
@@ -33,6 +33,7 @@
 #include <stddef.h>
 #include <limits.h>
 #include <math.h>
+#include <memory.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -449,6 +450,12 @@ void BKE_tracking_free(MovieTracking *tracking)
 
        if(tracking->camera.reconstructed)
                MEM_freeN(tracking->camera.reconstructed);
+
+       if(tracking->stabilization.ibuf)
+               IMB_freeImBuf(tracking->stabilization.ibuf);
+
+       if(tracking->stabilization.scaleibuf)
+               IMB_freeImBuf(tracking->stabilization.scaleibuf);
 }
 
 /*********************** tracking *************************/
@@ -1211,3 +1218,227 @@ MovieTrackingTrack *BKE_tracking_indexed_bundle(MovieTracking *tracking, int bun
 
        return NULL;
 }
+
+static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
+{
+       int ok= 0;
+       float min[2], max[2];
+       MovieTrackingTrack *track;
+
+       INIT_MINMAX2(min, max);
+
+       track= tracking->tracks.first;
+       while(track) {
+               if(track->flag&TRACK_USE_2D_STAB) {
+                       MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
+
+                       DO_MINMAX2(marker->pos, min, max);
+
+                       ok= 1;
+               }
+
+               track= track->next;
+       }
+
+       median[0]= (max[0]+min[0])/2.f;
+       median[1]= (max[1]+min[1])/2.f;
+
+       return ok;
+}
+
+static float stabilization_auto_scale_factor(MovieTracking *tracking)
+{
+       float firstmedian[2];
+       MovieTrackingStabilization *stab= &tracking->stabilization;
+
+       if(stab->ok)
+               return stab->scale;
+
+       if(stabilization_median_point(tracking, 1, firstmedian)) {
+               int sfra= INT_MAX, efra= INT_MIN, cfra;
+               float delta[2]= {0.f, 0.f}, scalex, scaley, near[2]={1.f, 1.f};
+               MovieTrackingTrack *track;
+
+               track= tracking->tracks.first;
+               while(track) {
+                       if(track->flag&TRACK_USE_2D_STAB) {
+                               if(track->markersnr) {
+                                       sfra= MIN2(sfra, track->markers[0].framenr);
+                                       efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
+                               }
+                       }
+
+                       track= track->next;
+               }
+
+               for(cfra=sfra; cfra<=efra; cfra++) {
+                       float median[2], d[2];
+
+                       stabilization_median_point(tracking, cfra, median);
+
+                       sub_v2_v2v2(d, firstmedian, median);
+                       d[0]= fabsf(d[0]);
+                       d[1]= fabsf(d[1]);
+
+                       delta[0]= MAX2(delta[0], d[0]);
+                       delta[1]= MAX2(delta[1], d[1]);
+
+                       near[0]= MIN3(near[0], median[0], 1.f-median[0]);
+                       near[1]= MIN3(near[1], median[1], 1.f-median[1]);
+               }
+
+               near[0]= MAX2(near[0], 0.05);
+               near[1]= MAX2(near[1], 0.05);
+
+               scalex= 1.f+delta[0]/near[0];
+               scaley= 1.f+delta[1]/near[1];
+
+               stab->scale= MAX2(scalex, scaley);
+       } else {
+               stab->scale= 1.f;
+       }
+
+       stab->ok= 1;
+
+       return stab->scale;
+}
+
+static void calculate_stabmat(MovieTrackingStabilization *stab, float width, float height,
+                       float firstmedian[2], float curmedian[2], float mat[4][4])
+{
+       unit_m4(mat);
+
+       mat[0][0]= stab->scale;
+       mat[1][1]= stab->scale;
+       mat[3][0]= (firstmedian[0]-curmedian[0])*width*stab->scale;
+       mat[3][1]= (firstmedian[1]-curmedian[1])*height*stab->scale;
+
+       mat[3][0]-= (firstmedian[0]*stab->scale-firstmedian[0])*width;
+       mat[3][1]-= (firstmedian[1]*stab->scale-firstmedian[1])*height;
+       /*mat[3][0]-= (width*stab->scale-width)/2.0f;
+       mat[3][1]-= (height*stab->scale-height)/2.0f;*/
+
+}
+
+static int stabelize_need_recalc(MovieTracking *tracking, float width, float height,
+                       float firstmedian[2], float curmedian[2], float mat[4][4])
+{
+       float stabmat[4][4];
+       MovieTrackingStabilization *stab= &tracking->stabilization;
+
+       if(!mat)
+               return 1;
+
+       if(stab->flag&TRACKING_AUTOSCALE)
+               stabilization_auto_scale_factor(tracking);
+
+       calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
+
+       return memcmp(mat, stabmat, sizeof(float)*16);
+}
+
+static ImBuf* stabelize_acquire_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
+{
+       int flags;
+
+       if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
+               IMB_freeImBuf(cacheibuf);
+               cacheibuf= NULL;
+       }
+
+       flags= IB_rect;
+
+       if(srcibuf->rect_float)
+               flags|= IB_rectfloat;
+
+       if(cacheibuf) {
+               if(fill) {
+                       float col[4]= {0.f, 0.f, 0.f, 0.f};
+                       IMB_rectfill(cacheibuf, col);
+               }
+       }
+       else {
+               cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->depth, flags);
+               cacheibuf->profile= srcibuf->profile;
+       }
+
+       return cacheibuf;
+}
+
+ImBuf *BKE_tracking_stabelize_shot(MovieTracking *tracking, int framenr, ImBuf *ibuf, float mat[4][4])
+{
+       float firstmedian[2], curmedian[2], stabmat[4][4];
+       MovieTrackingStabilization *stab= &tracking->stabilization;
+
+       if(mat)
+               copy_m4_m4(stabmat, mat);
+
+       if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
+               if(mat)
+                       unit_m4(mat);
+
+               return ibuf;
+       }
+
+       if(stabilization_median_point(tracking, 1, firstmedian)) {
+               ImBuf *tmpibuf;
+               float width= ibuf->x, height= ibuf->y;
+
+               stabilization_median_point(tracking, framenr, curmedian);
+
+               if((stab->flag&TRACKING_AUTOSCALE)==0)
+                               stab->scale= 1.f;
+
+               if(!stab->ok && stab->ibufok && stab->ibuf)
+                       stab->ibufok= stabelize_need_recalc(tracking, width, height, firstmedian, curmedian, mat) == 0;
+
+               if(!stab->ibuf || !stab->ibufok) {
+                       tmpibuf= stabelize_acquire_ibuf(stab->ibuf, ibuf, 1);
+                       stab->ibuf= tmpibuf;
+
+                       if(stab->flag&TRACKING_AUTOSCALE) {
+                               ImBuf *scaleibuf;
+
+                               stabilization_auto_scale_factor(tracking);
+
+                               scaleibuf= stabelize_acquire_ibuf(stab->scaleibuf, ibuf, 0);
+                               stab->scaleibuf= scaleibuf;
+
+                               IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
+                               IMB_scalefastImBuf(scaleibuf, ibuf->x*stab->scale, ibuf->y*stab->scale);
+
+                               ibuf= scaleibuf;
+                       }
+
+                       calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
+
+                       IMB_rectcpy(tmpibuf, ibuf, stabmat[3][0], stabmat[3][1], 0, 0, ibuf->x, ibuf->y);
+
+                       tmpibuf->userflags|= IB_MIPMAP_INVALID;
+
+                       if(tmpibuf->rect_float)
+                               tmpibuf->userflags|= IB_RECT_INVALID;
+               } else {
+                       calculate_stabmat(stab, width, height, firstmedian, curmedian, stabmat);
+                       tmpibuf= stab->ibuf;
+               }
+
+               stab->ibuf= tmpibuf;
+               IMB_refImBuf(stab->ibuf);
+
+               if(mat)
+                       copy_m4_m4(mat, stabmat);
+
+               stab->ibufok= 1;
+               stab->ok= 1;
+
+               return stab->ibuf;
+       } else {
+               unit_m4(stabmat);
+       }
+
+       if(mat)
+               copy_m4_m4(mat, stabmat);
+
+       return ibuf;
+}
index 43b29714f4fb6c21cdc69aff37477bc6fc159230..3d8537365a39f7d1c93e8e114c7528cfd4c502a3 100644 (file)
@@ -5720,6 +5720,11 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
 
        clip->anim= NULL;
        clip->tracking_context= NULL;
+
+       clip->tracking.stabilization.ok= 0;
+       clip->tracking.stabilization.ibufok= 0;
+       clip->tracking.stabilization.ibuf= NULL;
+       clip->tracking.stabilization.scaleibuf= NULL;
 }
 
 static void lib_link_movieclip(FileData *UNUSED(fd), Main *main)
@@ -11834,9 +11839,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                                        v3d->bundle_drawtype= OB_EMPTY_SPHERE;
                                        }
                                        else if(sl->spacetype==SPACE_CLIP) {
-                                               SpaceClip *sc= (SpaceClip *)sl;
-                                               if(sc->scopes.track_preview_height==0)
-                                                       sc->scopes.track_preview_height= 120;
+                                               SpaceClip *sclip= (SpaceClip *)sl;
+                                               if(sclip->scopes.track_preview_height==0)
+                                                       sclip->scopes.track_preview_height= 120;
                                        }
                                }
                        }
index 809ebb676350861f67e775b644029f8b5b31d9dc..d422deb51b00ee58c896db364e004ce05da13cc9 100644 (file)
@@ -48,8 +48,8 @@ void ED_space_clip_zoom(struct SpaceClip *sc, ARegion *ar, float *zoomx, float *
 void ED_clip_aspect(struct MovieClip *clip, float *aspx, float *aspy);
 void ED_space_clip_aspect(struct SpaceClip *sc, float *aspx, float *aspy);
 
-
 struct ImBuf *ED_space_clip_acquire_buffer(struct SpaceClip *sc);
+struct ImBuf *ED_space_clip_acquire_stable_buffer(struct SpaceClip *sc, float mat[4][4]);
 
 void ED_clip_update_frame(const struct Main *mainp, int cfra);
 void ED_clip_view_selection(struct SpaceClip *sc, struct ARegion *ar, int fit);
index 8c075771afb613e8a283d698f9349c632c47fe08..62ee0f8596a91c2d8bb6033a91e7dea3643abdbe 100644 (file)
@@ -161,8 +161,34 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, float
                        IMB_rect_from_float(ibuf);
                }
 
-               if(ibuf->rect)
+               if(ibuf->rect) {
+                       MovieClip *clip= ED_space_clip(sc);
                        glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+
+                       glColor3f(0.f, 0.f, 0.f);
+                       glLineStipple(3, 0xaaaa);
+                       glEnable(GL_LINE_STIPPLE);
+                       glEnable(GL_COLOR_LOGIC_OP);
+                       glLogicOp(GL_NOR);
+
+                       glPushMatrix();
+                       glTranslatef(x, y, 0);
+
+                       glScalef(zoomx, zoomy, 0);
+                       glMultMatrixf(sc->stabmat);
+
+                       glBegin(GL_LINE_LOOP);
+                               glVertex2f(-1.f, -1.f);
+                               glVertex2f(ibuf->x+1.f, -1.f);
+                               glVertex2f(ibuf->x+1.f, ibuf->y+1.f);
+                               glVertex2f(-1.f, ibuf->y+1.f);
+                       glEnd();
+
+                       glPopMatrix();
+
+                       glDisable(GL_COLOR_LOGIC_OP);
+                       glDisable(GL_LINE_STIPPLE);
+               }
        }
 
        /* reset zoom */
@@ -502,7 +528,7 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
 {
        float x, y, dx, dy, patdx, patdy, searchdx, searchdy, tdx, tdy;
        int tiny= sc->flag&SC_SHOW_TINY_MARKER;
-       float col[3], scol[3];
+       float col[3], scol[3], px[2];
 
        if((tiny && outline) || (marker->flag&MARKER_DISABLED))
                return;
@@ -529,6 +555,9 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
        searchdx= MIN2(dx, (track->search_max[0]-track->search_min[0])/6.f);
        searchdy= MIN2(dy, (track->search_max[1]-track->search_min[1])/6.f);
 
+       px[0]= 1.0f/sc->zoom/width/sc->stabmat[0][0];
+       px[1]= 1.0f/sc->zoom/height/sc->stabmat[1][1];
+
        if((sc->flag&SC_SHOW_MARKER_SEARCH) && ((track->search_flag&SELECT)==sel || outline)) {
                if(!outline) {
                        if(track->search_flag&SELECT) glColor3fv(scol);
@@ -543,8 +572,8 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
                tdy= searchdy;
 
                if(outline) {
-                       tdx+= 1.0f/sc->zoom/width;
-                       tdy+= 1.0f/sc->zoom/height;
+                       tdx+= px[0];
+                       tdy+= px[1];
                }
 
                glBegin(GL_QUADS);
@@ -562,8 +591,8 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
                tdy= searchdy*2.f;
 
                if(outline) {
-                       tdx+= 1.0f/sc->zoom/width;
-                       tdy+= 1.0f/sc->zoom/height;
+                       tdx+= px[0];
+                       tdy+= px[1];
                }
 
                glBegin(GL_TRIANGLES);
@@ -587,8 +616,8 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
                tdy= patdy;
 
                if(outline) {
-                       tdx+= 1.0f/sc->zoom/width;
-                       tdy+= 1.0f/sc->zoom/height;
+                       tdx+= px[0];
+                       tdy+= px[1];
                }
 
                glBegin(GL_QUADS);
@@ -606,8 +635,8 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
                tdy= patdy*2.f;
 
                if(outline) {
-                       tdx+= 1.0f/sc->zoom/width;
-                       tdy+= 1.0f/sc->zoom/height;
+                       tdx+= px[0];
+                       tdy+= px[1];
                }
 
                glBegin(GL_TRIANGLES);
@@ -648,8 +677,8 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
                dy= track->pat_min[1];
        }
 
-       x= (marker->pos[0]+dx)*width*zoomx;
-       y= (marker->pos[1]+dy)*height*zoomy-14.f*UI_DPI_FAC;
+       x= (marker->pos[0]+dx)*width*sc->stabmat[0][0]*zoomx+sc->stabmat[3][0]*zoomx;
+       y= (marker->pos[1]+dy)*height*sc->stabmat[1][1]*zoomy-14.f*UI_DPI_FAC+sc->stabmat[3][1]*zoomy;
 
        if(marker->flag&MARKER_DISABLED) strcpy(state, "disabled");
        else if(marker->framenr!=sc->user.framenr) strcpy(state, "estimated");
@@ -748,6 +777,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
 
        glPushMatrix();
        glScalef(zoomx, zoomy, 0);
+       glMultMatrixf(sc->stabmat);
        glScalef(width, height, 0);
 
        BKE_movieclip_last_selection(clip, &sel_type, &sel);
@@ -899,7 +929,7 @@ void draw_clip_main(SpaceClip *sc, ARegion *ar, Scene *scene)
 
        ED_space_clip_zoom(sc, ar, &zoomx, &zoomy);
 
-       ibuf= ED_space_clip_acquire_buffer(sc);
+       ibuf= ED_space_clip_acquire_stable_buffer(sc, sc->stabmat);
 
        if(ibuf) {
                draw_movieclip_buffer(sc, ar, ibuf, zoomx, zoomy);
index 0f1b753684836921e1ee3222f3fce210b8894f23..23f6de5b353142f7d84ef9bd888bcab04581af35 100644 (file)
@@ -78,6 +78,26 @@ ImBuf *ED_space_clip_acquire_buffer(SpaceClip *sc)
 
                if(ibuf && (ibuf->rect || ibuf->rect_float))
                        return ibuf;
+
+               if(ibuf)
+                       IMB_freeImBuf(ibuf);
+       }
+
+       return NULL;
+}
+
+ImBuf *ED_space_clip_acquire_stable_buffer(SpaceClip *sc, float mat[4][4])
+{
+       if(sc->clip) {
+               ImBuf *ibuf;
+
+               ibuf= BKE_movieclip_acquire_stable_ibuf(sc->clip, &sc->user, mat);
+
+               if(ibuf && (ibuf->rect || ibuf->rect_float))
+                       return ibuf;
+
+               if(ibuf)
+                       IMB_freeImBuf(ibuf);
        }
 
        return NULL;
@@ -130,7 +150,12 @@ void ED_clip_update_frame(const Main *mainp, int cfra)
                        for(sa= win->screen->areabase.first; sa; sa= sa->next) {
                                if(sa->spacetype==SPACE_CLIP) {
                                        SpaceClip *sc= sa->spacedata.first;
+                                       MovieClip *clip= ED_space_clip(sc);
+                                       MovieTrackingStabilization *stab= &clip->tracking.stabilization;
+
                                        sc->scopes.ok= 0;
+                                       stab->ibufok= 0;
+
                                        BKE_movieclip_user_set_frame(&sc->user, cfra);
                                }
                        }
@@ -154,10 +179,13 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr);
 
                        if(marker) {
-                               float pos[2];
+                               float pos[3];
 
                                pos[0]= (marker->pos[0]+track->offset[0])*width;
                                pos[1]= (marker->pos[1]+track->offset[1])*height;
+                               pos[2]= 0.f;
+
+                               mul_v3_m4v3(pos, sc->stabmat, pos);
 
                                DO_MINMAX2(pos, min, max);
 
index 165587526e5797907c054b4ffb1322b742064bab..c7fe8d968cf7acba7457a0b3c2be5d5ddbce59d0 100644 (file)
@@ -94,6 +94,10 @@ void CLIP_OT_track_copy_color(struct wmOperatorType *ot);
 
 void CLIP_OT_detect_features(struct wmOperatorType *ot);
 
+void CLIP_OT_stabilize_2d_add(struct wmOperatorType *ot);
+void CLIP_OT_stabilize_2d_remove(struct wmOperatorType *ot);
+void CLIP_OT_stabilize_2d_select(struct wmOperatorType *ot);
+
 /* clip_draw.c */
 void draw_clip_main(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene);
 void draw_clip_track_widget(const bContext *C, void *poin, void *arg1, void *arg2, rcti *rect);
index 6488f5bb646aaf1a193b80c4ded9bfd5cea21bf7..7f534c2e2dd20f9a5bfe9f92e6dce8adc15e36fd 100644 (file)
@@ -223,11 +223,16 @@ void CLIP_OT_open(wmOperatorType *ot)
 
 static int reload_exec(bContext *C, wmOperator *UNUSED(op))
 {
+       SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= CTX_data_edit_movieclip(C);
 
        if(!clip)
                return OPERATOR_CANCELLED;
 
+       sc->scopes.ok= 0;
+       clip->tracking.stabilization.ok= 0;
+       clip->tracking.stabilization.ibufok= 0;
+
        BKE_movieclip_reload(clip);
 
        WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
index 122d875199cd8df08362d714728f75844d6d482c..2cade521b399efb99d72e9b6d70154d7d4518cbc 100644 (file)
@@ -84,6 +84,19 @@ static void clip_scopes_tag_refresh(ScrArea *sa)
        sc->scopes.ok= 0;
 }
 
+static void clip_stabilization_tag_refresh(ScrArea *sa, int edited)
+{
+       SpaceClip *sc= (SpaceClip *)sa->spacedata.first;
+       MovieClip *clip= ED_space_clip(sc);
+       MovieTrackingStabilization *stab= &clip->tracking.stabilization;
+
+       if(edited) {
+               stab->ok= 0;
+       } else {
+               stab->ibufok= 0;
+       }
+}
+
 /* ******************** default callbacks for clip space ***************** */
 
 static SpaceLink *clip_new(const bContext *UNUSED(C))
@@ -164,6 +177,7 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
                        switch(wmn->data) {
                                case ND_FRAME:
                                        clip_scopes_tag_refresh(sa);
+                                       clip_stabilization_tag_refresh(sa, 0);
                                        /* no break! */
 
                                case ND_FRAME_RANGE:
@@ -186,6 +200,7 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
                                case NA_EDITED:
                                case NA_EVALUATED:
                                        clip_scopes_tag_refresh(sa);
+                                       clip_stabilization_tag_refresh(sa, 1);
                                        ED_area_tag_redraw(sa);
                                        break;
                        }
@@ -193,19 +208,21 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
                case NC_GEOM:
                        switch(wmn->data) {
                                case ND_SELECT:
-                                       ED_area_tag_redraw(sa);
                                        clip_scopes_tag_refresh(sa);
+                                       ED_area_tag_redraw(sa);
                                        break;
                        }
                        break;
                 case NC_SCREEN:
                        if(wmn->data==ND_ANIMPLAY) {
+                               clip_stabilization_tag_refresh(sa, 0);
                                ED_area_tag_redraw(sa);
                        }
                        break;
                case NC_SPACE:
                        if(wmn->data==ND_SPACE_CLIP) {
                                clip_scopes_tag_refresh(sa);
+                               clip_stabilization_tag_refresh(sa, 0);
                                ED_area_tag_redraw(sa);
                        }
                        break;
@@ -262,6 +279,10 @@ static void clip_operatortypes(void)
        WM_operatortype_append(CLIP_OT_frame_jump);
 
        WM_operatortype_append(CLIP_OT_detect_features);
+
+       WM_operatortype_append(CLIP_OT_stabilize_2d_add);
+       WM_operatortype_append(CLIP_OT_stabilize_2d_remove);
+       WM_operatortype_append(CLIP_OT_stabilize_2d_select);
 }
 
 static void clip_keymap(struct wmKeyConfig *keyconf)
@@ -471,9 +492,19 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
        if(clip && clip->tracking_context)
                BKE_tracking_sync_user(&sc->user, clip->tracking_context);
 
-       if(sc->flag&SC_LOCK_SELECTION)
+       if(sc->flag&SC_LOCK_SELECTION) {
+               ImBuf *tmpibuf= NULL;
+
+               if(clip && clip->tracking.stabilization.flag&TRACKING_2D_STABILIZATION) {
+                       tmpibuf= ED_space_clip_acquire_stable_buffer(sc, sc->stabmat);
+               }
+
                ED_clip_view_selection(sc, ar, 0);
 
+               if(tmpibuf)
+                       IMB_freeImBuf(tmpibuf);
+       }
+
        /* clear and setup matrix */
        UI_ThemeClearColor(TH_BACK);
        glClear(GL_COLOR_BUFFER_BIT);
index 1d617056b190efc37981a20aef339f70442509b6..53a4441a5ee953d05f6daa84d50e8c4c97f4f946 100644 (file)
@@ -162,34 +162,38 @@ static int add_marker_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-static void mouse_pos(bContext *C, wmEvent *event, float co[2])
+static void point_stable_pos(bContext *C, float x, float y, float *xr, float *yr)
 {
        ARegion *ar= CTX_wm_region(C);
        SpaceClip *sc= CTX_wm_space_clip(C);
-       int sx, sy;
-       float zoomx, zoomy;
+       int sx, sy, width, height;
+       float zoomx, zoomy, pos[3]={0.f, 0.f, 0.f}, imat[4][4];
 
        ED_space_clip_zoom(sc, ar, &zoomx, &zoomy);
+       ED_space_clip_size(sc, &width, &height);
 
        UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
 
-       co[0]= ((float)event->mval[0]-sx)/zoomx;
-       co[1]= ((float)event->mval[1]-sy)/zoomy;
+       pos[0]= (x-sx)/zoomx;
+       pos[1]= (y-sy)/zoomy;
+
+       invert_m4_m4(imat, sc->stabmat);
+       mul_v3_m4v3(pos, imat, pos);
+
+       *xr= pos[0]/width;
+       *yr= pos[1]/height;
+}
+
+static void mouse_pos(bContext *C, wmEvent *event, float co[2])
+{
+       point_stable_pos(C, event->mval[0], event->mval[1], &co[0], &co[1]);
 }
 
 static int add_marker_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       SpaceClip *sc= CTX_wm_space_clip(C);
-       int width, height;
        float co[2];
 
-       ED_space_clip_size(sc, &width, &height);
-       if(!width || !height)
-               return OPERATOR_CANCELLED;
-
        mouse_pos(C, event, co);
-       co[0]/= width;
-       co[1]/= height;
 
        RNA_float_set_array(op->ptr, "location", co);
 
@@ -206,7 +210,7 @@ void CLIP_OT_add_marker(wmOperatorType *ot)
        /* api callbacks */
        ot->invoke= add_marker_invoke;
        ot->exec= add_marker_exec;
-       ot->poll= space_clip_tracking_poll;
+       ot->poll= space_clip_frame_poll;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -395,7 +399,7 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki
        int inside= 0;
        float size= 12.f;
        float min[2], max[2];
-       float nco[2], crn[2], dx, dy, tdx, tdy;
+       float crn[2], dx, dy, tdx, tdy;
 
        if(area==TRACK_AREA_SEARCH) {
                copy_v2_v2(min, track->search_min);
@@ -405,9 +409,6 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki
                copy_v2_v2(max, track->pat_max);
        }
 
-       nco[0]= co[0]/width;
-       nco[1]= co[1]/height;
-
        dx= size/width/sc->zoom;
        dy= size/height/sc->zoom;
 
@@ -421,12 +422,12 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki
                crn[0]= marker->pos[0]+max[0];
                crn[1]= marker->pos[1]+min[1];
 
-               inside= nco[0]>=crn[0]-dx && nco[0]<=crn[0]+tdx && nco[1]>=crn[1]-tdy && nco[1]<=crn[1]+dy;
+               inside= co[0]>=crn[0]-dx && co[0]<=crn[0]+tdx && co[1]>=crn[1]-tdy && co[1]<=crn[1]+dy;
        } else {
                crn[0]= marker->pos[0]+min[0];
                crn[1]= marker->pos[1]+max[1];
 
-               inside= nco[0]>=crn[0]-dx && nco[0]<=crn[0]+dx && nco[1]>=crn[1]-dy && nco[1]<=crn[1]+dy;
+               inside= co[0]>=crn[0]-dx && co[0]<=crn[0]+dx && co[1]>=crn[1]-dy && co[1]<=crn[1]+dy;
        }
 
        return inside;
@@ -435,20 +436,17 @@ static int mouse_on_corner(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki
 static int mouse_on_offset(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
                        float co[2], int width, int height)
 {
-       float pos[2], nco[2], dx, dy;
+       float pos[2], dx, dy;
 
        add_v2_v2v2(pos, marker->pos, track->offset);
 
-       nco[0]= co[0]/width;
-       nco[1]= co[1]/height;
-
        dx= 12.f/width/sc->zoom;
        dy= 12.f/height/sc->zoom;
 
        dx=MIN2(dx, (track->pat_max[0]-track->pat_min[0])/3);
        dy=MIN2(dy, (track->pat_max[1]-track->pat_min[1])/3);
 
-       return nco[0]>=pos[0]-dx && nco[0]<=pos[0]+dx && nco[1]>=pos[1]-dy && nco[1]<=pos[1]+dy;
+       return co[0]>=pos[0]-dx && co[0]<=pos[0]+dx && co[1]>=pos[1]-dy && co[1]<=pos[1]+dy;
 }
 
 static void hide_cursor(bContext *C)
@@ -826,7 +824,6 @@ static int select_exec(bContext *C, wmOperator *op)
 
 static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       ARegion *ar= CTX_wm_region(C);
        void *customdata;
        float co[2];
        int extend= RNA_boolean_get(op->ptr, "extend");
@@ -839,7 +836,7 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
                }
        }
 
-       UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+       mouse_pos(C, event, co);
        RNA_float_set_array(op->ptr, "location", co);
 
        return select_exec(C, op);
@@ -874,7 +871,6 @@ static int border_select_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTrackingTrack *track;
-       ARegion *ar= CTX_wm_region(C);
        rcti rect;
        rctf rectf;
        int change= 0, mode;
@@ -885,8 +881,8 @@ static int border_select_exec(bContext *C, wmOperator *op)
        rect.xmax= RNA_int_get(op->ptr, "xmax");
        rect.ymax= RNA_int_get(op->ptr, "ymax");
 
-       UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
-       UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
+       point_stable_pos(C, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
+       point_stable_pos(C, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);
 
        mode= RNA_int_get(op->ptr, "gesture_mode");
 
@@ -973,7 +969,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        ellipse[0]= width*zoomx/radius;
        ellipse[1]= height*zoomy/radius;
 
-       UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]);
+       point_stable_pos(C, x, y, &offset[0], &offset[1]);
 
        /* do selection */
        track= clip->tracking.tracks.first;
@@ -2425,3 +2421,146 @@ void CLIP_OT_track_copy_color(wmOperatorType *ot)
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
+
+/********************** add 2d stabilization tracks operator *********************/
+
+static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceClip *sc= CTX_wm_space_clip(C);
+       MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+       MovieTrackingTrack *track;
+       MovieTrackingStabilization *stab= &tracking->stabilization;
+
+       track= tracking->tracks.first;
+       while(track) {
+               if(TRACK_SELECTED(track)) {
+                       track->flag|= TRACK_USE_2D_STAB;
+                       stab->tot_track++;
+               }
+
+               track= track->next;
+       }
+
+       stab->ok= 0;
+
+       DAG_id_tag_update(&clip->id, 0);
+       WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip);
+
+       return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_stabilize_2d_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Stabilization Tracks";
+       ot->description= "Add selected tracks to 2D stabilization tool";
+       ot->idname= "CLIP_OT_stabilize_2d_add";
+
+       /* api callbacks */
+       ot->exec= stabilize_2d_add_exec;
+       ot->poll= space_clip_tracking_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** remove 2d stabilization tracks operator *********************/
+
+static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceClip *sc= CTX_wm_space_clip(C);
+       MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+       MovieTrackingStabilization *stab= &tracking->stabilization;
+       MovieTrackingTrack *track;
+       int a= 0;
+
+       track= tracking->tracks.first;
+       while(track) {
+               if(track->flag&TRACK_USE_2D_STAB) {
+                       if(a==stab->act_track) {
+                               track->flag&= ~TRACK_USE_2D_STAB;
+
+                               stab->act_track--;
+                               stab->tot_track--;
+
+                               if(stab->act_track<0)
+                                       stab->act_track= 0;
+
+                               break;
+                       }
+
+                       a++;
+               }
+
+               track= track->next;
+       }
+
+       stab->ok= 0;
+
+       DAG_id_tag_update(&clip->id, 0);
+       WM_event_add_notifier(C, NC_MOVIECLIP|ND_DISPLAY, clip);
+
+       return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_stabilize_2d_remove(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Remove Stabilization Track";
+       ot->description= "Remove selected track from stabilization";
+       ot->idname= "CLIP_OT_stabilize_2d_remove";
+
+       /* api callbacks */
+       ot->exec= stabilize_2d_remove_exec;
+       ot->poll= space_clip_tracking_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** select 2d stabilization tracks operator *********************/
+
+static int stabilize_2d_select_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceClip *sc= CTX_wm_space_clip(C);
+       MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+       MovieTrackingTrack *track;
+       int a= 0, area;
+
+       area= TRACK_AREA_POINT;
+       if(sc->flag&SC_SHOW_MARKER_PATTERN) area|= TRACK_AREA_PAT;
+       if(sc->flag&SC_SHOW_MARKER_SEARCH) area|= TRACK_AREA_SEARCH;
+
+       track= tracking->tracks.first;
+       while(track) {
+               if(track->flag&TRACK_USE_2D_STAB) {
+                       BKE_tracking_track_flag(track, area, SELECT, 0);
+
+                       a++;
+               }
+
+               track= track->next;
+       }
+
+       WM_event_add_notifier(C, NC_MOVIECLIP|ND_SELECT, clip);
+
+       return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_stabilize_2d_select(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Select Stabilization Tracks";
+       ot->description= "Select track whic hare used for stabilization";
+       ot->idname= "CLIP_OT_stabilize_2d_select";
+
+       /* api callbacks */
+       ot->exec= stabilize_2d_select_exec;
+       ot->poll= space_clip_tracking_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
index 81a02b846cb082b82ba57212ed18ad4068a1c6b0..9690b35bc34822d436116892c929ef928df89b84 100644 (file)
@@ -1423,7 +1423,7 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d)
                                if(clip==NULL)
                                        continue;
                                BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
-                               ibuf= BKE_movieclip_acquire_ibuf(clip, &bgpic->cuser);
+                               ibuf= BKE_movieclip_acquire_stable_ibuf(clip, &bgpic->cuser, NULL);
 
                                /* working with ibuf from image and clip has got different workflow now.
                                   ibuf acquired from clip is referenced by cache system and should
index c9920d1edd2fffc87d4c522c1bfaa94901bf36f2..da0ad4c3aae87a1fb3aae2b4c003f66fa9a1b278 100644 (file)
@@ -589,6 +589,9 @@ typedef struct SpaceClip {
        float track_offset[2];                                          /* offset of "parenting" point */
        float track_search_pos[2], track_search[2];     /* position and dimensions of marker search in pixel coords */
        int marker_flag;                                                        /* marker's flags */
+
+       float stabmat[4][4];    /* current stabilization matrix, defined when drawing
+                                                          and used for mouse position calculation */
 } SpaceClip;
 
 /* view3d  Now in DNA_view3d_types.h */
index da479db257dfcf84effafbdca1826b2caa4d1cd3..fc6e19ad2ab57fe50a2206ef80010ab2b7b83a6a 100644 (file)
@@ -41,6 +41,7 @@
 
 /* match-moving data */
 
+struct ImBuf;
 struct MovieReconstructedCamera;
 struct MovieTrackingCamera;
 struct MovieTrackingBundle;
@@ -110,10 +111,26 @@ typedef struct MovieTrackingSettings {
        float pad;
 } MovieTrackingSettings;
 
+typedef struct MovieTrackingStabilization {
+       int flag;
+       int tot_track, act_track;               /* total number and index of active track in list */
+
+       /* some pre-computing run-time variables */
+       int ok, ibufok;                         /* are precomputed values and scaled buf relevant? */
+       float scale;                            /* autoscale factor */
+
+       int pad;
+
+       int framenr;                            /* number of frame image is stabilized for */
+       struct ImBuf *ibuf;                     /* currently stabelized ibuf */
+       struct ImBuf *scaleibuf;        /* currently scaled ibuf */
+} MovieTrackingStabilization;
+
 typedef struct MovieTracking {
-       MovieTrackingSettings settings;
-       MovieTrackingCamera camera;
-       ListBase tracks;
+       MovieTrackingSettings settings; /* different tracking-related settings */
+       MovieTrackingCamera camera;             /* camera intrinsics */
+       ListBase tracks;                                /* all tracks */
+       MovieTrackingStabilization stabilization;       /* stabilization data */
 } MovieTracking;
 
 /* MovieTrackingCamera->units */
@@ -134,6 +151,7 @@ enum {
 #define TRACK_HIDDEN           (1<<5)
 #define TRACK_LOCKED           (1<<6)
 #define TRACK_CUSTOMCOLOR      (1<<7)
+#define TRACK_USE_2D_STAB      (1<<8)
 
 /* MovieTrackingSettings->speed */
 #define TRACKING_SPEED_FASTEST         0
@@ -142,6 +160,10 @@ enum {
 #define TRACKING_SPEED_QUARTER         4
 
 /* MovieTrackingSettings->flag */
-#define TRACKING_FRAMES_LIMIT          1
+#define TRACKING_FRAMES_LIMIT          (1<<0)
+
+/* MovieTrackingStrabilization->flag */
+#define TRACKING_2D_STABILIZATION      (1<<0)
+#define TRACKING_AUTOSCALE                     (1<<1)
 
 #endif
index 064b44df87ffb7096d6daa15a46878f8dce1e19e..c735867478877ad0a6f810fe4cb8242e5db2e65f 100644 (file)
 #ifdef RNA_RUNTIME
 
 #include "BKE_depsgraph.h"
+#include "BKE_node.h"
+
+#include "IMB_imbuf.h"
+
+#include "WM_api.h"
 
 static void rna_tracking_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
@@ -143,6 +148,57 @@ static void rna_trackingCamera_focal_set(PointerRNA *ptr, float value)
        camera->focal= value;
 }
 
+static int rna_track_2d_stabilization(CollectionPropertyIterator *UNUSED(iter), void *data)
+{
+       MovieTrackingTrack *track= (MovieTrackingTrack*)data;
+
+       if((track->flag&TRACK_USE_2D_STAB)==0)
+               return 1;
+
+       return 0;
+}
+
+static void rna_tracking_stabTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+       rna_iterator_listbase_begin(iter, &clip->tracking.tracks, rna_track_2d_stabilization);
+}
+
+static int rna_tracking_stabTracks_active_index_get(PointerRNA *ptr)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+       return clip->tracking.stabilization.act_track;
+}
+
+static void rna_tracking_stabTracks_active_index_set(PointerRNA *ptr, int value)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+       clip->tracking.stabilization.act_track= value;
+}
+
+static void rna_tracking_stabTracks_active_index_range(PointerRNA *ptr, int *min, int *max)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+
+       *min= 0;
+       *max= clip->tracking.stabilization.tot_track-1;
+       *max= MAX2(0, *max);
+}
+
+static void rna_tracking_flushUpdate(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+       MovieTrackingStabilization *stab= &clip->tracking.stabilization;
+
+       stab->ok= 0;
+       stab->ibufok= 0;
+
+       NodeTagIDChanged(scene->nodetree, &clip->id);
+
+       WM_main_add_notifier(NC_SCENE|ND_NODES, NULL);
+       DAG_id_tag_update(&clip->id, 0);
+}
+
 #else
 
 static void rna_def_trackingSettings(BlenderRNA *brna)
@@ -400,6 +456,40 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL);
 }
 
+static void rna_def_trackingStabilization(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna= RNA_def_struct(brna, "MovieTrackingStabilization", NULL);
+       RNA_def_struct_ui_text(srna, "Movie tracking stabilization data", "Match-moving stabilization data for tracking");
+
+       /* tracks */
+       prop= RNA_def_property(srna, "tracks", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_funcs(prop, "rna_tracking_stabTracks_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0);
+       RNA_def_property_struct_type(prop, "MovieTrackingTrack");
+       RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks used for stabilization");
+       RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, "rna_tracking_flushUpdate");
+
+       /* 2d stabilization */
+       prop= RNA_def_property(srna, "use_2d_stabilization", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_2D_STABILIZATION);
+       RNA_def_property_ui_text(prop, "Use 2D stabilization", "Use 2D stabilization for footage");
+       RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, "rna_tracking_flushUpdate");
+
+       /* active track index */
+       prop= RNA_def_property(srna, "active_track_index", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "act_track");
+       RNA_def_property_int_funcs(prop, "rna_tracking_stabTracks_active_index_get", "rna_tracking_stabTracks_active_index_set", "rna_tracking_stabTracks_active_index_range");
+       RNA_def_property_ui_text(prop, "Active Track Index", "Index of active track in stabilization tracks list");
+
+       /* autoscale */
+       prop= RNA_def_property(srna, "use_autoscale", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_AUTOSCALE);
+       RNA_def_property_ui_text(prop, "Autoscale", "Automatically scale footage to cover unfilled areas when stabilizating");
+       RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, "rna_tracking_flushUpdate");
+}
+
 static void rna_def_tracking(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -408,6 +498,7 @@ static void rna_def_tracking(BlenderRNA *brna)
        rna_def_trackingSettings(brna);
        rna_def_trackingCamera(brna);
        rna_def_trackingTrack(brna);
+       rna_def_trackingStabilization(brna);
 
        srna= RNA_def_struct(brna, "MovieTracking", NULL);
        RNA_def_struct_ui_text(srna, "Movie tracking data", "Match-moving data for tracking");
@@ -426,11 +517,15 @@ static void rna_def_tracking(BlenderRNA *brna)
        RNA_def_property_struct_type(prop, "MovieTrackingTrack");
        RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
 
-       /* active tracks */
+       /* active track */
        prop= RNA_def_property(srna, "active_track", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "MovieTrackingTrack");
        RNA_def_property_pointer_funcs(prop, "rna_tracking_active_track_get", NULL, NULL, NULL);
        RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
+
+       /* stabilization*/
+       prop= RNA_def_property(srna, "stabilization", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "MovieTrackingStabilization");
 }
 
 void RNA_def_tracking(BlenderRNA *brna)
index cd26c9b56839f17fd3f3a8b2f0fb0da54ab8b238..36be818ed1d138d760c67b3af85273b148946363 100644 (file)
@@ -35,7 +35,6 @@
 
 #include "../CMP_util.h"
 
-
 static bNodeSocketType cmp_node_rlayers_out[]= {
        {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
@@ -50,14 +49,16 @@ static CompBuf *node_composit_get_movieclip(RenderData *rd, MovieClip *clip, Mov
        float *rect;
        int alloc= FALSE;
 
-       ibuf= BKE_movieclip_acquire_ibuf(clip, user);
+       ibuf= BKE_movieclip_acquire_stable_ibuf(clip, user, NULL);
+
        if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
                IMB_freeImBuf(ibuf);
                return NULL;
        }
 
-       if (ibuf->rect_float == NULL) {
+       if (ibuf->rect_float == NULL || ibuf->userflags&IB_RECT_INVALID) {
                IMB_float_from_rect(ibuf);
+               ibuf->userflags&= ~IB_RECT_INVALID;
        }
 
        /* now we need a float buffer from the image with matching color management */
index 91dfff53c2ac9e79d998d578508618771f6acab1..75e8401ad497b35a4e4991efed1f68f08363f4af 100644 (file)
@@ -68,6 +68,7 @@
 #include "BKE_movieclip.h"
 #include "BKE_node.h"
 #include "BKE_texture.h"
+#include "BKE_tracking.h"
 
 #include "BKE_library.h"
 #include "BKE_object.h"