Merge plane track feature from tomato branch
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 16 Aug 2013 09:46:30 +0000 (09:46 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 16 Aug 2013 09:46:30 +0000 (09:46 +0000)
This commit includes all the changes made for plane tracker
in tomato branch.

Movie clip editor changes:

- Artist might create a plane track out of multiple point
  tracks which belongs to the same track (minimum amount of
  point tracks is 4, maximum is not actually limited).

  When new plane track is added, it's getting "tracked"
  across all point tracks, which makes it stick to the same
  plane point tracks belong to.

- After plane track was added, it need to be manually adjusted
  in a way it covers feature one might to mask/replace.

  General transform tools (G, R, S) or sliding corners with
  a mouse could be sued for this. Plane corner which
  corresponds to left bottom image corner has got X/Y axis
  on it (red is for X axis, green for Y).

- Re-adjusting plane corners makes plane to be "re-tracked"
  for the frames sequence between current frame and next
  and previous keyframes.

- Kayframes might be removed from the plane, using Shit-X
  (Marker Delete) operator. However, currently manual
  re-adjustment or "re-track" trigger is needed.

Compositor changes:

- Added new node called Plane Track Deform.

- User selects which plane track to use (for this he need
  to select movie clip datablock, object and track names).

- Node gets an image input, which need to be warped into
  the plane.

- Node outputs:
  * Input image warped into the plane.
  * Plane, rasterized to a mask.

Masking changes:

- Mask points might be parented to a plane track, which
  makes this point deforming in a way as if it belongs
  to the tracked plane.

Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578

This is mine and Keir's holiday code project :)

48 files changed:
extern/libmv/libmv-capi.cc
extern/libmv/libmv-capi.h
extern/libmv/libmv-capi_stub.cc
release/scripts/startup/bl_ui/properties_mask_common.py
release/scripts/startup/bl_ui/space_clip.py
release/scripts/startup/nodeitems_builtins.py
source/blender/blenkernel/BKE_mask.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/mask.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/compositor/CMakeLists.txt
source/blender/compositor/intern/COM_Converter.cpp
source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp [new file with mode: 0644]
source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h [new file with mode: 0644]
source/blender/editors/mask/mask_relationships.c
source/blender/editors/mask/mask_shapekey.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_graph_ops.c
source/blender/editors/space_clip/clip_intern.h
source/blender/editors/space_clip/clip_utils.c
source/blender/editors/space_clip/space_clip.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/space_clip/tracking_select.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/makesdna/DNA_mask_types.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/intern/rna_mask.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_tracking.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_composite.h
source/blender/nodes/NOD_static_types.h
source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c [new file with mode: 0644]

index 063c63f9266b59eb9b3be8288c7bbef1632c6dd6..e1fd509d581c43fe7442db539757d01f912d23a9 100644 (file)
@@ -58,6 +58,8 @@
 #include "libmv/simple_pipeline/reconstruction_scale.h"
 #include "libmv/simple_pipeline/keyframe_selection.h"
 
+#include "libmv/multiview/homography.h"
+
 #ifdef _MSC_VER
 #  define snprintf _snprintf
 #endif
@@ -1080,4 +1082,28 @@ void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_cam
        }
 }
 
+void libmv_homography2DFromCorrespondencesLinear(double (*x1)[2], double (*x2)[2], int num_points,
+                                                 double H[3][3], double expected_precision)
+{
+       libmv::Mat x1_mat, x2_mat;
+       libmv::Mat3 H_mat;
+
+       x1_mat.resize(2, num_points);
+       x2_mat.resize(2, num_points);
+
+       for (int i = 0; i < num_points; i++) {
+               x1_mat.col(i) = libmv::Vec2(x1[i][0], x1[i][1]);
+               x2_mat.col(i) = libmv::Vec2(x2[i][0], x2[i][1]);
+       }
+
+       LG << "x1: " << x1_mat;
+       LG << "x2: " << x2_mat;
+
+       libmv::Homography2DFromCorrespondencesLinear(x1_mat, x2_mat, &H_mat, expected_precision);
+
+       LG << "H: " << H_mat;
+
+       memcpy(H, H_mat.data(), 9 * sizeof(double));
+}
+
 #endif
index 7c91881fe71638c0fc539ca12d7ddaedc9f4ace7..37aab2465ed76480cc7046cdf8240df3cdc5f5df 100644 (file)
@@ -159,6 +159,9 @@ void libmv_cameraIntrinsicsApply(const libmv_CameraIntrinsicsOptions *libmv_came
 void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
                                   double x, double y, double *x1, double *y1);
 
+void libmv_homography2DFromCorrespondencesLinear(double (*x1)[2], double (*x2)[2], int num_points,
+                                                 double H[3][3], double expected_precision);
+
 #ifdef __cplusplus
 }
 #endif
index 36977eb58bab11f64b21260448ce41bc9b1da60c..07125b80f0419d6e2f21f81690cd7132613cf9d4 100644 (file)
@@ -277,4 +277,13 @@ void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_cam
        *y1 = (y - principal_y) / focal_length;
 }
 
+void libmv_homography2DFromCorrespondencesLinear(double (* /* x1 */)[2], double (* /* x2 */)[2], int /* num_points */,
+                                                 double H[3][3], double /* expected_precision */)
+{
+       memset(H, 0, sizeof(H));
+       N[0][0] = 1.0f;
+       N[1][1] = 1.0f;
+       N[02[2] = 1.0f;
+}
+
 #endif  // ifndef WITH_LIBMV
index d38f5f934b41d6bc2fe6a19ae78bc04d61bb0ce2..9f72d7a6d888771792a499bf1488ee29891aac65 100644 (file)
@@ -190,16 +190,21 @@ class MASK_PT_point():
             clip = parent.id
             tracking = clip.tracking
 
+            row = col.row()
+            row.prop(parent, "type", expand=True)
+
             col.prop_search(parent, "parent", tracking,
                             "objects", icon='OBJECT_DATA', text="Object:")
 
+            tracks_list = "tracks" if parent.type == 'POINT_TRACK' else 'plane_tracks'
+
             if parent.parent in tracking.objects:
                 object = tracking.objects[parent.parent]
                 col.prop_search(parent, "sub_parent", object,
-                                "tracks", icon='ANIM_DATA', text="Track:")
+                                tracks_list, icon='ANIM_DATA', text="Track:")
             else:
                 col.prop_search(parent, "sub_parent", tracking,
-                                "tracks", icon='ANIM_DATA', text="Track:")
+                                tracks_list, icon='ANIM_DATA', text="Track:")
 
 
 class MASK_PT_display():
index 5048a93d56534f41dc8e43e4ded8d654a28702ad..04584855ed325d1368021ddc15a11780f3116112 100644 (file)
@@ -311,6 +311,16 @@ class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel):
         layout.operator("clip.join_tracks", text="Join")
 
 
+class CLIP_PT_tools_plane_tracking(CLIP_PT_tracking_panel, Panel):
+    bl_space_type = 'CLIP_EDITOR'
+    bl_region_type = 'TOOLS'
+    bl_label = "Plane Track"
+
+    def draw(self, context):
+        layout = self.layout
+        layout.operator("clip.create_plane_track")
+
+
 class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
     bl_space_type = 'CLIP_EDITOR'
     bl_region_type = 'TOOLS'
@@ -579,6 +589,26 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
             layout.label(text=label_text)
 
 
+class CLIP_PT_plane_track(CLIP_PT_tracking_panel, Panel):
+    bl_space_type = 'CLIP_EDITOR'
+    bl_region_type = 'UI'
+    bl_label = "Plane Track"
+
+    def draw(self, context):
+        layout = self.layout
+
+        sc = context.space_data
+        clip = context.space_data.clip
+        active_track = clip.tracking.plane_tracks.active
+
+        if not active_track:
+            layout.active = False
+            layout.label(text="No active plane track")
+            return
+
+        layout.prop(active_track, "name")
+
+
 class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel):
     bl_space_type = 'CLIP_EDITOR'
     bl_region_type = 'UI'
index 91090dc2c75dbd59a261281b8b792629c7113d21..6a5dccaed884b8513744c0bc5c246f8639b61270 100644 (file)
@@ -342,6 +342,7 @@ compositor_node_categories = [
         NodeItem("CompositorNodeMapUV"),
         NodeItem("CompositorNodeTransform"),
         NodeItem("CompositorNodeStabilize"),
+        NodeItem("CompositorNodePlaneTrackDeform"),
         ]),
     CompositorNodeCategory("CMP_GROUP", "Group", items=node_group_items),
     CompositorNodeCategory("CMP_LAYOUT", "Layout", items=[
index 92332116ba65dcdb26e78cf27e79535fe00357fd..14ceba42aff3d297455fd99143006f91558cf609 100644 (file)
@@ -53,9 +53,11 @@ void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay);
 void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay);
 
 void BKE_mask_layer_free_shapes(struct MaskLayer *masklay);
+void BKE_mask_layer_free_deform(struct MaskLayer *mask_layer);
 void BKE_mask_layer_free(struct MaskLayer *masklay);
 void BKE_mask_layer_free_list(struct ListBase *masklayers);
 void BKE_mask_spline_free(struct MaskSpline *spline);
+void BKE_mask_spline_free_list(struct ListBase *splines);
 struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline);
 void BKE_mask_point_free(struct MaskSplinePoint *point);
 
index 4e9e18d43e329706f3f5ec0a08611c9e6efb31d7..27192437c89a1d313729ced16df2f84e8f33881d 100644 (file)
@@ -898,6 +898,7 @@ void            ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
 #define CMP_NODE_PIXELATE       318
 
 #define CMP_NODE_MAP_RANGE     319
+#define CMP_NODE_PLANETRACKDEFORM      320
 
 /* channel toggles */
 #define CMP_CHAN_RGB           1
index 84bca0bd3ba7f7bc8a9e638998d3735241a44d0f..0d148e557533d18241fe4e60940c49d852a5ab26 100644 (file)
@@ -38,6 +38,8 @@ struct ListBase;
 struct MovieReconstructContext;
 struct MovieTrackingTrack;
 struct MovieTrackingMarker;
+struct MovieTrackingPlaneTrack;
+struct MovieTrackingPlaneMarker;
 struct MovieTracking;
 struct MovieTrackingContext;
 struct MovieTrackingObject;
@@ -55,6 +57,7 @@ void BKE_tracking_free(struct MovieTracking *tracking);
 void BKE_tracking_settings_init(struct MovieTracking *tracking);
 
 struct ListBase *BKE_tracking_get_active_tracks(struct MovieTracking *tracking);
+struct ListBase *BKE_tracking_get_active_plane_tracks(struct MovieTracking *tracking);
 struct MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(struct MovieTracking *tracking);
 
 /* matrices for constraints and drawing */
@@ -97,6 +100,7 @@ float *BKE_tracking_track_get_mask(int frame_width, int frame_height, struct Mov
 /* selection */
 void BKE_tracking_track_select(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend);
 void BKE_tracking_track_deselect(struct MovieTrackingTrack *track, int area);
+void BKE_tracking_tracks_deselect_all(struct ListBase *tracksbase);
 
 /* **** Marker **** */
 struct MovieTrackingMarker *BKE_tracking_marker_insert(struct MovieTrackingTrack *track,
@@ -113,6 +117,32 @@ void BKE_tracking_marker_pattern_minmax(const struct MovieTrackingMarker *marker
 
 void BKE_tracking_marker_get_subframe_position(struct MovieTrackingTrack *track, float framenr, float pos[2]);
 
+/* **** Plane Track **** */
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(struct MovieTracking *tracking, struct ListBase *plane_tracks_base,
+                                                             struct ListBase *tracks, int framenr);
+void BKE_tracking_plane_track_unique_name(struct ListBase *plane_tracks_base, struct MovieTrackingPlaneTrack *plane_track);
+void BKE_tracking_plane_track_free(struct MovieTrackingPlaneTrack *plane_track);
+
+bool BKE_tracking_plane_track_has_marker_at_frame(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+bool BKE_tracking_plane_track_has_enabled_marker_at_frame(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(struct MovieTracking *tracking,
+                                                                   struct MovieTrackingObject *object,
+                                                                   const char *name);
+
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking);
+
+void BKE_tracking_plane_tracks_deselect_all(struct ListBase *plane_tracks_base);
+
+/* **** Plane Marker **** */
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track,
+                                                                  struct MovieTrackingPlaneMarker *plane_marker);
+void BKE_tracking_plane_marker_delete(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
 /* **** Object **** */
 struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name);
 int BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object);
@@ -125,6 +155,7 @@ struct MovieTrackingObject *BKE_tracking_object_get_active(struct MovieTracking
 struct MovieTrackingObject *BKE_tracking_object_get_camera(struct MovieTracking *tracking);
 
 struct ListBase *BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
+struct ListBase *BKE_tracking_object_get_plane_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
 struct MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(struct MovieTracking *tracking,
                                                                            struct MovieTrackingObject *object);
 
@@ -182,6 +213,11 @@ void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context,
 int BKE_tracking_context_step(struct MovieTrackingContext *context);
 void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int backwards);
 
+/* **** Plane tracking **** */
+
+void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame);
+void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners[4][2], /*const*/ float corners[4][2], float H[3][3]);
+
 /* **** Camera solving **** */
 int BKE_tracking_reconstruction_check(struct MovieTracking *tracking, struct MovieTrackingObject *object,
                                       char *error_msg, int error_size);
index e3f30bad5cf3981dd5961c86d849d742313dc0e0..a7bfb15c99df82111dc5de7edc10047a8f1fba36 100644 (file)
@@ -817,6 +817,19 @@ void BKE_mask_spline_free(MaskSpline *spline)
        MEM_freeN(spline);
 }
 
+void BKE_mask_spline_free_list(ListBase *splines)
+{
+       MaskSpline *spline = splines->first;
+       while (spline) {
+               MaskSpline *next_spline = spline->next;
+
+               BLI_remlink(splines, spline);
+               BKE_mask_spline_free(spline);
+
+               spline = next_spline;
+       }
+}
+
 static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot_point)
 {
        MaskSplinePoint *npoints;
@@ -891,20 +904,30 @@ void BKE_mask_layer_free_shapes(MaskLayer *masklay)
        }
 }
 
-void BKE_mask_layer_free(MaskLayer *masklay)
+void BKE_mask_layer_free_deform(MaskLayer *mask_layer)
 {
-       MaskSpline *spline;
-
-       /* free splines */
-       spline = masklay->splines.first;
-       while (spline) {
-               MaskSpline *next_spline = spline->next;
+       MaskSpline *mask_spline;
 
-               BLI_remlink(&masklay->splines, spline);
-               BKE_mask_spline_free(spline);
-
-               spline = next_spline;
+       for (mask_spline = mask_layer->splines.first;
+            mask_spline;
+            mask_spline = mask_spline->next)
+       {
+               if (mask_spline->points_deform) {
+                       int i;
+                       MaskSplinePoint *points_deform = mask_spline->points_deform;
+                       for (i = 0; i < mask_spline->tot_point; i++) {
+                               BKE_mask_point_free(&points_deform[i]);
+                       }
+                       MEM_freeN(points_deform);
+                       mask_spline->points_deform = NULL;
+               }
        }
+}
+
+void BKE_mask_layer_free(MaskLayer *masklay)
+{
+       /* free splines */
+       BKE_mask_spline_free_list(&masklay->splines);
 
        /* free animation data */
        BKE_mask_layer_free_shapes(masklay);
@@ -1072,7 +1095,7 @@ void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], cons
        BKE_mask_coord_to_frame(r_co, co, frame_size);
 }
 
-static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[2])
+static int mask_evaluate_parent(MaskParent *parent, float ctime, float orig_co[2], float r_co[2])
 {
        if (!parent)
                return FALSE;
@@ -1084,18 +1107,38 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[
                        MovieTrackingObject *ob = BKE_tracking_object_get_named(tracking, parent->parent);
 
                        if (ob) {
-                               MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, ob, parent->sub_parent);
+                               MovieClipUser user = {0};
                                float clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
+                               BKE_movieclip_user_set_frame(&user, ctime);
 
-                               MovieClipUser user = {0};
-                               user.framenr = ctime;
+                               if (parent->type == MASK_PARENT_POINT_TRACK) {
+                                       MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, ob, parent->sub_parent);
 
-                               if (track) {
-                                       float marker_pos_ofs[2];
-                                       BKE_tracking_marker_get_subframe_position(track, clip_framenr, marker_pos_ofs);
-                                       BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs);
+                                       if (track) {
+                                               float marker_pos_ofs[2];
+                                               BKE_tracking_marker_get_subframe_position(track, clip_framenr, marker_pos_ofs);
+                                               BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs);
 
-                                       return TRUE;
+                                               return TRUE;
+                                       }
+                               }
+                               else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+                                       MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, ob, parent->sub_parent);
+
+                                       if (plane_track) {
+                                               MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+                                               float H[3][3], vec[3], warped[3];
+
+                                               BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, plane_marker->corners, H);
+
+                                               BKE_mask_coord_to_movieclip(clip, &user, vec, orig_co);
+                                               vec[2] = 1.0f;
+                                               mul_v3_m3v3(warped, H, vec);
+                                               warped[0] /= warped[2];
+                                               warped[1] /= warped[2];
+
+                                               BKE_mask_coord_from_movieclip(clip, &user, r_co, warped);
+                                       }
                                }
                        }
                }
@@ -1104,17 +1147,26 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[
        return FALSE;
 }
 
-/* could make external but for now its only used internally */
-static int mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2])
+static void mask_evaluate_apply_point_parent(MaskSplinePoint *point, float ctime)
 {
-       float parent_co[2];
+       MaskParent *parent = &point->parent;
+
+       if (parent->type == MASK_PARENT_POINT_TRACK) {
+               float parent_co[2];
 
-       if (BKE_mask_evaluate_parent(parent, ctime, parent_co)) {
-               sub_v2_v2v2(r_delta, parent_co, parent->parent_orig);
-               return TRUE;
+               if (mask_evaluate_parent(parent, ctime, NULL, parent_co)) {
+                       float delta[2];
+                       sub_v2_v2v2(delta, parent_co, parent->parent_orig);
+
+                       add_v2_v2(point->bezt.vec[0], delta);
+                       add_v2_v2(point->bezt.vec[1], delta);
+                       add_v2_v2(point->bezt.vec[2], delta);
+               }
        }
-       else {
-               return FALSE;
+       else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+               mask_evaluate_parent(parent, ctime, point->bezt.vec[0], point->bezt.vec[0]);
+               mask_evaluate_parent(parent, ctime, point->bezt.vec[1], point->bezt.vec[1]);
+               mask_evaluate_parent(parent, ctime, point->bezt.vec[2], point->bezt.vec[2]);
        }
 }
 
@@ -1438,18 +1490,13 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do
                        for (i = 0; i < spline->tot_point; i++) {
                                MaskSplinePoint *point = &spline->points[i];
                                MaskSplinePoint *point_deform = &spline->points_deform[i];
-                               float delta[2];
 
                                BKE_mask_point_free(point_deform);
 
                                *point_deform = *point;
                                point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL;
 
-                               if (mask_evaluate_parent_delta(&point->parent, ctime, delta)) {
-                                       add_v2_v2(point_deform->bezt.vec[0], delta);
-                                       add_v2_v2(point_deform->bezt.vec[1], delta);
-                                       add_v2_v2(point_deform->bezt.vec[2], delta);
-                               }
+                               mask_evaluate_apply_point_parent(point_deform, ctime);
 
                                if (ELEM(point->bezt.h1, HD_AUTO, HD_VECT)) {
                                        need_handle_recalc = TRUE;
index 5001aa01653e5b06dd75287db4bd448c50d3c387..1349c4dc8d4f73312deb33e75e0d5f8c7372ffaa 100644 (file)
@@ -3391,6 +3391,7 @@ static void registerCompositNodes(void)
 
        register_node_type_cmp_mask();
        register_node_type_cmp_trackpos();
+       register_node_type_cmp_planetrackdeform();
 }
 
 static void registerShaderNodes(void) 
index 4c3632928984804bb8b3fb6ac037a923b8be717d..54ba9ea56d7101904ddf1a22ecc4922a791799b3 100644 (file)
@@ -103,6 +103,18 @@ static void tracking_tracks_free(ListBase *tracks)
        BLI_freelistN(tracks);
 }
 
+/* Free the whole list of plane tracks, list's head and tail are set to NULL. */
+static void tracking_plane_tracks_free(ListBase *plane_tracks)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks->first; plane_track; plane_track = plane_track->next) {
+               BKE_tracking_plane_track_free(plane_track);
+       }
+
+       BLI_freelistN(plane_tracks);
+}
+
 /* Free reconstruction structures, only frees contents of a structure,
  * (if structure is allocated in heap, it shall be handled outside).
  *
@@ -122,6 +134,7 @@ static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruc
 static void tracking_object_free(MovieTrackingObject *object)
 {
        tracking_tracks_free(&object->tracks);
+       tracking_plane_tracks_free(&object->plane_tracks);
        tracking_reconstruction_free(&object->reconstruction);
 }
 
@@ -173,6 +186,7 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
 void BKE_tracking_free(MovieTracking *tracking)
 {
        tracking_tracks_free(&tracking->tracks);
+       tracking_plane_tracks_free(&tracking->plane_tracks);
        tracking_reconstruction_free(&tracking->reconstruction);
        tracking_objects_free(&tracking->objects);
 
@@ -221,6 +235,18 @@ ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
        return &tracking->tracks;
 }
 
+/* Get list base of active object's plane tracks. */
+ListBase *BKE_tracking_get_active_plane_tracks(MovieTracking *tracking)
+{
+       MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+
+       if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+               return &object->plane_tracks;
+       }
+
+       return &tracking->plane_tracks;
+}
+
 /* Get reconstruction data of active object. */
 MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking)
 {
@@ -1025,6 +1051,17 @@ void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area)
        BKE_tracking_track_flag_clear(track, area, SELECT);
 }
 
+void BKE_tracking_tracks_deselect_all(ListBase *tracksbase)
+{
+       MovieTrackingTrack *track;
+
+       for (track = tracksbase->first; track; track = track->next) {
+               if ((track->flag & TRACK_HIDDEN) == 0) {
+                       BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+               }
+       }
+}
+
 /*********************** Marker *************************/
 
 MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker)
@@ -1264,6 +1301,296 @@ void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float
        add_v2_v2(pos, track->offset);
 }
 
+/*********************** Plane Track *************************/
+
+/* Creates new plane track out of selected point tracks */
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, ListBase *plane_tracks_base,
+                                                      ListBase *tracks, int framenr)
+{
+       MovieTrackingPlaneTrack *plane_track;
+       MovieTrackingPlaneMarker plane_marker;
+       MovieTrackingTrack *track;
+       float tracks_min[2], tracks_max[2];
+       int track_index, num_selected_tracks = 0;
+
+       (void) tracking;  /* Ignored. */
+
+       /* Use bounding box of selected markers as an initial size of plane. */
+       INIT_MINMAX2(tracks_min, tracks_max);
+       for (track = tracks->first; track; track = track->next) {
+               if (TRACK_SELECTED(track)) {
+                       MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+                       float pattern_min[2], pattern_max[2];
+                       BKE_tracking_marker_pattern_minmax(marker, pattern_min, pattern_max);
+                       add_v2_v2(pattern_min, marker->pos);
+                       add_v2_v2(pattern_max, marker->pos);
+                       minmax_v2v2_v2(tracks_min, tracks_max, pattern_min);
+                       minmax_v2v2_v2(tracks_min, tracks_max, pattern_max);
+                       num_selected_tracks++;
+               }
+       }
+
+       if (num_selected_tracks < 4) {
+               return NULL;
+       }
+
+       /* Allocate new plane track. */
+       plane_track = MEM_callocN(sizeof(MovieTrackingPlaneTrack), "new plane track");
+
+       /* Use some default name. */
+       strcpy(plane_track->name, "Plane Track");
+
+       /* Use selected tracks from given list as a plane. */
+       plane_track->point_tracks = MEM_mallocN(sizeof(MovieTrackingTrack *) * num_selected_tracks, "new plane tracks array");
+       for (track = tracks->first, track_index = 0; track; track = track->next) {
+               if (TRACK_SELECTED(track)) {
+                       plane_track->point_tracks[track_index] = track;
+                       track_index++;
+               }
+       }
+       plane_track->point_tracksnr = num_selected_tracks;
+
+       /* Setup new plane marker and add it to the track. */
+       plane_marker.framenr = framenr;
+       plane_marker.flag = 0;
+
+       copy_v2_v2(plane_marker.corners[0], tracks_min);
+       copy_v2_v2(plane_marker.corners[2], tracks_max);
+
+       plane_marker.corners[1][0] = tracks_max[0];
+       plane_marker.corners[1][1] = tracks_min[1];
+       plane_marker.corners[3][0] = tracks_min[0];
+       plane_marker.corners[3][1] = tracks_max[1];
+
+       BKE_tracking_plane_marker_insert(plane_track, &plane_marker);
+
+       /* Put new plane track to the list, ensure it's name is unique. */
+       BLI_addtail(plane_tracks_base, plane_track);
+       BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
+
+       return plane_track;
+}
+
+void BKE_tracking_plane_track_unique_name(ListBase *plane_tracks_base, MovieTrackingPlaneTrack *plane_track)
+{
+       BLI_uniquename(plane_tracks_base, plane_track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Plane Track"), '.',
+                      offsetof(MovieTrackingPlaneTrack, name), sizeof(plane_track->name));
+}
+
+/* Free specified plane track, only frees contents of a structure
+ * (if track is allocated in heap, it shall be handled outside).
+ *
+ * All the pointers inside track becomes invalid after this call.
+ */
+void BKE_tracking_plane_track_free(MovieTrackingPlaneTrack *plane_track)
+{
+       if (plane_track->markers) {
+               MEM_freeN(plane_track->markers);
+       }
+
+       MEM_freeN(plane_track->point_tracks);
+}
+
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *tracking,
+                                                            MovieTrackingObject *object,
+                                                            const char *name)
+{
+       ListBase *plane_tracks_base = BKE_tracking_object_get_plane_tracks(tracking, object);
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (!strcmp(plane_track->name, name)) {
+                       return plane_track;
+               }
+       }
+
+       return NULL;
+}
+
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking)
+{
+       ListBase *plane_tracks_base;
+
+       if (tracking->act_plane_track == NULL) {
+               return NULL;
+       }
+
+       plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+
+       /* Check that active track is in current plane tracks list */
+       if (BLI_findindex(plane_tracks_base, tracking->act_plane_track) >= 0) {
+               return tracking->act_plane_track;
+       }
+
+       return NULL;
+}
+
+void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+               plane_track->flag &= ~SELECT;
+       }
+}
+
+/*********************** Plane Marker *************************/
+
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track,
+                                                           MovieTrackingPlaneMarker *plane_marker)
+{
+       MovieTrackingPlaneMarker *old_plane_marker = NULL;
+
+       if (plane_track->markersnr)
+               old_plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, plane_marker->framenr);
+
+       if (old_plane_marker) {
+               /* Simply replace settings in existing marker. */
+               *old_plane_marker = *plane_marker;
+
+               return old_plane_marker;
+       }
+       else {
+               int a = plane_track->markersnr;
+
+               /* Find position in array where to add new marker. */
+               /* TODO(sergey): we coud use bisect to speed things up. */
+               while (a--) {
+                       if (plane_track->markers[a].framenr < plane_marker->framenr) {
+                               break;
+                       }
+               }
+
+               plane_track->markersnr++;
+               plane_track->markers = MEM_reallocN(plane_track->markers,
+                                                   sizeof(MovieTrackingPlaneMarker) * plane_track->markersnr);
+
+               /* Shift array to "free" space for new marker. */
+               memmove(plane_track->markers + a + 2, plane_track->markers + a + 1,
+                       (plane_track->markersnr - a - 2) * sizeof(MovieTrackingPlaneMarker));
+
+               /* Put new marker to an array. */
+               plane_track->markers[a + 1] = *plane_marker;
+               plane_track->last_marker = a + 1;
+
+               return &plane_track->markers[a + 1];
+       }
+}
+
+void BKE_tracking_plane_marker_delete(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       int a = 0;
+
+       while (a < plane_track->markersnr) {
+               if (plane_track->markers[a].framenr == framenr) {
+                       if (plane_track->markersnr > 1) {
+                               memmove(plane_track->markers + a, plane_track->markers + a + 1,
+                                       (plane_track->markersnr - a - 1) * sizeof(MovieTrackingPlaneMarker));
+                               plane_track->markersnr--;
+                               plane_track->markers = MEM_reallocN(plane_track->markers,
+                                                                   sizeof(MovieTrackingMarker) * plane_track->markersnr);
+                       }
+                       else {
+                               MEM_freeN(plane_track->markers);
+                               plane_track->markers = NULL;
+                               plane_track->markersnr = 0;
+                       }
+
+                       break;
+               }
+
+               a++;
+       }
+}
+
+/* TODO(sergey): The next couple of functions are really quite the same as point marker version,
+ *               would be nice to de-duplicate them somehow..
+ */
+
+/* Get a plane marker at given frame,
+ * If there's no such marker, closest one from the left side will be returned.
+ */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       int a = plane_track->markersnr - 1;
+
+       if (!plane_track->markersnr)
+               return NULL;
+
+       /* Approximate pre-first framenr marker with first marker. */
+       if (framenr < plane_track->markers[0].framenr) {
+               return &plane_track->markers[0];
+       }
+
+       if (plane_track->last_marker < plane_track->markersnr) {
+               a = plane_track->last_marker;
+       }
+
+       if (plane_track->markers[a].framenr <= framenr) {
+               while (a < plane_track->markersnr && plane_track->markers[a].framenr <= framenr) {
+                       if (plane_track->markers[a].framenr == framenr) {
+                               plane_track->last_marker = a;
+
+                               return &plane_track->markers[a];
+                       }
+                       a++;
+               }
+
+               /* If there's no marker for exact position, use nearest marker from left side. */
+               return &plane_track->markers[a - 1];
+       }
+       else {
+               while (a >= 0 && plane_track->markers[a].framenr >= framenr) {
+                       if (plane_track->markers[a].framenr == framenr) {
+                               plane_track->last_marker = a;
+
+                               return &plane_track->markers[a];
+                       }
+
+                       a--;
+               }
+
+               /* If there's no marker for exact position, use nearest marker from left side. */
+               return &plane_track->markers[a];
+       }
+
+       return NULL;
+}
+
+/* Get a plane marker at exact given frame, if there's no marker at the frame,
+ * NULL will be returned.
+ */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+       if (plane_marker->framenr != framenr) {
+               return NULL;
+       }
+
+       return plane_marker;
+}
+
+/* Ensure there's a marker for the given frame. */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+       if (plane_marker->framenr != framenr) {
+               MovieTrackingPlaneMarker plane_marker_new;
+
+               plane_marker_new = *plane_marker;
+               plane_marker_new.framenr = framenr;
+
+               plane_marker = BKE_tracking_plane_marker_insert(plane_track, &plane_marker_new);
+       }
+
+       return plane_marker;
+}
+
 /*********************** Object *************************/
 
 MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name)
@@ -1379,6 +1706,15 @@ ListBase *BKE_tracking_object_get_tracks(MovieTracking *tracking, MovieTrackingO
        return &object->tracks;
 }
 
+ListBase *BKE_tracking_object_get_plane_tracks(MovieTracking *tracking, MovieTrackingObject *object)
+{
+       if (object->flag & TRACKING_OBJECT_CAMERA) {
+               return &tracking->plane_tracks;
+       }
+
+       return &object->plane_tracks;
+}
+
 MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(MovieTracking *tracking,
                                                                     MovieTrackingObject *object)
 {
@@ -2528,7 +2864,7 @@ static bool track_context_update_reference(MovieTrackingContext *context, TrackC
 }
 
 /* Fill in libmv tracker options structure with settings need to be used to perform track. */
-static void tracking_configure_tracker(MovieTrackingTrack *track, float *mask,
+static void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
                                        libmv_TrackRegionOptions *options)
 {
        options->motion_model = track->motion_model;
@@ -2863,6 +3199,147 @@ void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, Movi
        IMB_freeImBuf(destination_ibuf);
 }
 
+/*********************** Plane tracking *************************/
+
+typedef double Vec2[2];
+
+static int point_markers_correspondences_on_both_image(MovieTrackingPlaneTrack *plane_track, int frame1, int frame2,
+                                                       Vec2 **x1_r, Vec2 **x2_r)
+{
+       int i, correspondence_index;
+       Vec2 *x1, *x2;
+
+       *x1_r = x1 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x1");
+       *x2_r = x2 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x2");
+
+       for (i = 0, correspondence_index = 0; i < plane_track->point_tracksnr; i++) {
+               MovieTrackingTrack *point_track = plane_track->point_tracks[i];
+               MovieTrackingMarker *point_marker1, *point_marker2;
+
+               point_marker1 = BKE_tracking_marker_get_exact(point_track, frame1);
+               point_marker2 = BKE_tracking_marker_get_exact(point_track, frame2);
+
+               if (point_marker1 != NULL && point_marker2 != NULL) {
+                       /* Here conversion from float to double happens. */
+                       x1[correspondence_index][0] = point_marker1->pos[0];
+                       x1[correspondence_index][1] = point_marker1->pos[1];
+
+                       x2[correspondence_index][0] = point_marker2->pos[0];
+                       x2[correspondence_index][1] = point_marker2->pos[1];
+
+                       correspondence_index++;
+               }
+       }
+
+       return correspondence_index;
+}
+
+/* TODO(sergey): Make it generic function available for everyone. */
+BLI_INLINE void mat3f_from_mat3d(float mat_float[3][3], double mat_double[3][3])
+{
+       /* Keep it stupid simple for better data flow in CPU. */
+       mat_float[0][0] = mat_double[0][0];
+       mat_float[0][1] = mat_double[0][1];
+       mat_float[0][2] = mat_double[0][2];
+
+       mat_float[1][0] = mat_double[1][0];
+       mat_float[1][1] = mat_double[1][1];
+       mat_float[1][2] = mat_double[1][2];
+
+       mat_float[2][0] = mat_double[2][0];
+       mat_float[2][1] = mat_double[2][1];
+       mat_float[2][2] = mat_double[2][2];
+}
+
+/* NOTE: frame number should be in clip space, not scene space */
+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 new_plane_marker;
+       int current_frame, frame_delta = direction > 0 ? 1 : -1;
+
+       new_plane_marker = *start_plane_marker;
+       new_plane_marker.flag |= PLANE_MARKER_TRACKED;
+
+       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);
+               Vec2 *x1, *x2;
+               int i, num_correspondences;
+               double H_double[3][3];
+               float H[3][3];
+
+               /* 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;
+               }
+
+               num_correspondences =
+                       point_markers_correspondences_on_both_image(plane_track, current_frame, current_frame + frame_delta,
+                                                                   &x1, &x2);
+
+               if (num_correspondences < 4) {
+                       MEM_freeN(x1);
+                       MEM_freeN(x2);
+
+                       break;
+               }
+
+               libmv_homography2DFromCorrespondencesLinear(x1, x2, num_correspondences, H_double, 1e-8);
+
+               mat3f_from_mat3d(H, H_double);
+
+               for (i = 0; i < 4; i++) {
+                       float vec[3] = {0.0f, 0.0f, 1.0f}, vec2[3];
+                       copy_v2_v2(vec, new_plane_marker.corners[i]);
+
+                       /* Apply homography */
+                       mul_v3_m3v3(vec2, H, vec);
+
+                       /* Normalize. */
+                       vec2[0] /= vec2[2];
+                       vec2[1] /= vec2[2];
+
+                       copy_v2_v2(new_plane_marker.corners[i], vec2);
+               }
+
+               new_plane_marker.framenr = current_frame + frame_delta;
+
+               BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker);
+
+               MEM_freeN(x1);
+               MEM_freeN(x2);
+       }
+}
+
+/* NOTE: frame number should be in clip space, not scene space */
+void BKE_tracking_track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track, int start_frame)
+{
+       track_plane_from_existing_motion(plane_track, start_frame, 1);
+       track_plane_from_existing_motion(plane_track, start_frame, -1);
+}
+
+BLI_INLINE void float_corners_to_double(/*const*/ float corners[4][2], double double_corners[4][2])
+{
+       copy_v2db_v2fl(double_corners[0], corners[0]);
+       copy_v2db_v2fl(double_corners[1], corners[1]);
+       copy_v2db_v2fl(double_corners[2], corners[2]);
+       copy_v2db_v2fl(double_corners[3], corners[3]);
+}
+
+void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners[4][2], /*const*/ float corners[4][2], float H[3][3])
+{
+       Vec2 x1[4], x2[4];
+       double H_double[3][3];
+
+       float_corners_to_double(reference_corners, x1);
+       float_corners_to_double(corners, x2);
+
+       libmv_homography2DFromCorrespondencesLinear(x1, x2, 4, H_double, 1e-8);
+
+       mat3f_from_mat3d(H, H_double);
+}
+
 /*********************** Camera solving *************************/
 
 typedef struct MovieReconstructContext {
@@ -3264,7 +3741,6 @@ static void reconstruct_update_solve_cb(void *customdata, double progress, const
 
        BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message);
 }
-
 /* FIll in camera intrinsics structure from reconstruction context. */
 static void camraIntrincicsOptionsFromContext(libmv_CameraIntrinsicsOptions *camera_intrinsics_options,
                                               MovieReconstructContext *context)
index 22ab7e499736d74c86c498a262cf5ce4c33e7eac..37cebc3063d82adac465505a534a37fd064a6dbb 100644 (file)
@@ -6687,6 +6687,28 @@ static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase)
        }
 }
 
+static void direct_link_moviePlaneTracks(FileData *fd, ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       link_list(fd, plane_tracks_base);
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               int i;
+
+               plane_track->point_tracks = newdataadr(fd, plane_track->point_tracks);
+
+               for (i = 0; i < plane_track->point_tracksnr; i++) {
+                       plane_track->point_tracks[i] = newdataadr(fd, plane_track->point_tracks[i]);
+               }
+
+               plane_track->markers = newdataadr(fd, plane_track->markers);
+       }
+}
+
 static void direct_link_movieclip(FileData *fd, MovieClip *clip)
 {
        MovieTracking *tracking = &clip->tracking;
@@ -6701,9 +6723,11 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
        else clip->tracking.camera.intrinsics = NULL;
 
        direct_link_movieTracks(fd, &tracking->tracks);
+       direct_link_moviePlaneTracks(fd, &tracking->plane_tracks);
        direct_link_movieReconstruction(fd, &tracking->reconstruction);
 
        clip->tracking.act_track = newdataadr(fd, clip->tracking.act_track);
+       clip->tracking.act_plane_track = newdataadr(fd, clip->tracking.act_plane_track);
 
        clip->anim = NULL;
        clip->tracking_context = NULL;
@@ -6720,6 +6744,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
        
        for (object = tracking->objects.first; object; object = object->next) {
                direct_link_movieTracks(fd, &object->tracks);
+               direct_link_moviePlaneTracks(fd, &object->plane_tracks);
                direct_link_movieReconstruction(fd, &object->reconstruction);
        }
 }
index 4f0ccd3c62652fb7acdb181286bf1dea43835765..f3d58c42bc8d8126015968fba40d1447d7bae904 100644 (file)
@@ -2920,6 +2920,21 @@ static void write_movieTracks(WriteData *wd, ListBase *tracks)
        }
 }
 
+static void write_moviePlaneTracks(WriteData *wd, ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               writestruct(wd, DATA, "MovieTrackingPlaneTrack", 1, plane_track);
+
+               writedata(wd, DATA, sizeof(MovieTrackingTrack *) * plane_track->point_tracksnr, plane_track->point_tracks);
+               writestruct(wd, DATA, "MovieTrackingPlaneMarker", plane_track->markersnr, plane_track->markers);
+       }
+}
+
 static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction)
 {
        if (reconstruction->camnr)
@@ -2944,6 +2959,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
                                write_animdata(wd, clip->adt);
 
                        write_movieTracks(wd, &tracking->tracks);
+                       write_moviePlaneTracks(wd, &tracking->plane_tracks);
                        write_movieReconstruction(wd, &tracking->reconstruction);
 
                        object= tracking->objects.first;
@@ -2951,6 +2967,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
                                writestruct(wd, DATA, "MovieTrackingObject", 1, object);
 
                                write_movieTracks(wd, &object->tracks);
+                               write_moviePlaneTracks(wd, &object->plane_tracks);
                                write_movieReconstruction(wd, &object->reconstruction);
 
                                object= object->next;
index c1b99274bed0d877c7af509add1494653434705e..a119a89c842852f9ba29a063477789006d0c11e1 100644 (file)
@@ -184,6 +184,9 @@ set(SRC
        nodes/COM_GlareNode.cpp
        nodes/COM_GlareNode.h
 
+       nodes/COM_PlaneTrackDeformNode.cpp
+       nodes/COM_PlaneTrackDeformNode.h
+
        nodes/COM_CropNode.cpp
        nodes/COM_CropNode.h
        operations/COM_CropOperation.cpp
@@ -595,6 +598,12 @@ set(SRC
        operations/COM_ProjectorLensDistortionOperation.h
        operations/COM_ScreenLensDistortionOperation.cpp
        operations/COM_ScreenLensDistortionOperation.h
+       operations/COM_PlaneTrackCommonOperation.cpp
+       operations/COM_PlaneTrackCommonOperation.h
+       operations/COM_PlaneTrackMaskOperation.cpp
+       operations/COM_PlaneTrackMaskOperation.h
+       operations/COM_PlaneTrackWarpImageOperation.cpp
+       operations/COM_PlaneTrackWarpImageOperation.h
 
        #Filter operations
        operations/COM_ConvolutionFilterOperation.h
index 80ae952b87f6d72037b0db95a902cf9058d2f70f..db0cdd1692e2b160f477fb4a3f2b4cc21b8a8a8d 100644 (file)
 #include "COM_ViewerNode.h"
 #include "COM_ZCombineNode.h"
 #include "COM_PixelateNode.h"
+#include "COM_PlaneTrackDeformNode.h"
 
 Node *Converter::convert(bNode *b_node, bool fast)
 {
@@ -402,6 +403,9 @@ Node *Converter::convert(bNode *b_node, bool fast)
                case CMP_NODE_PIXELATE:
                        node = new PixelateNode(b_node);
                        break;
+               case CMP_NODE_PLANETRACKDEFORM:
+                       node = new PlaneTrackDeformNode(b_node);
+                       break;
                default:
                        node = new MuteNode(b_node);
                        break;
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
new file mode 100644 (file)
index 0000000..d6434c2
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Jeroen Bakker
+ *             Monique Dewanchand
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackDeformNode.h"
+#include "COM_ExecutionSystem.h"
+
+#include "COM_PlaneTrackMaskOperation.h"
+#include "COM_PlaneTrackWarpImageOperation.h"
+
+extern "C" {
+       #include "BKE_node.h"
+       #include "BKE_movieclip.h"
+       #include "BKE_tracking.h"
+}
+
+PlaneTrackDeformNode::PlaneTrackDeformNode(bNode *editorNode) : Node(editorNode)
+{
+       /* pass */
+}
+
+void PlaneTrackDeformNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
+{
+       InputSocket *input_image = this->getInputSocket(0);
+
+       OutputSocket *output_warped_image = this->getOutputSocket(0);
+       OutputSocket *output_plane = this->getOutputSocket(1);
+
+       bNode *editorNode = this->getbNode();
+       MovieClip *clip = (MovieClip *) editorNode->id;
+
+       NodePlaneTrackDeformData *data = (NodePlaneTrackDeformData *) editorNode->storage;
+
+       int frame_number = context->getFramenumber();
+
+       if (output_warped_image->isConnected()) {
+               PlaneTrackWarpImageOperation *warp_image_operation = new PlaneTrackWarpImageOperation();
+
+               warp_image_operation->setMovieClip(clip);
+               warp_image_operation->setTrackingObject(data->tracking_object);
+               warp_image_operation->setPlaneTrackName(data->plane_track_name);
+               warp_image_operation->setFramenumber(frame_number);
+
+               input_image->relinkConnections(warp_image_operation->getInputSocket(0), 0, graph);
+               output_warped_image->relinkConnections(warp_image_operation->getOutputSocket());
+
+               graph->addOperation(warp_image_operation);
+       }
+
+       if (output_plane->isConnected()) {
+               PlaneTrackMaskOperation *plane_mask_operation = new PlaneTrackMaskOperation();
+
+               plane_mask_operation->setMovieClip(clip);
+               plane_mask_operation->setTrackingObject(data->tracking_object);
+               plane_mask_operation->setPlaneTrackName(data->plane_track_name);
+               plane_mask_operation->setFramenumber(frame_number);
+
+               output_plane->relinkConnections(plane_mask_operation->getOutputSocket());
+
+               graph->addOperation(plane_mask_operation);
+       }
+}
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
new file mode 100644 (file)
index 0000000..cf173cd
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Sergey Sharybin
+ */
+
+#include "COM_Node.h"
+#include "DNA_node_types.h"
+
+extern "C" {
+       #include "DNA_movieclip_types.h"
+       #include "DNA_node_types.h"
+}
+
+/**
+ * @brief PlaneTrackDeformNode
+ * @ingroup Node
+ */
+class PlaneTrackDeformNode : public Node {
+public:
+       PlaneTrackDeformNode(bNode *editorNode);
+       void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
+};
diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp
new file mode 100644 (file)
index 0000000..51e803f
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackMaskOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+       #include "BKE_movieclip.h"
+       #include "BKE_node.h"
+       #include "BKE_tracking.h"
+}
+
+PlaneTrackCommonOperation::PlaneTrackCommonOperation() : NodeOperation()
+{
+       this->m_movieClip = NULL;
+       this->m_framenumber = 0;
+       this->m_trackingObjectName[0] = '\0';
+       this->m_planeTrackName[0] = '\0';
+}
+
+void PlaneTrackCommonOperation::initExecution()
+{
+       MovieTracking *tracking;
+       MovieTrackingObject *object;
+
+       memset(this->m_corners, 0, sizeof(this->m_corners));
+       memset(this->m_frameSpaceCorners, 0, sizeof(this->m_frameSpaceCorners));
+
+       if (!this->m_movieClip)
+               return;
+
+       tracking = &this->m_movieClip->tracking;
+
+       object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName);
+       if (object) {
+               MovieTrackingPlaneTrack *plane_track;
+
+               plane_track = BKE_tracking_plane_track_get_named(tracking, object, this->m_planeTrackName);
+
+               if (plane_track) {
+                       MovieTrackingPlaneMarker *plane_marker;
+                       int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
+
+                       plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+                       memcpy(this->m_corners, plane_marker->corners, sizeof(this->m_corners));
+               }
+       }
+
+       for (int i = 0; i < 4; i++) {
+               this->m_frameSpaceCorners[i][0] = this->m_corners[i][0] * this->getWidth();
+               this->m_frameSpaceCorners[i][1] = this->m_corners[i][1] * this->getHeight();
+       }
+}
+
+void PlaneTrackCommonOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+       NodeOperation::determineResolution(resolution, preferredResolution);
+
+       resolution[0] = 0;
+       resolution[1] = 0;
+
+       if (this->m_movieClip) {
+               int width, height;
+               MovieClipUser user = {0};
+
+               BKE_movieclip_user_set_frame(&user, this->m_framenumber);
+               BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height);
+
+               resolution[0] = width;
+               resolution[1] = height;
+       }
+}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h
new file mode 100644 (file)
index 0000000..705bdf4
--- /dev/null
@@ -0,0 +1,62 @@
+
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Sergey Sharybin
+ */
+
+#ifndef _COM_PlaneTrackCommonOperation_h
+#define _COM_PlaneTrackCommonOperation_h
+
+#include <string.h>
+
+#include "COM_NodeOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackCommonOperation : public NodeOperation {
+protected:
+       MovieClip *m_movieClip;
+       int m_framenumber;
+       char m_trackingObjectName[64];
+       char m_planeTrackName[64];
+
+       float m_corners[4][2];            /* Corners coordinates in normalized space. */
+       float m_frameSpaceCorners[4][2];  /* Corners coordinates in pixel space. */
+
+       /**
+        * Determine the output resolution. The resolution is retrieved from the Renderer
+        */
+       void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
+public:
+       PlaneTrackCommonOperation();
+
+       void setMovieClip(MovieClip *clip) {this->m_movieClip = clip;}
+       void setTrackingObject(char *object) { BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); }
+       void setPlaneTrackName(char *plane_track) { BLI_strncpy(this->m_planeTrackName, plane_track, sizeof(this->m_planeTrackName)); }
+       void setFramenumber(int framenumber) {this->m_framenumber = framenumber;}
+
+       void initExecution();
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp
new file mode 100644 (file)
index 0000000..fe794cb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackMaskOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+       #include "BLI_jitter.h"
+
+       #include "BKE_movieclip.h"
+       #include "BKE_node.h"
+       #include "BKE_tracking.h"
+}
+
+PlaneTrackMaskOperation::PlaneTrackMaskOperation() : PlaneTrackCommonOperation()
+{
+       this->addOutputSocket(COM_DT_VALUE);
+}
+
+void PlaneTrackMaskOperation::initExecution()
+{
+       PlaneTrackCommonOperation::initExecution();
+
+       const int osa = 8;
+       this->m_osa = osa;
+       BLI_jitter_init(this->m_jitter[0], osa);
+}
+
+void PlaneTrackMaskOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       float point[2];
+
+       int inside_counter = 0;
+       for (int sample = 0; sample < this->m_osa; sample++) {
+               point[0] = x + this->m_jitter[sample][0];
+               point[1] = y + this->m_jitter[sample][1];
+
+               if (isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) ||
+                   isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3]))
+               {
+                       inside_counter++;
+               }
+       }
+
+       output[0] = (float) inside_counter / this->m_osa;
+}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h
new file mode 100644 (file)
index 0000000..db32f98
--- /dev/null
@@ -0,0 +1,49 @@
+
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Sergey Sharybin
+ */
+
+#ifndef _COM_PlaneTrackMaskOperation_h
+#define _COM_PlaneTrackMaskOperation_h
+
+#include <string.h>
+
+#include "COM_PlaneTrackCommonOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackMaskOperation : public PlaneTrackCommonOperation {
+protected:
+       int m_osa;
+       float m_jitter[32][2];
+
+public:
+       PlaneTrackMaskOperation();
+
+       void initExecution();
+
+       void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
new file mode 100644 (file)
index 0000000..9bbf456
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackWarpImageOperation.h"
+#include "COM_ReadBufferOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+       #include "BLI_jitter.h"
+
+       #include "BKE_movieclip.h"
+       #include "BKE_node.h"
+       #include "BKE_tracking.h"
+}
+
+BLI_INLINE bool isPointInsideQuad(const float x, const float y, const float corners[4][2])
+{
+       float point[2];
+
+       point[0] = x;
+       point[1] = y;
+
+       return isect_point_tri_v2(point, corners[0], corners[1], corners[2]) ||
+              isect_point_tri_v2(point, corners[0], corners[2], corners[3]);
+}
+
+BLI_INLINE bool resolveUV(const float x, const float y, const float corners[4][2], float uv[2])
+{
+       float point[2];
+       bool inside;
+
+       inside = isPointInsideQuad(x, y, corners);
+
+       point[0] = x;
+       point[1] = y;
+
+       /* Use reverse bilinear to get UV coordinates within original frame */
+       resolve_quad_uv(uv, point, corners[0], corners[1], corners[2], corners[3]);
+
+       return inside;
+}
+
+BLI_INLINE void resolveUVAndDxDy(const float x, const float y, const float corners[4][2],
+                                 float *u_r, float *v_r, float *dx_r, float *dy_r)
+{
+       float inputUV[2];
+       float uv_a[2], uv_b[2];
+
+       float dx, dy;
+       float uv_l, uv_r;
+       float uv_u, uv_d;
+
+       bool ok1, ok2;
+
+       resolveUV(x, y, corners, inputUV);
+
+       /* adaptive sampling, red (U) channel */
+       ok1 = resolveUV(x - 1, y, corners, uv_a);
+       ok2 = resolveUV(x + 1, y, corners, uv_b);
+       uv_l = ok1 ? fabsf(inputUV[0] - uv_a[0]) : 0.0f;
+       uv_r = ok2 ? fabsf(inputUV[0] - uv_b[0]) : 0.0f;
+
+       dx = 0.5f * (uv_l + uv_r);
+
+       /* adaptive sampling, green (V) channel */
+       ok1 = resolveUV(x, y - 1, corners, uv_a);
+       ok2 = resolveUV(x, y + 1, corners, uv_b);
+       uv_u = ok1 ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
+       uv_d = ok2 ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
+
+       dy = 0.5f * (uv_u + uv_d);
+
+       /* more adaptive sampling, red and green (UV) channels */
+       ok1 = resolveUV(x - 1, y - 1, corners, uv_a);
+       ok2 = resolveUV(x - 1, y + 1, corners, uv_b);
+       uv_l = ok1 ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
+       uv_r = ok2 ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
+       uv_u = ok1 ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
+       uv_d = ok2 ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
+
+       dx += 0.25f * (uv_l + uv_r);
+       dy += 0.25f * (uv_u + uv_d);
+
+       ok1 = resolveUV(x + 1, y - 1, corners, uv_a);
+       ok2 = resolveUV(x + 1, y + 1, corners, uv_b);
+       uv_l = ok1 ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
+       uv_r = ok2 ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
+       uv_u = ok1 ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
+       uv_d = ok2 ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
+
+       dx += 0.25f * (uv_l + uv_r);
+       dy += 0.25f * (uv_u + uv_d);
+
+       /* should use mipmap */
+       *dx_r = min(dx, 0.2f);
+       *dy_r = min(dy, 0.2f);
+
+       *u_r = inputUV[0];
+       *v_r = inputUV[1];
+}
+
+PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonOperation()
+{
+       this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
+       this->addOutputSocket(COM_DT_COLOR);
+       this->m_pixelReader = NULL;
+       this->setComplex(true);
+}
+
+void PlaneTrackWarpImageOperation::initExecution()
+{
+       PlaneTrackCommonOperation::initExecution();
+
+       this->m_pixelReader = this->getInputSocketReader(0);
+
+       const int osa = 8;
+       this->m_osa = osa;
+       BLI_jitter_init(this->m_jitter[0], osa);
+}
+
+void PlaneTrackWarpImageOperation::deinitExecution()
+{
+       this->m_pixelReader = NULL;
+}
+
+void PlaneTrackWarpImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       float color_accum[4];
+
+       zero_v4(color_accum);
+       for (int sample = 0; sample < this->m_osa; sample++) {
+               float current_x = x + this->m_jitter[sample][0],
+                     current_y = y + this->m_jitter[sample][1];
+               if (isPointInsideQuad(current_x, current_y, this->m_frameSpaceCorners)) {
+                       float current_color[4];
+                       float u, v, dx, dy;
+
+                       resolveUVAndDxDy(current_x, current_y, this->m_frameSpaceCorners, &u, &v, &dx, &dy);
+
+                       u *= this->m_pixelReader->getWidth();
+                       v *= this->m_pixelReader->getHeight();
+
+                       this->m_pixelReader->read(current_color, u, v, dx, dy, COM_PS_BICUBIC);
+                       premul_to_straight_v4(current_color);
+                       add_v4_v4(color_accum, current_color);
+               }
+       }
+
+       mul_v4_v4fl(output, color_accum, 1.0f / this->m_osa);
+       straight_to_premul_v4(output);
+}
+
+bool PlaneTrackWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+       float frame_space_corners[4][2];
+
+       for (int i = 0; i < 4; i++) {
+               frame_space_corners[i][0] = this->m_corners[i][0] * this->getWidth();
+               frame_space_corners[i][1] = this->m_corners[i][1] * this->getHeight();
+       }
+
+       float UVs[4][2];
+
+       /* TODO(sergey): figure out proper way to do this. */
+       resolveUV(input->xmin - 2, input->ymin - 2, frame_space_corners, UVs[0]);
+       resolveUV(input->xmax + 2, input->ymin - 2, frame_space_corners, UVs[1]);
+       resolveUV(input->xmax + 2, input->ymax + 2, frame_space_corners, UVs[2]);
+       resolveUV(input->xmin - 2, input->ymax + 2, frame_space_corners, UVs[3]);
+
+       float min[2], max[2];
+       INIT_MINMAX2(min, max);
+       for (int i = 0; i < 4; i++) {
+               minmax_v2v2_v2(min, max, UVs[i]);
+       }
+
+       rcti newInput;
+
+       newInput.xmin = min[0] * readOperation->getWidth() - 1;
+       newInput.ymin = min[1] * readOperation->getHeight() - 1;
+       newInput.xmax = max[0] * readOperation->getWidth() + 1;
+       newInput.ymax = max[1] * readOperation->getHeight() + 1;
+
+       return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
new file mode 100644 (file)
index 0000000..a92ff3f
--- /dev/null
@@ -0,0 +1,53 @@
+
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ *             Sergey Sharybin
+ */
+
+#ifndef _COM_PlaneTrackWarpImageOperation_h
+#define _COM_PlaneTrackWarpImageOperation_h
+
+#include <string.h>
+
+#include "COM_PlaneTrackCommonOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackWarpImageOperation : public PlaneTrackCommonOperation {
+protected:
+       SocketReader *m_pixelReader;
+       int m_osa;
+       float m_jitter[32][2];
+
+public:
+       PlaneTrackWarpImageOperation();
+
+       void initExecution();
+       void deinitExecution();
+
+       void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+       bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+};
+
+#endif
index 2a1bdee32f77dc59cbb53e84f6dab5e8910062d0..6ced2423074c0f51b44d9092c7ad03fbffbb2af4 100644 (file)
@@ -102,32 +102,53 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
        MaskLayer *masklay;
 
        /* parent info */
-       SpaceClip *sc;
-       MovieClip *clip;
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       MovieTracking *tracking;
        MovieTrackingTrack *track;
-       MovieTrackingMarker *marker;
+       MovieTrackingPlaneTrack *plane_track;
        MovieTrackingObject *tracking_object;
        /* done */
 
-       int framenr;
+       int framenr, parent_type;
+       float parmask_pos[2], orig_corners[4][2];
+       char *sub_parent_name;
 
-       float marker_pos_ofs[2];
-       float parmask_pos[2];
-
-       if ((NULL == (sc = CTX_wm_space_clip(C))) ||
-           (NULL == (clip = sc->clip)) ||
-           (NULL == (track = clip->tracking.act_track)) ||
-           (NULL == (tracking_object = BKE_tracking_object_get_active(&clip->tracking))))
-       {
+       if (ELEM(NULL, sc, clip)) {
                return OPERATOR_CANCELLED;
        }
 
        framenr = ED_space_clip_get_clip_frame_number(sc);
-       marker = BKE_tracking_marker_get(track, framenr);
 
-       add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
+       tracking = &clip->tracking;
+       tracking_object = BKE_tracking_object_get_active(&clip->tracking);
+
+       if (tracking_object == NULL) {
+               return OPERATOR_CANCELLED;
+       }
+
+       if ((track = BKE_tracking_track_get_active(tracking)) != NULL) {
+               MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+               float marker_pos_ofs[2];
+
+               add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
 
-       BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
+               BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
+
+               sub_parent_name = track->name;
+               parent_type = MASK_PARENT_POINT_TRACK;
+       }
+       else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) {
+               MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+               zero_v2(parmask_pos);
+               sub_parent_name = plane_track->name;
+               parent_type = MASK_PARENT_PLANE_TRACK;
+               memcpy(orig_corners, plane_marker->corners, sizeof(orig_corners));
+       }
+       else {
+               return OPERATOR_CANCELLED;
+       }
 
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
                MaskSpline *spline;
@@ -144,10 +165,12 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
                                if (MASKPOINT_ISSEL_ANY(point)) {
                                        point->parent.id_type = ID_MC;
                                        point->parent.id = &clip->id;
+                                       point->parent.type = parent_type;
                                        BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent));
-                                       BLI_strncpy(point->parent.sub_parent, track->name, sizeof(point->parent.sub_parent));
+                                       BLI_strncpy(point->parent.sub_parent, sub_parent_name, sizeof(point->parent.sub_parent));
 
                                        copy_v2_v2(point->parent.parent_orig, parmask_pos);
+                                       memcpy(point->parent.parent_corners_orig, orig_corners, sizeof(point->parent.parent_corners_orig));
                                }
                        }
                }
index 93bdca930962b5dc9974bd746c07364e53d2c159..d5fbdca5b0aadde226f37185e3ea09148e795156 100644 (file)
@@ -38,6 +38,7 @@
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
 #include "BKE_mask.h"
+#include "BKE_report.h"
 
 #include "DNA_object_types.h"
 #include "DNA_mask_types.h"
index d1fd50939748f0a50b6d9cb6906a39fcaa32e2de..eb58bdc7696c4162f85b73ae21ce06618cd7bb97 100644 (file)
@@ -111,6 +111,57 @@ static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int wid
        }
 }
 
+static int generic_track_get_markersnr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track)
+{
+       if (track) {
+               return track->markersnr;
+       }
+       else if (plane_track) {
+               return plane_track->markersnr;
+       }
+
+       return 0;
+}
+
+static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+                                            int marker_index)
+{
+       if (track) {
+               return track->markers[marker_index].framenr;
+       }
+       else if (plane_track) {
+               return plane_track->markers[marker_index].framenr;
+       }
+
+       return 0;
+}
+
+static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+                                            int marker_index)
+{
+       if (track) {
+               return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
+       }
+       else if (plane_track) {
+               return true;
+       }
+
+       return false;
+}
+
+static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+                                              int marker_index)
+{
+       if (track) {
+               return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
+       }
+       else if (plane_track) {
+               return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
+       }
+
+       return false;
+}
+
 static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
 {
        float x;
@@ -119,6 +170,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
+       MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
        MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
 
        glEnable(GL_BLEND);
@@ -143,34 +195,29 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
        }
 
        /* track */
-       if (act_track) {
-               MovieTrackingTrack *track = act_track;
-
+       if (act_track || act_plane_track) {
                for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
                        int framenr;
-                       MovieTrackingMarker *marker;
+                       int markersnr = generic_track_get_markersnr(act_track, act_plane_track);
 
-                       while (a < track->markersnr) {
-                               if (track->markers[a].framenr >= i)
+                       while (a < markersnr) {
+                               int marker_framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
+
+                               if (marker_framenr >= i)
                                        break;
 
-                               if (a < track->markersnr - 1 && track->markers[a + 1].framenr > i)
+                               if (a < markersnr - 1 && generic_track_get_marker_framenr(act_track, act_plane_track, a + 1) > i)
                                        break;
 
                                a++;
                        }
 
-                       if (a < track->markersnr)
-                               marker = &track->markers[a];
-                       else
-                               marker = &track->markers[track->markersnr - 1];
-
-                       if ((marker->flag & MARKER_DISABLED) == 0) {
-                               framenr = marker->framenr;
+                       if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
+                               framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
 
                                if (framenr != i)
                                        glColor4ub(128, 128, 0, 96);
-                               else if ((marker->flag & MARKER_TRACKED) == 0)
+                               else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a))
                                        glColor4ub(255, 255, 0, 196);
                                else
                                        glColor4ub(255, 255, 0, 96);
@@ -961,13 +1008,159 @@ static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx
        *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
 }
 
+static void plane_track_colors(bool is_active, float color[3], float selected_color[3])
+{
+       UI_GetThemeColor3fv(TH_MARKER, color);
+
+       if (is_active)
+               UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color);
+       else
+               UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color);
+}
+
+static void getArrowEndPoint(const int width, const int height, const float zoom,
+                             const float start_corner[2], const float end_corner[2],
+                             float end_point[2])
+{
+       float direction[2];
+       float max_length;
+
+       sub_v2_v2v2(direction, end_corner, start_corner);
+
+       direction[0] *= width;
+       direction[1] *= height;
+       max_length = len_v2(direction);
+       normalize_v2(direction);
+       mul_v2_fl(direction, min_ff(32.0f / zoom, max_length));
+       direction[0] /= width;
+       direction[1] /= height;
+
+       add_v2_v2v2(end_point, start_corner, direction);
+}
+
+static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                                 MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
+                                 bool draw_outline, int width, int height)
+{
+       bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
+       bool is_selected_track = plane_track->flag & SELECT;
+       float px[2];
+
+       if (draw_outline) {
+               UI_ThemeColor(TH_MARKER_OUTLINE);
+       }
+       else {
+               float color[3], selected_color[3];
+               plane_track_colors(is_active_track, color, selected_color);
+               if (is_selected_track) {
+                       glColor3fv(selected_color);
+               }
+               else {
+                       glColor3fv(color);
+               }
+       }
+
+       px[0] = 1.0f / width / sc->zoom;
+       px[1] = 1.0f / height / sc->zoom;
+
+       if (draw_outline) {
+               if (!tiny) {
+                       glLineWidth(3.0f);
+               }
+       }
+       else if (tiny) {
+               glLineStipple(3, 0xaaaa);
+               glEnable(GL_LINE_STIPPLE);
+               glEnable(GL_COLOR_LOGIC_OP);
+               glLogicOp(GL_NOR);
+       }
+
+       /* Draw rectangle itself. */
+       glBegin(GL_LINE_LOOP);
+       glVertex2fv(plane_marker->corners[0]);
+       glVertex2fv(plane_marker->corners[1]);
+       glVertex2fv(plane_marker->corners[2]);
+       glVertex2fv(plane_marker->corners[3]);
+       glEnd();
+
+       /* Draw axis. */
+       if (!draw_outline) {
+               float end_point[2];
+               glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
+
+               getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
+               glColor3f(1.0, 0.0, 0.0f);
+               glBegin(GL_LINES);
+               glVertex2fv(plane_marker->corners[0]);
+               glVertex2fv(end_point);
+               glEnd();
+
+               getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
+               glColor3f(0.0, 1.0, 0.0f);
+               glBegin(GL_LINES);
+               glVertex2fv(plane_marker->corners[0]);
+               glVertex2fv(end_point);
+               glEnd();
+
+               glPopAttrib();
+       }
+
+       /* Draw sliders. */
+       if (is_selected_track) {
+               int i;
+               for (i = 0; i < 4; i++) {
+                       draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
+                                                3.0f * px[0], 3.0f * px[1], draw_outline, px);
+               }
+       }
+
+       if (draw_outline) {
+               if (!tiny) {
+                       glLineWidth(1.0f);
+               }
+       }
+       else if (tiny) {
+               glDisable(GL_COLOR_LOGIC_OP);
+               glDisable(GL_LINE_STIPPLE);
+               glLineStipple(3, 0xaaaa);
+               glEnable(GL_LINE_STIPPLE);
+       }
+}
+
+static void draw_plane_marker_outline(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                                      MovieTrackingPlaneMarker *plane_marker, int width, int height)
+{
+       draw_plane_marker_ex(sc, plane_track, plane_marker, false, true, width, height);
+}
+
+static void draw_plane_marker(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                              MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
+                              int width, int height)
+{
+       draw_plane_marker_ex(sc, plane_track, plane_marker, is_active_track, false, width, height);
+}
+
+static void draw_plane_track(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                             int framenr, bool is_active_track, int width, int height)
+{
+       MovieTrackingPlaneMarker *plane_marker;
+
+       plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+       draw_plane_marker_outline(sc, plane_track, plane_marker, width, height);
+       draw_plane_marker(sc, plane_track, plane_marker, is_active_track, width, height);
+}
+
+/* Draw all kind of tracks. */
 static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                                  int width, int height, float zoomx, float zoomy)
 {
        float x, y;
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *track, *act_track;
+       MovieTrackingPlaneTrack *plane_track, *active_plane_track;
        MovieTrackingMarker *marker;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
@@ -1160,6 +1353,15 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                glDisable(GL_POINT_SMOOTH);
        }
 
+       /* Draw plane tracks */
+       active_plane_track = BKE_tracking_plane_track_get_active(tracking);
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               draw_plane_track(sc, plane_track, framenr, plane_track == active_plane_track, width, height);
+       }
+
        glPopMatrix();
 
        if (sc->flag & SC_SHOW_NAMES) {
index edc6ac1ecf73ebbc807d3d1db2c3ec5f37a06f66..cdb0fdadebd9ea5f90b99c1b191914b5084847e5 100644 (file)
@@ -466,11 +466,10 @@ static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
-       ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
 
        if (act_track)
-               clip_delete_track(C, clip, tracksbase, act_track);
+               clip_delete_track(C, clip, act_track);
 
        return OPERATOR_FINISHED;
 }
@@ -498,7 +497,6 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
-       ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
 
        if (act_track) {
@@ -508,7 +506,7 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
                        MovieTrackingMarker *marker = &act_track->markers[a];
 
                        if (marker->flag & MARKER_GRAPH_SEL)
-                               clip_delete_marker(C, clip, tracksbase, act_track, marker);
+                               clip_delete_marker(C, clip, act_track, marker);
                        else
                                a++;
                }
index 51cb83eecad6f8d7fc632c7d5bd49063a9f48152..8d112b7413c432180e893c005e3d6f3243f0b6df 100644 (file)
@@ -132,8 +132,8 @@ void clip_graph_tracking_values_iterate(struct SpaceClip *sc, int selected_only,
 void clip_graph_tracking_iterate(struct SpaceClip *sc, int selected_only, int include_hidden, void *userdata,
                                  void (*func)(void *userdata, struct MovieTrackingMarker *marker));
 
-void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track);
-void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
+void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track);
+void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
 
 void clip_view_center_to_point(SpaceClip *sc, float x, float y);
 
@@ -193,6 +193,9 @@ void CLIP_OT_tracking_object_remove(struct wmOperatorType *ot);
 void CLIP_OT_copy_tracks(struct wmOperatorType *ot);
 void CLIP_OT_paste_tracks(struct wmOperatorType *ot);
 
+void CLIP_OT_create_plane_track(struct wmOperatorType *ot);
+void CLIP_OT_slide_plane_marker(struct wmOperatorType *ot);
+
 /* tracking_select.c */
 void CLIP_OT_select(struct wmOperatorType *ot);
 void CLIP_OT_select_all(struct wmOperatorType *ot);
index d7a9b1c0cb6fd4ea32533e5cd15dbe858c19174b..72a3cb98a6a1ffa8205d34ff6b6b4ca0aa9896a8 100644 (file)
@@ -175,11 +175,14 @@ void clip_graph_tracking_iterate(SpaceClip *sc, int selected_only, int include_h
        }
 }
 
-void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, MovieTrackingTrack *track)
+void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
 {
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingStabilization *stab = &tracking->stabilization;
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+       MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+       ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
 
        int has_bundle = FALSE, update_stab = FALSE;
 
@@ -196,6 +199,51 @@ void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, Movie
        if (track->flag & TRACK_HAS_BUNDLE)
                has_bundle = TRUE;
 
+       /* Make sure no plane will use freed track */
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = next_plane_track)
+       {
+               bool found  = false;
+               int i;
+
+               next_plane_track = plane_track->next;
+
+               for (i = 0; i < plane_track->point_tracksnr; i++) {
+                       if (plane_track->point_tracks[i] == track) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       continue;
+               }
+
+               if (plane_track->point_tracksnr > 4) {
+                       int track_index;
+                       MovieTrackingTrack **new_point_tracks;
+
+                       new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * plane_track->point_tracksnr,
+                                                      "new point tracks array");
+
+                       for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
+                               if (plane_track->point_tracks[i] != track) {
+                                       new_point_tracks[track_index++] = plane_track->point_tracks[i];
+                               }
+                       }
+
+                       MEM_freeN(plane_track->point_tracks);
+                       plane_track->point_tracks = new_point_tracks;
+                       plane_track->point_tracksnr--;
+               }
+               else {
+                       /* Delete planes with less than 3 point tracks in it. */
+                       BKE_tracking_plane_track_free(plane_track);
+                       BLI_freelinkN(plane_tracks_base, plane_track);
+               }
+       }
+
        BKE_tracking_track_free(track);
        BLI_freelinkN(tracksbase, track);
 
@@ -212,11 +260,11 @@ void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, Movie
                WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 }
 
-void clip_delete_marker(bContext *C, MovieClip *clip, ListBase *tracksbase,
-                        MovieTrackingTrack *track, MovieTrackingMarker *marker)
+void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track,
+                        MovieTrackingMarker *marker)
 {
        if (track->markersnr == 1) {
-               clip_delete_track(C, clip, tracksbase, track);
+               clip_delete_track(C, clip, track);
        }
        else {
                BKE_tracking_marker_delete(track, marker->framenr);
index 562a8584560517f76c13071bf720579baabd99d5..8213853c9374b337a77419eb097d26401d05de56 100644 (file)
@@ -517,6 +517,10 @@ static void clip_operatortypes(void)
        WM_operatortype_append(CLIP_OT_copy_tracks);
        WM_operatortype_append(CLIP_OT_paste_tracks);
 
+       /* Plane tracker */
+       WM_operatortype_append(CLIP_OT_create_plane_track);
+       WM_operatortype_append(CLIP_OT_slide_plane_marker);
+
        /* ** clip_graph_ops.c  ** */
 
        /* graph editing */
@@ -685,6 +689,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
 
        WM_keymap_add_item(keymap, "CLIP_OT_hide_tracks_clear", HKEY, KM_PRESS, KM_ALT, 0);
 
+       /* plane tracks */
+       WM_keymap_add_item(keymap, "CLIP_OT_slide_plane_marker", LEFTMOUSE, KM_PRESS, 0, 0);
+
        /* clean-up */
        WM_keymap_add_item(keymap, "CLIP_OT_join_tracks", JKEY, KM_PRESS, KM_CTRL, 0);
 
index f3d070452a5f8bd77418bb949c87f8a518731e00..e14fc8ad399b4ff4fc9d3f463243771771fb0cb1 100644 (file)
@@ -34,6 +34,7 @@
 #include "DNA_camera_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_movieclip_types.h"
 #include "DNA_object_types.h"   /* SELECT */
 #include "DNA_scene_types.h"
@@ -55,6 +56,8 @@
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_library.h"
+#include "BKE_mask.h"
+#include "BKE_node.h"
 #include "BKE_sound.h"
 
 #include "WM_api.h"
@@ -88,6 +91,7 @@ static bool add_marker(const bContext *C, float x, float y)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *track;
        int width, height;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -101,8 +105,10 @@ static bool add_marker(const bContext *C, float x, float y)
        track = BKE_tracking_track_add(tracking, tracksbase, x, y, framenr, width, height);
 
        BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, 0);
+       BKE_tracking_plane_tracks_deselect_all(plane_tracks_base);
 
        clip->tracking.act_track = track;
+       clip->tracking.act_plane_track = NULL;
 
        return true;
 }
@@ -234,13 +240,31 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *track = tracksbase->first, *next;
+       MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+       bool modified = false;
+
+       /* Delete selected plane tracks. */
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = next_plane_track)
+       {
+               next_plane_track = plane_track->next;
+
+               if (plane_track->flag & SELECT) {
+                       BKE_tracking_plane_track_free(plane_track);
+                       BLI_freelinkN(plane_tracks_base, plane_track);
+                       modified = true;
+               }
+       }
 
+       /* Remove selected point tracks (they'll also be removed from planes which uses them). */
        while (track) {
                next = track->next;
 
                if (TRACK_VIEW_SELECTED(sc, track))
-                       clip_delete_track(C, clip, tracksbase, track);
+                       clip_delete_track(C, clip, track);
 
                track = next;
        }
@@ -248,6 +272,10 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
        /* nothing selected now, unlock view so it can be scrolled nice again */
        sc->flag &= ~SC_LOCK_SELECTION;
 
+       if (modified) {
+               WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+       }
+
        return OPERATOR_FINISHED;
 }
 
@@ -274,7 +302,9 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc = CTX_wm_space_clip(C);
        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 = tracksbase->first, *next;
+       MovieTrackingPlaneTrack *plane_track, *plane_track_next;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        int has_selection = 0;
 
@@ -287,13 +317,34 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
                        if (marker) {
                                has_selection |= track->markersnr > 1;
 
-                               clip_delete_marker(C, clip, tracksbase, track, marker);
+                               clip_delete_marker(C, clip, track, marker);
                        }
                }
 
                track = next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track_next)
+       {
+               plane_track_next = plane_track->next;
+
+               if (plane_track->flag & SELECT) {
+                       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, framenr);
+
+                       if (plane_marker) {
+                               if (plane_track->markersnr == 1) {
+                                       BKE_tracking_plane_track_free(plane_track);
+                                       BLI_freelinkN(plane_tracks_base, plane_track);
+                               }
+                               else {
+                                       BKE_tracking_plane_marker_delete(plane_track, framenr);
+                               }
+                       }
+               }
+       }
+
        if (!has_selection) {
                /* nothing selected now, unlock view so it can be scrolled nice again */
                sc->flag &= ~SC_LOCK_SELECTION;
@@ -727,6 +778,7 @@ static int slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event
                MovieTracking *tracking = &clip->tracking;
 
                tracking->act_track = slidedata->track;
+               tracking->act_plane_track = NULL;
 
                op->customdata = slidedata;
 
@@ -3670,3 +3722,350 @@ void CLIP_OT_paste_tracks(wmOperatorType *ot)
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
+
+/********************** Create plane track operator *********************/
+
+static int create_plane_track_tracks_exec(bContext *C, wmOperator *op)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       MovieTracking *tracking = &clip->tracking;
+       MovieTrackingPlaneTrack *plane_track;
+       ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       plane_track = BKE_tracking_plane_track_add(tracking, plane_tracks_base, tracks_base, framenr);
+
+       if (plane_track == NULL) {
+               BKE_report(op->reports, RPT_ERROR, "Need at least 4 selected point tracks to create a plane");
+               return OPERATOR_CANCELLED;
+       }
+       else {
+               BKE_tracking_tracks_deselect_all(tracks_base);
+
+               plane_track->flag |= SELECT;
+               clip->tracking.act_track = NULL;
+               clip->tracking.act_plane_track = plane_track;
+
+               /* Copute homoraphies and apply them on marker's corner, so we've got
+                * quite nice motion from the very beginning.
+                */
+               BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+       }
+
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+       return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_create_plane_track(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Create Plane Track";
+       ot->description = "Create new plane track out of selected point tracks";
+       ot->idname = "CLIP_OT_create_plane_track";
+
+       /* api callbacks */
+       ot->exec = create_plane_track_tracks_exec;
+       ot->poll = ED_space_clip_tracking_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** Slide plane marker corner operator *********************/
+
+typedef struct SlidePlaneMarkerData {
+       MovieTrackingPlaneTrack *plane_track;
+       MovieTrackingPlaneMarker *plane_marker;
+       int width, height;
+       int corner_index;
+       float *corner;
+       int previous_mval[2];
+       float previous_corner[2];
+       float old_corner[2];
+       bool accurate;
+} SlidePlaneMarkerData;
+
+static bool mouse_on_plane_slide_zone(SpaceClip *sc, float co[2], float slide_zone[2], int width, int height)
+{
+       const float size = 12.0f;
+       float dx, dy;
+
+       dx = size / width / sc->zoom;
+       dy = size / height / sc->zoom;
+
+       return IN_RANGE_INCL(co[0], slide_zone[0] - dx, slide_zone[0] + dx) &&
+              IN_RANGE_INCL(co[1], slide_zone[1] - dy, slide_zone[1] + dy);
+}
+
+static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C, const wmEvent *event, int *corner_r)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       ARegion *ar = CTX_wm_region(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       MovieTrackingPlaneTrack *plane_track;
+       int width, height;
+       float co[2];
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       ED_space_clip_get_size(sc, &width, &height);
+
+       if (width == 0 || height == 0) {
+               return NULL;
+       }
+
+       ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (plane_track->flag & SELECT) {
+                       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+                       bool ok = false;
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               if (mouse_on_plane_slide_zone(sc, co, plane_marker->corners[i], width, height)) {
+                                       if (corner_r) {
+                                               *corner_r = i;
+                                       }
+                                       ok = true;
+                                       break;
+                               }
+                       }
+
+                       if (ok) {
+                               return plane_track;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+static void *slide_plane_marker_customdata(bContext *C, const wmEvent *event)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       ARegion *ar = CTX_wm_region(C);
+       MovieTrackingPlaneTrack *plane_track;
+       int width, height;
+       float co[2];
+       SlidePlaneMarkerData *customdata = NULL;
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+       int corner;
+
+       ED_space_clip_get_size(sc, &width, &height);
+
+       if (width == 0 || height == 0) {
+               return NULL;
+       }
+
+       ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+       plane_track = tracking_plane_marker_check_slide(C, event, &corner);
+       if (plane_track) {
+               MovieTrackingPlaneMarker *plane_marker;
+
+               customdata = MEM_callocN(sizeof(SlidePlaneMarkerData), "slide plane marker data");
+
+               plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+
+               customdata->plane_track = plane_track;
+               customdata->plane_marker = plane_marker;
+               customdata->width = width;
+               customdata->height = height;
+
+               customdata->previous_mval[0] = event->mval[0];
+               customdata->previous_mval[1] = event->mval[1];
+
+               customdata->corner_index = corner;
+               customdata->corner = plane_marker->corners[corner];
+
+               copy_v2_v2(customdata->previous_corner, customdata->corner);
+               copy_v2_v2(customdata->old_corner, customdata->corner);
+       }
+
+       return customdata;
+}
+
+static int slide_plane_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       SlidePlaneMarkerData *slidedata = slide_plane_marker_customdata(C, event);
+
+       if (slidedata) {
+               SpaceClip *sc = CTX_wm_space_clip(C);
+               MovieClip *clip = ED_space_clip_get_clip(sc);
+               MovieTracking *tracking = &clip->tracking;
+
+               tracking->act_plane_track = slidedata->plane_track;
+               tracking->act_track = NULL;
+
+               op->customdata = slidedata;
+
+               hide_cursor(C);
+               WM_event_add_modal_handler(C, op);
+
+               WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+
+               return OPERATOR_RUNNING_MODAL;
+       }
+
+       return OPERATOR_PASS_THROUGH;
+}
+
+static void cancel_mouse_slide_plane_marker(SlidePlaneMarkerData *data)
+{
+       copy_v2_v2(data->corner, data->old_corner);
+}
+
+static void free_slide_plane_marker_data(SlidePlaneMarkerData *data)
+{
+       MEM_freeN(data);
+}
+
+static void slide_plane_marker_update_homographies(SpaceClip *sc, SlidePlaneMarkerData *data)
+{
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       BKE_tracking_track_plane_from_existing_motion(data->plane_track, framenr);
+}
+
+static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       SlidePlaneMarkerData *data = (SlidePlaneMarkerData *) op->customdata;
+       float dx, dy, mdelta[2];
+       int next_corner_index, prev_corner_index, diag_corner_index;
+       float *next_corner, *prev_corner, *diag_corner;
+       float next_edge[2], prev_edge[2], next_diag_edge[2], prev_diag_edge[2];
+
+       switch (event->type) {
+               case LEFTCTRLKEY:
+               case RIGHTCTRLKEY:
+               case LEFTSHIFTKEY:
+               case RIGHTSHIFTKEY:
+                       if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
+                               data->accurate = event->val == KM_PRESS;
+
+                       /* fall-through */
+               case MOUSEMOVE:
+                       mdelta[0] = event->mval[0] - data->previous_mval[0];
+                       mdelta[1] = event->mval[1] - data->previous_mval[1];
+
+                       dx = mdelta[0] / data->width / sc->zoom;
+                       dy = mdelta[1] / data->height / sc->zoom;
+
+                       if (data->accurate) {
+                               dx /= 5.0f;
+                               dy /= 5.0f;
+                       }
+
+                       data->corner[0] = data->previous_corner[0] + dx;
+                       data->corner[1] = data->previous_corner[1] + dy;
+
+
+                       /*
+                                                      prev_edge
+                           (Corner 3, current) <-----------------------   (Corner 2, previous)
+                                   |                                              ^
+                                   |                                              |
+                                   |                                              |
+                                   |                                              |
+                         next_edge |                                              | next_diag_edge
+                                   |                                              |
+                                   |                                              |
+                                   |                                              |
+                                   v                                              |
+                            (Corner 0, next)   ----------------------->   (Corner 1, diagonal)
+                                                     prev_diag_edge
+                        */
+
+                       next_corner_index = (data->corner_index + 1) % 4;
+                       prev_corner_index = (data->corner_index + 3) % 4;
+                       diag_corner_index = (data->corner_index + 2) % 4;
+
+                       next_corner = data->plane_marker->corners[next_corner_index];
+                       prev_corner = data->plane_marker->corners[prev_corner_index];
+                       diag_corner = data->plane_marker->corners[diag_corner_index];
+
+                       sub_v2_v2v2(next_edge, next_corner, data->corner);
+                       sub_v2_v2v2(prev_edge, data->corner, prev_corner);
+                       sub_v2_v2v2(next_diag_edge, prev_corner, diag_corner);
+                       sub_v2_v2v2(prev_diag_edge, diag_corner, next_corner);
+
+                       if (cross_v2v2(prev_edge, next_edge) < 0.0f) {
+                               closest_to_line_v2(data->corner, data->corner, prev_corner, next_corner);
+                       }
+
+                       if (cross_v2v2(next_diag_edge, prev_edge) < 0.0f) {
+                               closest_to_line_v2(data->corner, data->corner, prev_corner, diag_corner);
+                       }
+
+                       if (cross_v2v2(next_edge, prev_diag_edge) < 0.0f) {
+                               closest_to_line_v2(data->corner, data->corner, next_corner, diag_corner);
+                       }
+
+                       data->previous_mval[0] = event->mval[0];
+                       data->previous_mval[1] = event->mval[1];
+                       copy_v2_v2(data->previous_corner, data->corner);
+
+                       DAG_id_tag_update(&sc->clip->id, 0);
+
+                       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+
+                       break;
+
+               case LEFTMOUSE:
+                       if (event->val == KM_RELEASE) {
+                               /* Marker is now keyframed. */
+                               data->plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+
+                               slide_plane_marker_update_homographies(sc, data);
+
+                               free_slide_plane_marker_data(op->customdata);
+
+                               show_cursor(C);
+
+                               DAG_id_tag_update(&sc->clip->id, 0);
+                               WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+                               return OPERATOR_FINISHED;
+                       }
+
+                       break;
+
+               case ESCKEY:
+                       cancel_mouse_slide_plane_marker(op->customdata);
+
+                       free_slide_plane_marker_data(op->customdata);
+
+                       show_cursor(C);
+
+                       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+                       return OPERATOR_CANCELLED;
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+void CLIP_OT_slide_plane_marker(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Slide Plane Marker";
+       ot->description = "Slide plane marker areas";
+       ot->idname = "CLIP_OT_slide_plane_marker";
+
+       /* api callbacks */
+       ot->poll = ED_space_clip_tracking_poll;
+       ot->invoke = slide_plane_marker_invoke;
+       ot->modal = slide_plane_marker_modal;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+}
index b03209173d8b9135fac0beb75910feff2819f34e..6e4d10173fb2af20b78a90e5e9f3213142b65081 100644 (file)
@@ -169,6 +169,7 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
        return sqrtf(min_ffff(d1, d2, d3, d4));
 }
 
+/* Distance to quad defined by it's corners, corners are relative to pos */
 static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
 {
        float d1, d2, d3, d4;
@@ -184,7 +185,22 @@ static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
        return sqrtf(min_ffff(d1, d2, d3, d4));
 }
 
-static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2])
+/* Same as above, but all the coordinates are absolute */
+static float dist_to_crns_abs(float co[2], float corners[4][2])
+{
+       float d1, d2, d3, d4;
+       float *v1 = corners[0], *v2 = corners[1];
+       float *v3 = corners[2], *v4 = corners[3];
+
+       d1 = dist_squared_to_line_segment_v2(co, v1, v2);
+       d2 = dist_squared_to_line_segment_v2(co, v2, v3);
+       d3 = dist_squared_to_line_segment_v2(co, v3, v4);
+       d4 = dist_squared_to_line_segment_v2(co, v4, v1);
+
+       return sqrtf(min_ffff(d1, d2, d3, d4));
+}
+
+static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2], float *distance_r)
 {
        MovieTrackingTrack *track = NULL, *cur;
        float mindist = 0.0f;
@@ -221,19 +237,88 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas
                cur = cur->next;
        }
 
+       *distance_r = mindist;
+
        return track;
 }
 
+static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc, ListBase *plane_tracks_base,
+                                                         float co[2], float *distance_r)
+{
+       MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;
+       float min_distance = 0.0f;
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       for (current_plane_track = plane_tracks_base->first;
+            current_plane_track;
+            current_plane_track = current_plane_track->next)
+       {
+               MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(current_plane_track, framenr);
+
+               if ((current_plane_track->flag & TRACK_HIDDEN) == 0) {
+                       float distance = dist_to_crns_abs(co, plane_marker->corners);
+                       if (plane_track == NULL || distance < min_distance) {
+                               plane_track = current_plane_track;
+                               min_distance = distance;
+                       }
+               }
+       }
+
+       *distance_r = min_distance;
+
+       return plane_track;
+}
+
+static void delect_all_tracks(ListBase *tracks_base)
+{
+       MovieTrackingTrack *track;
+       for (track = tracks_base->first;
+            track;
+            track = track->next)
+       {
+               BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+       }
+}
+
+static void delect_all_plane_tracks(ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               plane_track->flag &= ~SELECT;
+       }
+}
+
 static int mouse_select(bContext *C, float co[2], int extend)
 {
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
-       MovieTrackingTrack *track = NULL;   /* selected marker */
+       MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
+       float distance_to_track, distance_to_plane_track;
+
+       track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
+       plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);
+
+       /* Between track and plane we choose closest to the mouse for selection here. */
+       if (track && plane_track) {
+               if (distance_to_track < distance_to_plane_track) {
+                       plane_track = NULL;
+               }
+               else {
+                       track = NULL;
+               }
+       }
 
-       track = find_nearest_track(sc, tracksbase, co);
+       if (!extend) {
+               delect_all_plane_tracks(plane_tracks_base);
+       }
 
        if (track) {
                int area = track_mouse_area(C, co, track);
@@ -242,10 +327,13 @@ static int mouse_select(bContext *C, float co[2], int extend)
                        area = TRACK_AREA_ALL;
 
                if (extend && TRACK_AREA_SELECTED(track, area)) {
-                       if (track == act_track)
+                       if (track == act_track) {
                                BKE_tracking_track_deselect(track, area);
-                       else
+                       }
+                       else {
                                clip->tracking.act_track = track;
+                               clip->tracking.act_plane_track = NULL;
+                       }
                }
                else {
                        if (area == TRACK_AREA_POINT)
@@ -253,7 +341,25 @@ static int mouse_select(bContext *C, float co[2], int extend)
 
                        BKE_tracking_track_select(tracksbase, track, area, extend);
                        clip->tracking.act_track = track;
+                       clip->tracking.act_plane_track = NULL;
+               }
+       }
+       else if (plane_track) {
+               if (!extend) {
+                       delect_all_tracks(tracksbase);
+               }
+
+               if (plane_track->flag & SELECT) {
+                       if (extend) {
+                               plane_track->flag &= ~SELECT;
+                       }
+               }
+               else {
+                       plane_track->flag |= SELECT;
                }
+
+               clip->tracking.act_track = NULL;
+               clip->tracking.act_plane_track = plane_track;
        }
 
        if (!extend) {
@@ -350,7 +456,9 @@ static int border_select_exec(bContext *C, wmOperator *op)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        rcti rect;
        rctf rectf;
        int change = FALSE, mode, extend;
@@ -389,6 +497,33 @@ static int border_select_exec(bContext *C, wmOperator *op)
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       MovieTrackingPlaneMarker *plane_marker =
+                               BKE_tracking_plane_marker_get(plane_track, framenr);
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               if (BLI_rctf_isect_pt_v(&rectf, plane_marker->corners[i])) {
+                                       if (mode == GESTURE_MODAL_SELECT) {
+                                               plane_track->flag |= SELECT;
+                                       }
+                                       else {
+                                               plane_track->flag &= ~SELECT;
+                                       }
+                               }
+                               else if (!extend) {
+                                       plane_track->flag &= ~SELECT;
+                               }
+                       }
+
+                       change = TRUE;
+               }
+       }
+
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
@@ -430,7 +565,9 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        rcti rect;
        int change = FALSE;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -466,6 +603,37 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       MovieTrackingPlaneMarker *plane_marker =
+                               BKE_tracking_plane_marker_get(plane_track, framenr);
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               float screen_co[2];
+
+                               /* marker in screen coords */
+                               ED_clip_point_stable_pos__reverse(sc, ar, plane_marker->corners[i], screen_co);
+
+                               if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
+                                   BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED))
+                               {
+                                       if (select) {
+                                               plane_track->flag |= SELECT;
+                                       }
+                                       else {
+                                               plane_track->flag &= ~SELECT;
+                                       }
+                               }
+                       }
+
+                       change = TRUE;
+               }
+       }
+
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
@@ -518,17 +686,22 @@ void CLIP_OT_select_lasso(wmOperatorType *ot)
 
 /********************** circle select operator *********************/
 
-static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
+static int point_inside_ellipse(float point[2], float offset[2], float ellipse[2])
 {
        /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
        float x, y;
 
-       x = (marker->pos[0] - offset[0]) * ellipse[0];
-       y = (marker->pos[1] - offset[1]) * ellipse[1];
+       x = (point[0] - offset[0]) * ellipse[0];
+       y = (point[1] - offset[1]) * ellipse[1];
 
        return x * x + y * y < 1.0f;
 }
 
+static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
+{
+       return point_inside_ellipse(marker->pos, offset, ellipse);
+}
+
 static int circle_select_exec(bContext *C, wmOperator *op)
 {
        SpaceClip *sc = CTX_wm_space_clip(C);
@@ -537,7 +710,9 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        int x, y, radius, width, height, mode, change = FALSE;
        float zoomx, zoomy, offset[2], ellipse[2];
        int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -577,6 +752,30 @@ static int circle_select_exec(bContext *C, wmOperator *op)
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       MovieTrackingPlaneMarker *plane_marker =
+                               BKE_tracking_plane_marker_get(plane_track, framenr);
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               if (point_inside_ellipse(plane_marker->corners[i], offset, ellipse)) {
+                                       if (mode == GESTURE_MODAL_SELECT) {
+                                               plane_track->flag |= SELECT;
+                                       }
+                                       else {
+                                               plane_track->flag &= ~SELECT;
+                                       }
+                               }
+                       }
+
+                       change = TRUE;
+               }
+       }
+
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
@@ -619,16 +818,18 @@ static int select_all_exec(bContext *C, wmOperator *op)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track = NULL;   /* selected track */
+       MovieTrackingPlaneTrack *plane_track = NULL;   /* selected plane track */
        MovieTrackingMarker *marker;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        int action = RNA_enum_get(op->ptr, "action");
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        int has_selection = FALSE;
 
        if (action == SEL_TOGGLE) {
                action = SEL_SELECT;
-               track = tracksbase->first;
-               while (track) {
+
+               for (track = tracksbase->first; track; track = track->next) {
                        if (TRACK_VIEW_SELECTED(sc, track)) {
                                marker = BKE_tracking_marker_get(track, framenr);
 
@@ -637,13 +838,20 @@ static int select_all_exec(bContext *C, wmOperator *op)
                                        break;
                                }
                        }
+               }
 
-                       track = track->next;
+               for (plane_track = plane_tracks_base->first;
+                    plane_track;
+                    plane_track = plane_track->next)
+               {
+                       if (plane_track->flag & SELECT) {
+                               action = SEL_DESELECT;
+                               break;
+                       }
                }
        }
 
-       track = tracksbase->first;
-       while (track) {
+       for (track = tracksbase->first; track; track = track->next) {
                if ((track->flag & TRACK_HIDDEN) == 0) {
                        marker = BKE_tracking_marker_get(track, framenr);
 
@@ -670,8 +878,29 @@ static int select_all_exec(bContext *C, wmOperator *op)
 
                if (TRACK_VIEW_SELECTED(sc, track))
                        has_selection = TRUE;
+       }
 
-               track = track->next;
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       switch (action) {
+                               case SEL_SELECT:
+                                       plane_track->flag |= SELECT;
+                                       break;
+                               case SEL_DESELECT:
+                                       plane_track->flag &= ~SELECT;
+                                       break;
+                               case SEL_INVERT:
+                                       plane_track->flag ^= SELECT;
+                                       break;
+                       }
+               }
+
+               if (plane_track->flag & SELECT) {
+                       has_selection = TRUE;
+               }
        }
 
        if (!has_selection)
index cf3c0454e6b0103ad61e65918241fceecae5ba06..5cc22b25f72e7613fbd1fcb84f16614a7241fc4a 100644 (file)
@@ -2225,6 +2225,39 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
        }
 }
 
+static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+       bNode *node = ptr->data;
+
+       uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
+
+       if (node->id) {
+               MovieClip *clip = (MovieClip *) node->id;
+               MovieTracking *tracking = &clip->tracking;
+               MovieTrackingObject *object;
+               uiLayout *col;
+               PointerRNA tracking_ptr;
+               NodeTrackPosData *data = node->storage;
+
+               RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
+
+               col = uiLayoutColumn(layout, FALSE);
+               uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
+
+               object = BKE_tracking_object_get_named(tracking, data->tracking_object);
+               if (object) {
+                       PointerRNA object_ptr;
+
+                       RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
+
+                       uiItemPointerR(col, ptr, "plane_track_name", &object_ptr, "plane_tracks", "", ICON_ANIM_DATA);
+               }
+               else {
+                       uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
+               }
+       }
+}
+
 /* only once called */
 static void node_composit_set_butfunc(bNodeType *ntype)
 {
@@ -2444,6 +2477,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
                case CMP_NODE_TRACKPOS:
                        ntype->uifunc = node_composit_buts_trackpos;
                        break;
+               case CMP_NODE_PLANETRACKDEFORM:
+                       ntype->uifunc = node_composit_buts_planetrackdeform;
+                       break;
        }
 }
 
index d5a9d0f9f932a1106d739e6eab5dbb9ddc1ffdf6..6d801b866851856ab6ddb8a20c211a2ae993a395 100644 (file)
@@ -3005,7 +3005,12 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
                copy_v3_v3(center, td->center);
        }
        else if (t->options & CTX_MOVIECLIP) {
-               copy_v3_v3(center, td->center);
+               if (td->flag & TD_INDIVIDUAL_SCALE) {
+                       copy_v3_v3(center, td->center);
+               }
+               else {
+                       copy_v3_v3(center, t->center);
+               }
        }
        else {
                copy_v3_v3(center, t->center);
index 4a1c4203a4370d2c606c9e79102340a7fd0c9162..4954f8619349669a5f068a61bd636ac9d3c4cad3 100644 (file)
@@ -455,7 +455,7 @@ typedef struct TransInfo {
 #define        TD_USEQUAT                      (1 << 3)
 #define TD_NOTCONNECTED                (1 << 4)
 #define TD_SINGLESIZE          (1 << 5)        /* used for scaling of MetaElem->rad */
-/*#define TD_TIMEONLY                  (1 << 8) */ /*UNUSED*/
+#define TD_INDIVIDUAL_SCALE    (1 << 8) /* Scale relative to individual element center */
 #define TD_NOCENTER                    (1 << 9)
 #define TD_NO_EXT                      (1 << 10)       /* ext abused for particle key timing */
 #define TD_SKIP                                (1 << 11)       /* don't transform this data */
index 95ec20a0c2bbbba55f661abba249c86eec4aece4..01605003d7b40c492806f827253f5a65ab10ee38 100644 (file)
@@ -5959,7 +5959,8 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
 
 enum transDataTracking_Mode {
        transDataTracking_ModeTracks = 0,
-       transDataTracking_ModeCurves = 1
+       transDataTracking_ModeCurves = 1,
+       transDataTracking_ModePlaneTracks = 2,
 };
 
 typedef struct TransDataTracking {
@@ -5978,6 +5979,9 @@ typedef struct TransDataTracking {
        /* marker transformation from curves editor */
        float *prev_pos, scale;
        short coord;
+
+       MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
 } TransDataTracking;
 
 static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
@@ -6008,6 +6012,7 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
 
        tdt->markersnr = track->markersnr;
        tdt->markers = track->markers;
+       tdt->track = track;
 
        if (rel) {
                if (!anchor) {
@@ -6026,6 +6031,7 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
        copy_v3_v3(td->iloc, td->loc);
 
        //copy_v3_v3(td->center, td->loc);
+       td->flag |= TD_INDIVIDUAL_SCALE;
        td->center[0] = marker->pos[0] * aspx;
        td->center[1] = marker->pos[1] * aspy;
 
@@ -6076,6 +6082,52 @@ static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d
        }
 }
 
+static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
+                                       MovieTrackingPlaneTrack *plane_track, float corner[2],
+                                       float aspx, float aspy)
+{
+       tdt->mode = transDataTracking_ModePlaneTracks;
+       tdt->plane_track = plane_track;
+
+       td2d->loc[0] = corner[0] * aspx; /* hold original location */
+       td2d->loc[1] = corner[1] * aspy;
+
+       td2d->loc2d = corner; /* current location */
+       td2d->loc[2] = 0.0f;
+
+       td->flag = 0;
+       td->loc = td2d->loc;
+       copy_v3_v3(td->iloc, td->loc);
+       copy_v3_v3(td->center, td->loc);
+
+       memset(td->axismtx, 0, sizeof(td->axismtx));
+       td->axismtx[2][2] = 1.0f;
+
+       td->ext = NULL;
+       td->val = NULL;
+
+       td->flag |= TD_SELECTED;
+       td->dist = 0.0;
+
+       unit_m3(td->mtx);
+       unit_m3(td->smtx);
+}
+
+static void planeTrackToTransData(const int framenr, TransData *td, TransData2D *td2d,
+                                  TransDataTracking *tdt, MovieTrackingPlaneTrack *plane_track,
+                                  float aspx, float aspy)
+{
+       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+       int i;
+
+       tdt->flag = plane_marker->flag;
+       plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+
+       for (i = 0; i < 4; i++) {
+               planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspx, aspy);
+       }
+}
+
 static void transDataTrackingFree(TransInfo *t)
 {
        TransDataTracking *tdt = t->customData;
@@ -6096,7 +6148,9 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
        SpaceClip *sc = CTX_wm_space_clip(C);
        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;
        TransDataTracking *tdt;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        float aspx, aspy;
@@ -6122,6 +6176,15 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (plane_track->flag & SELECT) {
+                       t->total += 4;
+               }
+       }
+
        if (t->total == 0)
                return;
 
@@ -6165,11 +6228,23 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
 
                track = track->next;
        }
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (plane_track->flag & SELECT) {
+                       planeTrackToTransData(framenr, td, td2d, tdt, plane_track, aspx, aspy);
+                       td += 4;
+                       td2d += 4;
+                       tdt += 4;
+               }
+       }
 }
 
 static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
-                                       MovieTrackingMarker *marker, MovieTrackingMarker *prev_marker,
-                                       short coord, float size)
+                                       MovieTrackingTrack *track, MovieTrackingMarker *marker,
+                                       MovieTrackingMarker *prev_marker, short coord, float size)
 {
        float frames_delta = (marker->framenr - prev_marker->framenr);
 
@@ -6180,6 +6255,7 @@ static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDa
        tdt->coord = coord;
        tdt->scale = 1.0f / size * frames_delta;
        tdt->prev_pos = prev_marker->pos;
+       tdt->track = track;
 
        /* calculate values depending on marker's speed */
        td2d->loc[0] = marker->framenr;
@@ -6265,14 +6341,14 @@ static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
                                        continue;
 
                                if (marker->flag & MARKER_GRAPH_SEL_X) {
-                                       markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i - 1], 0, width);
+                                       markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
                                        td += 1;
                                        td2d += 1;
                                        tdt += 1;
                                }
 
                                if (marker->flag & MARKER_GRAPH_SEL_Y) {
-                                       markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i - 1], 1, height);
+                                       markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
 
                                        td += 1;
                                        td2d += 1;
@@ -6313,57 +6389,54 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
 
 static void cancelTransTracking(TransInfo *t)
 {
-       TransDataTracking *tdt = t->customData;
        SpaceClip *sc = t->sa->spacedata.first;
-       MovieClip *clip = ED_space_clip_get_clip(sc);
-       ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
-       MovieTrackingTrack *track;
-       MovieTrackingMarker *marker;
-       int a, framenr = ED_space_clip_get_clip_frame_number(sc);
+       int i, framenr = ED_space_clip_get_clip_frame_number(sc);
 
-       if (tdt->mode == transDataTracking_ModeTracks) {
-               track = tracksbase->first;
-               while (track) {
-                       if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
-                               marker = BKE_tracking_marker_get(track, framenr);
-                               marker->flag = tdt->flag;
+       i = 0;
+       while (i < t->total) {
+               TransDataTracking *tdt = (TransDataTracking *) t->customData + i;
 
-                               tdt++;
+               if (tdt->mode == transDataTracking_ModeTracks) {
+                       MovieTrackingTrack *track = tdt->track;
+                       MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
 
-                               if (track->flag & SELECT)
-                                       tdt++;
+                       marker->flag = tdt->flag;
 
-                               if (track->pat_flag & SELECT)
-                                       tdt += 2;
+                       if (track->flag & SELECT)
+                               i++;
 
-                               if (track->search_flag & SELECT)
-                                       tdt += 2;
-                       }
+                       if (track->pat_flag & SELECT)
+                               i += 4;
 
-                       track = track->next;
+                       if (track->search_flag & SELECT)
+                               i += 2;
                }
-       }
-       else if (tdt->mode == transDataTracking_ModeCurves) {
-               MovieTrackingMarker *prev_marker;
+               else if (tdt->mode == transDataTracking_ModeCurves) {
+                       MovieTrackingTrack *track = tdt->track;
+                       MovieTrackingMarker *marker, *prev_marker;
+                       int a;
 
-               track = tracksbase->first;
-               while (track) {
-                       if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
-                               for (a = 1; a < track->markersnr; a++) {
-                                       marker = &track->markers[a];
-                                       prev_marker = &track->markers[a - 1];
+                       for (a = 1; a < track->markersnr; a++) {
+                               marker = &track->markers[a];
+                               prev_marker = &track->markers[a - 1];
 
-                                       if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
-                                               continue;
+                               if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+                                       continue;
 
-                                       if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
-                                               marker->flag = tdt->flag;
-                                       }
+                               if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
+                                       marker->flag = tdt->flag;
                                }
                        }
+               }
+               else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+                       MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
+                       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
 
-                       track = track->next;
+                       plane_marker->flag = tdt->flag;
+                       i += 3;
                }
+
+               i++;
        }
 }
 
@@ -6432,6 +6505,10 @@ void flushTransTracking(TransInfo *t)
                else if (tdt->mode == transDataTracking_ModeCurves) {
                        td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
                }
+               else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+                       td2d->loc2d[0] = td2d->loc[0] / aspx;
+                       td2d->loc2d[1] = td2d->loc[1] / aspy;
+               }
        }
 }
 
index cb0a053003630c8e06294f0996b60097d7685fb1..4c7ac4193b36b0930ce4eb04fa993ae73bc96705 100644 (file)
@@ -659,7 +659,9 @@ 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);
@@ -690,6 +692,15 @@ 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) {
index 1b6b802f2de9d3c34b0a284bb095f54f50d97e00..1b1c912d179730bd7067278d88562a081887a434 100644 (file)
@@ -58,15 +58,18 @@ typedef struct Mask {
 
 typedef struct MaskParent {
        // int flag;             /* parenting flags */ /* not used */
-       int pad;
        int id_type;          /* type of parenting */
+       int type;             /* type of parenting */
        ID *id;               /* ID block of entity to which mask/spline is parented to
                               * in case of parenting to movie tracking data set to MovieClip datablock */
        char parent[64];      /* entity of parent to which parenting happened
                               * in case of parenting to movie tracking data contains name of layer */
        char sub_parent[64];  /* sub-entity of parent to which parenting happened
                               * in case of parenting to movie tracking data contains name of track */
-       float parent_orig[2]; /* track location at the moment of parenting */
+       float parent_orig[2]; /* track location at the moment of parenting,
+                                stored in mask space*/
+
+       float parent_corners_orig[4][2]; /* Original corners of plane track at the moment of parenting */
 } MaskParent;
 
 typedef struct MaskSplinePointUW {
@@ -141,6 +144,12 @@ typedef struct MaskLayer {
 /* MaskParent->flag */
 /* #define MASK_PARENT_ACTIVE  (1 << 0) */ /* UNUSED */
 
+/* MaskParent->type */
+enum {
+       MASK_PARENT_POINT_TRACK = 0, /* parenting happens to point track */
+       MASK_PARENT_PLANE_TRACK = 1, /* parenting happens to plane track */
+};
+
 /* MaskSpline->flag */
 /* reserve (1 << 0) for SELECT */
 enum {
index 9ff4392242eabf2663dcc9a261b2363c2f5edfcc..109cdf5f1a107d402fc956c29c828ff8397aa9d7 100644 (file)
@@ -827,6 +827,10 @@ typedef struct NodeTranslateData {
        char pad[6];
 } NodeTranslateData;
 
+typedef struct NodePlaneTrackDeformData {
+       char tracking_object[64];
+       char plane_track_name[64];
+} NodePlaneTrackDeformData;
 
 typedef struct NodeShaderScript {
        int mode;
index 04cd69bc5aeef9a4a096d83c36e10e4df4a112c7..f81ac4dab0642e473ffbc66d48b27344a54ceba5 100644 (file)
@@ -144,6 +144,44 @@ typedef struct MovieTrackingTrack {
        struct bGPdata *gpd;        /* grease-pencil data */
 } MovieTrackingTrack;
 
+typedef struct MovieTrackingPlaneMarker {
+       /* Corners of the plane in the following order:
+        *
+        *       Y
+        *       ^
+        *       | (3) --- (2)
+        *       |  |       |
+        *       |  |       |
+        *       |  |       |
+        *       | (0) --- (1)
+        *       +-------------> X
+        *
+        * The coordinates are stored in frame normalized coordinates.
+        */
+       float corners[4][2];
+
+       int framenr;    /* Number of frame plane marker is associated with */
+       int flag;       /* Marker's flag (alive, ...) */
+} MovieTrackingPlaneMarker;
+
+typedef struct MovieTrackingPlaneTrack {
+       struct MovieTrackingPlaneTrack *next, *prev;
+
+       char name[64];  /* MAX_NAME */
+
+       MovieTrackingTrack **point_tracks;  /* Array of point tracks used to define this plane.
+                                              Each element is a pointer to MovieTrackingTrack. */
+       int point_tracksnr, pad;  /* Number of tracks in point_tracks array. */
+
+       MovieTrackingPlaneMarker *markers;   /* Markers in the plane track */
+       int markersnr;                       /* Count of markers in track (size of markers array) */
+
+       int flag;    /* flags (selection, ...) */
+
+       /* Runtime data */
+       int last_marker, pad2;               /* Most recently used marker */
+} MovieTrackingPlaneTrack;
+
 typedef struct MovieTrackingSettings {
        int flag;
 
@@ -225,6 +263,7 @@ typedef struct MovieTrackingObject {
        float scale;            /* scale of object solution in amera space */
 
        ListBase tracks;        /* list of tracks use to tracking this object */
+       ListBase plane_tracks;  /* list of plane tracks used by this object */
        MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */
 
        /* reconstruction options */
@@ -280,9 +319,11 @@ typedef struct MovieTracking {
        MovieTrackingSettings settings; /* different tracking-related settings */
        MovieTrackingCamera camera;     /* camera intrinsics */
        ListBase tracks;                /* list of tracks used for camera object */
+       ListBase plane_tracks;          /* list of plane tracks used by camera object */
        MovieTrackingReconstruction reconstruction; /* reconstruction data for camera object */
        MovieTrackingStabilization stabilization;   /* stabilization data */
-       MovieTrackingTrack *act_track;      /* active track */
+       MovieTrackingTrack *act_track;             /* active track */
+       MovieTrackingPlaneTrack *act_plane_track;  /* active plane track */
 
        ListBase objects;
        int objectnr, tot_object;       /* index of active object and total number of objects */
@@ -432,4 +473,16 @@ enum {
        TRACKING_COVERAGE_OK         = 2
 };
 
+/* MovieTrackingPlaneMarker->flag */
+enum {
+       PLANE_MARKER_DISABLED = (1 << 0),
+       PLANE_MARKER_TRACKED  = (1 << 1),
+};
+
+/* MovieTrackingPlaneTrack->flag */
+enum {
+       PLANE_TRACK_HIDDEN = (1 << 1),
+       PLANE_TRACK_LOCKED = (1 << 2),
+};
+
 #endif  /* __DNA_TRACKING_TYPES_H__ */
index 65e6b15d676b8b7426b8859c91818b744286a3bd..6a5fc3932696f0c36e4a454581cad27b2811bda6 100644 (file)
@@ -84,21 +84,33 @@ static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr)
                        MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, parent->parent);
 
                        if (object) {
-                               MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, object, parent->sub_parent);
+                               int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
 
-                               if (track) {
-                                       int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
-                                       MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_framenr);
-                                       float marker_pos_ofs[2], parmask_pos[2];
-                                       MovieClipUser user = {0};
+                               if (parent->type == MASK_PARENT_POINT_TRACK) {
+                                       MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, object, parent->sub_parent);
 
-                                       BKE_movieclip_user_set_frame(&user, scene->r.cfra);
+                                       if (track) {
+                                               MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_framenr);
+                                               float marker_pos_ofs[2], parmask_pos[2];
+                                               MovieClipUser user = {0};
 
-                                       add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
+                                               BKE_movieclip_user_set_frame(&user, scene->r.cfra);
 
-                                       BKE_mask_coord_from_movieclip(clip, &user, parmask_pos, marker_pos_ofs);
+                                               add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
 
-                                       copy_v2_v2(parent->parent_orig, parmask_pos);
+                                               BKE_mask_coord_from_movieclip(clip, &user, parmask_pos, marker_pos_ofs);
+
+                                               copy_v2_v2(parent->parent_orig, parmask_pos);
+                                       }
+                               }
+                               else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+                                       MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, object, parent->sub_parent);
+                                       if (plane_track) {
+                                               MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+
+                                               memcpy(parent->parent_corners_orig, plane_marker->corners, sizeof(parent->parent_corners_orig));
+                                               zero_v2(parent->parent_orig);
+                                       }
                                }
                        }
                }
@@ -513,6 +525,11 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
                {ID_MC, "MOVIECLIP", ICON_SEQUENCE, "Movie Clip", ""},
                {0, NULL, 0, NULL, NULL}};
 
+       static EnumPropertyItem parent_type_items[] = {
+               {MASK_PARENT_POINT_TRACK, "POINT_TRACK", 0, "Point Track", ""},
+               {MASK_PARENT_PLANE_TRACK, "PLANE_TRACK", 0, "Plane Track", ""},
+               {0, NULL, 0, NULL, NULL}};
+
        srna = RNA_def_struct(brna, "MaskParent", NULL);
        RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for masking element");
 
@@ -535,6 +552,12 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
        RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used");
        RNA_def_property_update(prop, 0, "rna_Mask_update_parent");
 
+       /* type */
+       prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, parent_type_items);
+       RNA_def_property_ui_text(prop, "Parent Type", "Parent Type");
+       RNA_def_property_update(prop, 0, "rna_Mask_update_parent");
+
        /* parent */
        prop = RNA_def_property(srna, "parent", PROP_STRING, PROP_NONE);
        RNA_def_property_ui_text(prop, "Parent", "Name of parent object in specified data block to which parenting happens");
index 535c279c02ff76ceaf82f5c6e11dcd1a2bb8c048..3b594ab096112148e93e86a50c7f29f2d8a78fe6 100644 (file)
@@ -5919,6 +5919,29 @@ static void def_cmp_translate(StructRNA *srna)
        RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 }
 
+static void def_cmp_planetrackdeform(StructRNA *srna)
+{
+       PropertyRNA *prop;
+
+       prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "id");
+       RNA_def_property_struct_type(prop, "MovieClip");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Movie Clip", "");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+       RNA_def_struct_sdna_from(srna, "NodePlaneTrackDeformData", "storage");
+
+       prop = RNA_def_property(srna, "tracking_object", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "tracking_object");
+       RNA_def_property_ui_text(prop, "Tracking Object", "");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "plane_track_name", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "plane_track_name");
+       RNA_def_property_ui_text(prop, "Plane Track", "");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
 
 /* -- Texture Nodes --------------------------------------------------------- */
 
index 4c47bbf93a60942ac1d027e216c4023384b82218..c92af884b1be00f33f569251369a33f1ea617dd4 100644 (file)
@@ -95,6 +95,13 @@ static void rna_trackingTracks_begin(CollectionPropertyIterator *iter, PointerRN
        rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL);
 }
 
+static void rna_trackingPlaneTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+       MovieClip *clip = (MovieClip *)ptr->id.data;
+
+       rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
+}
+
 static void rna_trackingObjects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
        MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -146,6 +153,27 @@ static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value)
                clip->tracking.act_track = NULL;
 }
 
+static PointerRNA rna_tracking_active_plane_track_get(PointerRNA *ptr)
+{
+       MovieClip *clip = (MovieClip *)ptr->id.data;
+       MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
+
+       return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingPlaneTrack, act_plane_track);
+}
+
+static void rna_tracking_active_plane_track_set(PointerRNA *ptr, PointerRNA value)
+{
+       MovieClip *clip = (MovieClip *)ptr->id.data;
+       MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *) value.data;
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+       int index = BLI_findindex(plane_tracks_base, plane_track);
+
+       if (index >= 0)
+               clip->tracking.act_plane_track = plane_track;
+       else
+               clip->tracking.act_plane_track = NULL;
+}
+
 static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
 {
        MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -197,6 +225,71 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, int value)
        }
 }
 
+static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value)
+{
+       MovieClip *clip = (MovieClip *) ptr->id.data;
+       MovieTracking *tracking = &clip->tracking;
+       MovieTrackingPlaneTrack *plane_track;
+       MovieTrackingPlaneMarker *plane_marker = (MovieTrackingPlaneMarker *) ptr->data;
+
+       /* TODO(sergey): Need to support editing markers from object's tracks */
+
+       plane_track = tracking->plane_tracks.first;
+       while (plane_track) {
+               if (plane_marker >= plane_track->markers &&
+                   plane_marker < plane_track->markers + plane_track->markersnr)
+               {
+                       break;
+               }
+
+               plane_track = plane_track->next;
+       }
+
+       if (plane_track) {
+               MovieTrackingPlaneMarker new_plane_marker = *plane_marker;
+               new_plane_marker.framenr = value;
+
+               BKE_tracking_plane_marker_delete(plane_track, plane_marker->framenr);
+               BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker);
+       }
+}
+
+static char *rna_trackingPlaneTrack_path(PointerRNA *ptr)
+{
+       MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
+       char name_esc[sizeof(plane_track->name) * 2];
+       BLI_strescape(name_esc, plane_track->name, sizeof(name_esc));
+       return BLI_sprintfN("tracking.plane_tracks[\"%s\"]", name_esc);
+}
+
+static void rna_trackingPlaneTrack_name_set(PointerRNA *ptr, const char *value)
+{
+       MovieClip *clip = (MovieClip *)ptr->id.data;
+       MovieTracking *tracking = &clip->tracking;
+       MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
+       ListBase *plane_tracks_base = &tracking->plane_tracks;
+
+       BLI_strncpy(plane_track->name, value, sizeof(plane_track->name));
+
+       /* TODO: it's a bit difficult to find list track came from knowing just
+        *       movie clip ID and MovieTracking structure, so keep this naive
+        *       search for a while */
+       if (BLI_findindex(plane_tracks_base, plane_track) < 0) {
+               MovieTrackingObject *object = tracking->objects.first;
+
+               while (object) {
+                       if (BLI_findindex(&object->plane_tracks, plane_track)) {
+                               plane_tracks_base = &object->plane_tracks;
+                               break;
+                       }
+
+                       object = object->next;
+               }
+       }
+
+       BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
+}
+
 static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr))
 {
        return BLI_sprintfN("tracking.camera");
@@ -294,6 +387,20 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po
        }
 }
 
+static void rna_trackingObject_plane_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+       MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
+
+       if (object->flag & TRACKING_OBJECT_CAMERA) {
+               MovieClip *clip = (MovieClip *)ptr->id.data;
+
+               rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
+       }
+       else {
+               rna_iterator_listbase_begin(iter, &object->plane_tracks, NULL);
+       }
+}
+
 static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr)
 {
        MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
@@ -1188,6 +1295,115 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
 }
 
+static void rna_def_trackingPlaneMarker(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna = RNA_def_struct(brna, "MovieTrackingPlaneMarker", NULL);
+       RNA_def_struct_ui_text(srna, "Movie Tracking Plane Marker Data", "Match-moving plane marker data for tracking");
+
+       /* frame */
+       prop = RNA_def_property(srna, "frame", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "framenr");
+       RNA_def_property_ui_text(prop, "Frame", "Frame number marker is keyframed on");
+       RNA_def_property_int_funcs(prop, NULL, "rna_trackingPlaneMarker_frame_set", NULL);
+       RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, 0);
+
+       /* Corners */
+       prop = RNA_def_property(srna, "corners", PROP_FLOAT, PROP_MATRIX);
+       RNA_def_property_float_sdna(prop, NULL, "corners");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x2);
+       RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+       RNA_def_property_ui_text(prop, "Corners",
+                                "Array of coordinates which represents UI rectange corners in "
+                                "frame normalized coordinates");
+       RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+
+       /* enable */
+       prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", PLANE_MARKER_DISABLED);
+       RNA_def_property_ui_text(prop, "Mode", "Is marker muted for current frame");
+       RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+}
+
+static void rna_def_trackingPlaneMarkers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+       StructRNA *srna;
+       //FunctionRNA *func;
+       //PropertyRNA *parm;
+
+       RNA_def_property_srna(cprop, "MovieTrackingPlaneMarkers");
+       srna = RNA_def_struct(brna, "MovieTrackingPlaneMarkers", NULL);
+       RNA_def_struct_sdna(srna, "MovieTrackingPlaneTrack");
+       RNA_def_struct_ui_text(srna, "Movie Tracking Plane Markers", "Collection of markers for movie tracking plane track");
+
+       /*
+       func = RNA_def_function(srna, "find_frame", "rna_trackingMarkers_find_frame");
+       RNA_def_function_ui_description(func, "Get marker for specified frame");
+       parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame",
+                          "Frame number to find marker for", MINFRAME, MAXFRAME);
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+       RNA_def_boolean(func, "exact", TRUE, "Exact",
+                       "Get marker at exact frame number rather than get estimated marker");
+       parm = RNA_def_pointer(func, "marker", "MovieTrackingMarker", "", "Marker for specified frame");
+       RNA_def_function_return(func, parm);
+
+       func = RNA_def_function(srna, "insert_frame", "rna_trackingMarkers_insert_frame");
+       RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip");
+       parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame",
+                          "Frame number to insert marker to", MINFRAME, MAXFRAME);
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+       RNA_def_float_vector(func, "co", 2, 0, -1.0, 1.0, "Coordinate",
+                            "Place new marker at the given frame using specified in normalized space coordinates",
+                            -1.0, 1.0);
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+       parm = RNA_def_pointer(func, "marker", "MovieTrackingMarker", "", "Newly created marker");
+       RNA_def_function_return(func, parm);
+
+       func = RNA_def_function(srna, "delete_frame", "rna_trackingMarkers_delete_frame");
+       RNA_def_function_ui_description(func, "Delete marker at specified frame");
+       parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame",
+                          "Frame number to delete marker from", MINFRAME, MAXFRAME);
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+       */
+}
+
+static void rna_def_trackingPlaneTrack(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       rna_def_trackingPlaneMarker(brna);
+
+       srna = RNA_def_struct(brna, "MovieTrackingPlaneTrack", NULL);
+       RNA_def_struct_path_func(srna, "rna_trackingPlaneTrack_path");
+       RNA_def_struct_ui_text(srna, "Movie tracking plane track data", "Match-moving plane track data for tracking");
+       RNA_def_struct_ui_icon(srna, ICON_ANIM_DATA);
+
+       /* name */
+       prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Name", "Unique name of track");
+       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_trackingPlaneTrack_name_set");
+       RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2);
+       RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+       RNA_def_struct_name_property(srna, prop);
+
+       /* markers */
+       prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_struct_type(prop, "MovieTrackingPlaneMarker");
+       RNA_def_property_collection_sdna(prop, NULL, "markers", "markersnr");
+       RNA_def_property_ui_text(prop, "Markers", "Collection of markers in track");
+       rna_def_trackingPlaneMarkers(brna, prop);
+
+       /* select */
+       prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+       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);
+}
+
 static void rna_def_trackingStabilization(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -1373,6 +1589,37 @@ static void rna_def_trackingTracks(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
 }
 
+static void rna_def_trackingPlaneTracks(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       //FunctionRNA *func;
+       PropertyRNA *prop;
+       //PropertyRNA *parm;
+
+       srna = RNA_def_struct(brna, "MovieTrackingPlaneTracks", NULL);
+       RNA_def_struct_sdna(srna, "MovieTracking");
+       RNA_def_struct_ui_text(srna, "Movie Plane Tracks", "Collection of movie tracking plane tracks");
+
+       /* TODO(sergey): Need to support tracks API. */
+
+#if 0
+       func = RNA_def_function(srna, "new", "rna_trackingTracks_new");
+       RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+       RNA_def_function_ui_description(func, "Create new motion track in this movie clip");
+       RNA_def_string(func, "name", "", 0, "", "Name of new track");
+       RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add track on", MINFRAME, MAXFRAME);
+       parm = RNA_def_pointer(func, "track", "MovieTrackingTrack", "", "Newly created track");
+       RNA_def_function_return(func, parm);
+#endif
+
+       /* active plane track */
+       prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+       RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", NULL, NULL);
+       RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+       RNA_def_property_ui_text(prop, "Active Plane Track", "Active plane track in this tracking data object");
+}
+
 static void rna_def_trackingObjectTracks(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -1400,6 +1647,35 @@ static void rna_def_trackingObjectTracks(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
 }
 
+static void rna_def_trackingObjectPlaneTracks(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       //FunctionRNA *func;
+       PropertyRNA *prop;
+       //PropertyRNA *parm;
+
+       srna = RNA_def_struct(brna, "MovieTrackingObjectPlaneTracks", NULL);
+       RNA_def_struct_sdna(srna, "MovieTrackingObject");
+       RNA_def_struct_ui_text(srna, "Plane Tracks", "Collection of tracking plane tracks");
+
+#if 0
+       func = RNA_def_function(srna, "new", "rna_trackingObject_tracks_new");
+       RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+       RNA_def_function_ui_description(func, "create new motion track in this movie clip");
+       RNA_def_string(func, "name", "", 0, "", "Name of new track");
+       RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add tracks on", MINFRAME, MAXFRAME);
+       parm = RNA_def_pointer(func, "track", "MovieTrackingTrack", "", "Newly created track");
+       RNA_def_function_return(func, parm);
+#endif
+
+       /* active track */
+       prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "MovieTrackingTrack");
+       RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", NULL, NULL);
+       RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+       RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
+}
+
 static void rna_def_trackingObject(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -1432,6 +1708,15 @@ static void rna_def_trackingObject(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
        RNA_def_property_srna(prop, "MovieTrackingObjectTracks");
 
+       /* plane tracks */
+       prop = RNA_def_property(srna, "plane_tracks", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_funcs(prop, "rna_trackingObject_plane_tracks_begin", "rna_iterator_listbase_next",
+                                         "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+                                         NULL, NULL, NULL, NULL);
+       RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+       RNA_def_property_ui_text(prop, "Plane Tracks", "Collection of plane tracks in this tracking data object");
+       RNA_def_property_srna(prop, "MovieTrackingObjectPlaneTracks");
+
        /* reconstruction */
        prop = RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "MovieTrackingReconstruction");
@@ -1549,8 +1834,11 @@ static void rna_def_tracking(BlenderRNA *brna)
        rna_def_trackingSettings(brna);
        rna_def_trackingCamera(brna);
        rna_def_trackingTrack(brna);
+       rna_def_trackingPlaneTrack(brna);
        rna_def_trackingTracks(brna);
+       rna_def_trackingPlaneTracks(brna);
        rna_def_trackingObjectTracks(brna);
+       rna_def_trackingObjectPlaneTracks(brna);
        rna_def_trackingStabilization(brna);
        rna_def_trackingReconstruction(brna);
        rna_def_trackingObject(brna);
@@ -1577,6 +1865,15 @@ static void rna_def_tracking(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
        RNA_def_property_srna(prop, "MovieTrackingTracks");
 
+       /* tracks */
+       prop = RNA_def_property(srna, "plane_tracks", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_funcs(prop, "rna_trackingPlaneTracks_begin", "rna_iterator_listbase_next",
+                                         "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+                                         NULL, NULL, NULL, NULL);
+       RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+       RNA_def_property_ui_text(prop, "Plane Tracks", "Collection of plane tracks in this tracking data object");
+       RNA_def_property_srna(prop, "MovieTrackingPlaneTracks");
+
        /* stabilization */
        prop = RNA_def_property(srna, "stabilization", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "MovieTrackingStabilization");
index 64261246e3d31c2b2cda94b9161325a4df439ac1..4ac75c15efe6c71e7b56c166c6c4541e8f301de3 100644 (file)
@@ -92,6 +92,7 @@ set(SRC
        composite/nodes/node_composite_normal.c
        composite/nodes/node_composite_normalize.c
        composite/nodes/node_composite_outputFile.c
+       composite/nodes/node_composite_planetrackdeform.c
        composite/nodes/node_composite_premulkey.c
        composite/nodes/node_composite_rgb.c
        composite/nodes/node_composite_rotate.c
index 626e7955b08d648836e0c05db23440218eda790b..4320e0436ced1ff9a791b023d8adcced97b97218 100644 (file)
@@ -137,6 +137,7 @@ void register_node_type_cmp_bokehblur(void);
 void register_node_type_cmp_switch(void);
 void register_node_type_cmp_pixelate(void);
 void register_node_type_cmp_trackpos(void);
+void register_node_type_cmp_planetrackdeform(void);
 
 void node_cmp_rlayers_force_hidden_passes(struct bNode *node);
 
index 0b526fcde0ec6be2df24f871afa18f0e6c6500d3..eeec40c911f719f5e67f42336fba57d9a0ac43f8 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -200,6 +201,7 @@ DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN,   def_cmp_keyingscreen,   "KEYIN
 DefNode( CompositorNode, CMP_NODE_KEYING,         def_cmp_keying,         "KEYING",         Keying,           "Keying",            ""              )
 DefNode( CompositorNode, CMP_NODE_TRACKPOS,       def_cmp_trackpos,       "TRACKPOS",       TrackPos,         "Track Position",    ""              )
 DefNode( CompositorNode, CMP_NODE_PIXELATE,       0,                      "PIXELATE",       Pixelate,         "Pixelate",          ""              )
+DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform",""              )
 
 DefNode( TextureNode,    TEX_NODE_OUTPUT,         def_tex_output,         "OUTPUT",         Output,           "Output",            ""              )
 DefNode( TextureNode,    TEX_NODE_CHECKER,        0,                      "CHECKER",        Checker,          "Checker",           ""              )
diff --git a/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c b/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
new file mode 100644 (file)
index 0000000..7a15d63
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation,
+ *                 Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_planetrackdeform.c
+ *  \ingroup cmpnodes
+ */
+
+
+#include "node_composite_util.h"
+
+static bNodeSocketTemplate cmp_node_planetrackdeform_in[] = {
+       {   SOCK_RGBA,  1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
+       {   -1, 0, ""   }
+};
+
+static bNodeSocketTemplate cmp_node_planetrackdeform_out[] = {
+       {       SOCK_RGBA,   0,  N_("Image")},
+       {       SOCK_FLOAT,  0,  N_("Plane")},
+       {       -1, 0, ""       }
+};
+
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+       NodePlaneTrackDeformData *data = MEM_callocN(sizeof(NodePlaneTrackDeformData), "node plane track deform data");
+
+       node->storage = data;
+}
+
+void register_node_type_cmp_planetrackdeform(void)
+{
+       static bNodeType ntype;
+
+       cmp_node_type_base(&ntype, CMP_NODE_PLANETRACKDEFORM, "Plane Track Deform", NODE_CLASS_DISTORT, 0);
+       node_type_socket_templates(&ntype, cmp_node_planetrackdeform_in, cmp_node_planetrackdeform_out);
+       node_type_init(&ntype, init);
+       node_type_storage(&ntype, "NodePlaneTrackDeformData", node_free_standard_storage, node_copy_standard_storage);
+
+       nodeRegisterType(&ntype);
+}