Merging r42442 through r42457 from trunk into soc-2011-tomato
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 6 Dec 2011 09:27:18 +0000 (09:27 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 6 Dec 2011 09:27:18 +0000 (09:27 +0000)
38 files changed:
extern/libmv/libmv-capi.cpp
extern/libmv/libmv-capi.h
extern/libmv/libmv/numeric/tinyvector.cc [new file with mode: 0644]
extern/libmv/libmv/tracking/brute_region_tracker.cc
extern/libmv/libmv/tracking/esm_region_tracker.cc
extern/libmv/libmv/tracking/esm_region_tracker.h
extern/libmv/third_party/ssba/README.libmv [changed mode: 0644->0755]
intern/ghost/intern/GHOST_System.cpp
release/scripts/presets/camera/Nikon_D35.py [new file with mode: 0644]
release/scripts/startup/bl_ui/properties_object_constraint.py
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/interface/interface_draw.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/object/object_constraint.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_editor.c
source/blender/editors/space_clip/clip_graph_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_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_constraint.c
source/blender/makesrna/intern/rna_tracking.c

index dd98d0828dcc2dcd1e66937830e1afe4c665a9e2..1835c53b53f78acc1cb168dc0421712e7d018f71 100644 (file)
@@ -111,12 +111,13 @@ void libmv_setLoggingVerbosity(int verbosity)
 
 /* ************ RegionTracker ************ */
 
-libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size)
+libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size, double minimum_correlation)
 {
        libmv::EsmRegionTracker *esm_region_tracker = new libmv::EsmRegionTracker;
        esm_region_tracker->half_window_size = half_window_size;
        esm_region_tracker->max_iterations = max_iterations;
        esm_region_tracker->min_determinant = 1e-4;
+       esm_region_tracker->minimum_correlation = minimum_correlation;
 
        libmv::PyramidRegionTracker *pyramid_region_tracker =
                new libmv::PyramidRegionTracker(esm_region_tracker, pyramid_level);
@@ -124,12 +125,13 @@ libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyram
        return (libmv_RegionTracker *)pyramid_region_tracker;
 }
 
-libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size)
+libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size, double minimum_correlation)
 {
        libmv::EsmRegionTracker *esm_region_tracker = new libmv::EsmRegionTracker;
        esm_region_tracker->half_window_size = half_window_size;
        esm_region_tracker->max_iterations = max_iterations;
        esm_region_tracker->min_determinant = 1e-4;
+       esm_region_tracker->minimum_correlation = minimum_correlation;
 
        libmv::BruteRegionTracker *brute_region_tracker = new libmv::BruteRegionTracker;
        brute_region_tracker->half_window_size = half_window_size;
index c5e61d69c56cdd2180e6faaabf250ad1147780b3..e10d4ef842ae3d80bddc1cb187b06275249f3344 100644 (file)
@@ -43,8 +43,8 @@ void libmv_startDebugLogging(void);
 void libmv_setLoggingVerbosity(int verbosity);
 
 /* RegionTracker */
-struct libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size);
-struct libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size);
+struct libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size, double minimum_correlation);
+struct libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size, double minimum_correlation);
 int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const float *ima1, const float *ima2,
                        int width, int height, double  x1, double  y1, double *x2, double *y2);
 void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker);
diff --git a/extern/libmv/libmv/numeric/tinyvector.cc b/extern/libmv/libmv/numeric/tinyvector.cc
new file mode 100644 (file)
index 0000000..e69de29
index a416710ad2bae9cccd0bdbfe92323768dfb17fb4..2c7f613ee4a6b2bf7deccc24ee541003c8424117 100644 (file)
 
 #if !defined(__APPLE__) && !defined(__FreeBSD__)
 // Needed for memalign on Linux and _aligned_alloc on Windows.
-#ifdef FREE_WINDOWS
-/* make sure _aligned_malloc is included */
-#ifdef __MSVCRT_VERSION__
-#undef __MSVCRT_VERSION__
-#endif
-
-#define __MSVCRT_VERSION__ 0x0700
-#endif
-
 #include <malloc.h>
 #else
 // Apple's malloc is 16-byte aligned, and does not have malloc.h, so include
index 844b5ff3cb9853e52110f341db4eb3845551675e..9784b61c0684fb615a4c8650cc6b171865029583 100644 (file)
@@ -273,10 +273,30 @@ bool EsmRegionTracker::Track(const FloatImage &image1,
 
     // If the step was accepted, then check for termination.
     if (d.squaredNorm() < min_update_squared_distance) {
-      if (new_error > reasonable_error) {
-        LG << "Update size shrank but reasonable error ("
-           << reasonable_error << ") not achieved; failing.";
-        return true; // XXX
+      // Compute the Pearson product-moment correlation coefficient to check
+      // for sanity.
+      // TODO(keir): Put this somewhere smarter.
+      double sX=0,sY=0,sXX=0,sYY=0,sXY=0;
+      for (int r = 0; r < width; ++r) {
+        for (int c = 0; c < width; ++c) {
+          double x = image_and_gradient1_sampled(r, c, 0);
+          double y = image_and_gradient2_sampled[new_image](r, c, 0);
+          sX += x;
+          sY += y;
+          sXX += x*x;
+          sYY += y*y;
+          sXY += x*y;
+        }
+      }
+      double N = width*width;
+      sX /= N, sY /= N, sXX /= N, sYY /= N, sXY /= N;
+      double correlation = (sXY-sX*sY)/sqrt(double((sXX-sX*sX)*(sYY-sY*sY)));
+      LG << "Final correlation: " << correlation;
+
+      if (correlation < minimum_correlation) {
+        LG << "Correlation " << correlation << " greater than "
+           << minimum_correlation << "; bailing.";
+        return false;
       }
       LG << "Successful track in " << (i + 1) << " iterations.";
       return true;
index c63417201ad8058b975fe2ef8b7a8d7432a82080..602b32f16754c7836714182109fe558401f92e97 100644 (file)
@@ -38,7 +38,8 @@ struct EsmRegionTracker : public RegionTracker {
         max_iterations(16),
         min_determinant(1e-6),
         min_update_squared_distance(1e-4),
-        sigma(0.9) {}
+        sigma(0.9),
+        minimum_correlation(0.78) {}
   
   virtual ~EsmRegionTracker() {}
 
@@ -54,6 +55,7 @@ struct EsmRegionTracker : public RegionTracker {
   double min_determinant;
   double min_update_squared_distance;
   double sigma;
+  double minimum_correlation;
 };
 
 }  // namespace libmv
old mode 100644 (file)
new mode 100755 (executable)
index 839e014aff6d4fbad16ffcbfad3cd5e9373a1741..afc54d3c6a025139d33653365a29cf116decf3be 100644 (file)
@@ -136,7 +136,7 @@ bool GHOST_System::validWindow(GHOST_IWindow* window)
 
 
 GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
-                                                                                        const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+                                                                                        const bool stereoVisual)
 {
        GHOST_TSuccess success = GHOST_kFailure;
        GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager")
@@ -148,7 +148,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
                        success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
                        if (success == GHOST_kSuccess) {
                                //GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
-                               success = createFullScreenWindow((GHOST_Window**)window, stereoVisual, numOfAASamples);
+                               success = createFullScreenWindow((GHOST_Window**)window, stereoVisual);
                                if (success == GHOST_kSuccess) {
                                        m_windowManager->beginFullScreen(*window, stereoVisual);
                                }
@@ -330,7 +330,7 @@ GHOST_TSuccess GHOST_System::exit()
 }
 
 
-GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const bool stereoVisual)
 {
        GHOST_TSuccess success;
        GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager")
@@ -344,8 +344,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const
                                        0, 0, settings.xPixels, settings.yPixels,
                                        GHOST_kWindowStateFullScreen,
                                        GHOST_kDrawingContextTypeOpenGL,
-                                       stereoVisual,
-                                       numOfAASamples);
+                                       stereoVisual);
                success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess;
        }
        return success;
diff --git a/release/scripts/presets/camera/Nikon_D35.py b/release/scripts/presets/camera/Nikon_D35.py
new file mode 100644 (file)
index 0000000..e6dc62d
--- /dev/null
@@ -0,0 +1,4 @@
+import bpy
+bpy.context.object.data.sensor_width = 36.0
+bpy.context.object.data.sensor_height = 23.9
+bpy.context.object.data.sensor_fit = 'HORIZONTAL'
index 038d7a38fd637acacd9baeec8b56c4663d257322..f88f501ab1f0d13b2d501c1224c7500cd4592e1f 100644 (file)
@@ -763,6 +763,7 @@ class ConstraintButtonsPanel():
         if not con.use_active_clip:
             layout.prop(con, "clip")
 
+        layout.prop(con, "object")
         layout.prop(con, "track")
 
         layout.operator("clip.constraint_to_fcurve")
@@ -775,6 +776,16 @@ class ConstraintButtonsPanel():
 
         layout.operator("clip.constraint_to_fcurve")
 
+    def OBJECT_SOLVER(self, context, layout, con):
+        layout.prop(con, "use_active_clip")
+
+        if not con.use_active_clip:
+            layout.prop(con, "clip")
+
+        layout.prop(con, "object")
+
+        layout.operator("clip.constraint_to_fcurve")
+
     def SCRIPT(self, context, layout, con):
         layout.label("Blender 2.5 has no py-constraints")
 
index 39b78ce8cdcd6ffd2ee19eab0eb8a0e0b7595ee1..139f674d6e80f02c043a8e1ffc61d275df82316b 100644 (file)
@@ -70,7 +70,13 @@ class CLIP_HT_header(Header):
         row.template_ID(sc, "clip", open='clip.open')
 
         if clip:
-            r = clip.tracking.reconstruction
+            tracking = clip.tracking
+            active = tracking.objects.active
+
+            if active and not active.is_camera:
+                r = active.reconstruction
+            else:
+                r = tracking.reconstruction
 
             if r.is_valid:
                 layout.label(text="Average solve error: %.4f" %
@@ -129,8 +135,7 @@ class CLIP_PT_tools_marker(Panel):
 
             if settings.default_tracker == 'KLT':
                 col.prop(settings, "default_pyramid_levels")
-            elif settings.default_tracker == 'SAD':
-                col.prop(settings, "default_correlation_min")
+            col.prop(settings, "default_correlation_min")
 
             col.separator()
 
@@ -198,10 +203,18 @@ class CLIP_PT_tools_solve(Panel):
     def draw(self, context):
         layout = self.layout
         clip = context.space_data.clip
-        settings = clip.tracking.settings
+        tracking = clip.tracking
+        settings = tracking.settings
+        tracking_object = tracking.objects.active
 
         col = layout.column(align=True)
-        col.operator("clip.solve_camera", text="Camera Motion")
+
+        if tracking_object.is_camera:
+            solve_text = "Camera Motion"
+        else:
+            solve_text = "Object Motion"
+
+        col.operator("clip.solve_camera", text=solve_text)
         col.operator("clip.clear_solution")
 
         col = layout.column(align=True)
@@ -209,6 +222,7 @@ class CLIP_PT_tools_solve(Panel):
         col.prop(settings, "keyframe_b")
 
         col = layout.column(align=True)
+        col.active = tracking_object.is_camera
         col.label(text="Refine:")
         col.prop(settings, "refine_intrinsics", text="")
 
@@ -317,6 +331,37 @@ class CLIP_PT_tools_grease_pencil(Panel):
         row.prop(context.tool_settings, "use_grease_pencil_sessions")
 
 
+class CLIP_PT_objects(Panel):
+    bl_space_type = 'CLIP_EDITOR'
+    bl_region_type = 'UI'
+    bl_label = "Objects"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        sc = context.space_data
+
+        return sc.clip
+
+    def draw(self, context):
+        layout = self.layout
+        sc = context.space_data
+        clip = context.space_data.clip
+        tracking = clip.tracking
+
+        row = layout.row()
+        row.template_list(tracking, "objects", tracking, "active_object_index", rows=3)
+
+        sub = row.column(align=True)
+
+        sub.operator("clip.tracking_object_new", icon='ZOOMIN', text="")
+        sub.operator("clip.tracking_object_remove", icon='ZOOMOUT', text="")
+
+        active = tracking.objects.active
+        if active:
+            layout.prop(active, "name")
+
+
 class CLIP_PT_track(Panel):
     bl_space_type = 'CLIP_EDITOR'
     bl_region_type = 'UI'
@@ -353,9 +398,15 @@ class CLIP_PT_track(Panel):
         layout.template_track(sc, "scopes")
 
         row = layout.row(align=True)
-        row.prop(act_track, "use_red_channel", text="R", toggle=True)
-        row.prop(act_track, "use_green_channel", text="G", toggle=True)
-        row.prop(act_track, "use_blue_channel", text="B", toggle=True)
+        sub = row.row()
+        sub.prop(act_track, "use_red_channel", text="R", toggle=True)
+        sub.prop(act_track, "use_green_channel", text="G", toggle=True)
+        sub.prop(act_track, "use_blue_channel", text="B", toggle=True)
+
+        row.separator()
+
+        sub = row.row()
+        sub.prop(act_track, "use_grayscale_preview", text="B/W", toggle=True)
 
         layout.separator()
 
@@ -497,8 +548,7 @@ class CLIP_PT_track_settings(Panel):
 
             if active.tracker == 'KLT':
                 col.prop(active, "pyramid_levels")
-            elif active.tracker == 'SAD':
-                col.prop(active, "correlation_min")
+            col.prop(active, "correlation_min")
 
             col.separator()
             col.prop(active, "frames_limit")
index e55d40ebfe5aa99a89a035ec25dfe67918cca961..6c43493d1d4df20c6add1ebee4f5d0099f365928 100644 (file)
 
 struct bGPDlayer;
 struct ImBuf;
+struct ListBase;
 struct MovieReconstructContext;
 struct MovieTrackingTrack;
 struct MovieTrackingMarker;
 struct MovieTracking;
 struct MovieTrackingContext;
+struct MovieTrackingObject;
 struct MovieClipUser;
 struct MovieDistortion;
 struct Camera;
@@ -49,8 +51,8 @@ void BKE_tracking_init_settings(struct MovieTracking *tracking);
 void BKE_tracking_clamp_track(struct MovieTrackingTrack *track, int event);
 void BKE_tracking_track_flag(struct MovieTrackingTrack *track, int area, int flag, int clear);
 
-struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, float x, float y,
-                       int framenr, int width, int height);
+struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, struct ListBase *tracksbase,
+                       float x, float y, int framenr, int width, int height);
 void BKE_tracking_insert_marker(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
 void BKE_tracking_delete_marker(struct MovieTrackingTrack *track, int framenr);
 
@@ -72,16 +74,27 @@ struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTra
 struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
                        struct MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]);
 
-void BKE_track_unique_name(struct MovieTracking *tracking, struct MovieTrackingTrack *track);
+void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track);
 
-struct MovieTrackingTrack *BKE_tracking_named_track(struct MovieTracking *tracking, const char *name);
+struct MovieTrackingTrack *BKE_tracking_named_track(struct MovieTracking *tracking, struct MovieTrackingObject *object, const char *name);
 struct MovieTrackingTrack *BKE_tracking_indexed_track(struct MovieTracking *tracking, int tracknr);
 
 void BKE_tracking_camera_shift(struct MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty);
 void BKE_tracking_camera_to_blender(struct MovieTracking *tracking, struct Scene *scene, struct Camera *camera, int width, int height);
 
 void BKE_get_tracking_mat(struct Scene *scene, struct Object *ob, float mat[4][4]);
-void BKE_tracking_projection_matrix(struct MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4]);
+void BKE_tracking_projection_matrix(struct MovieTracking *tracking, struct MovieTrackingObject *object,
+                       int framenr, int winx, int winy, float mat[4][4]);
+
+struct ListBase *BKE_tracking_get_tracks(struct MovieTracking *tracking);
+struct MovieTrackingReconstruction *BKE_tracking_get_reconstruction(struct MovieTracking *tracking);
+
+struct MovieTrackingTrack *BKE_tracking_active_track(struct MovieTracking *tracking);
+struct MovieTrackingObject *BKE_tracking_active_object(struct MovieTracking *tracking);
+struct MovieTrackingObject *BKE_tracking_get_camera_object(struct MovieTracking *tracking);
+struct ListBase *BKE_tracking_object_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
+struct MovieTrackingReconstruction *BKE_tracking_object_reconstruction(struct MovieTracking *tracking,
+                       struct MovieTrackingObject *object);
 
 /* 2D tracking */
 struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user,
@@ -92,20 +105,23 @@ void BKE_tracking_sync_user(struct MovieClipUser *user, struct MovieTrackingCont
 int BKE_tracking_next(struct MovieTrackingContext *context);
 
 /* Camera solving */
-int BKE_tracking_can_reconstruct(struct MovieTracking *tracking, char *error_msg, int error_size);
+int BKE_tracking_can_reconstruct(struct MovieTracking *tracking, struct MovieTrackingObject *object,
+                       char *error_msg, int error_size);
 
 struct MovieReconstructContext* BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking,
-                       int keyframe1, int keyframe2, int width, int height);
+                       struct MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height);
 void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context);
 void BKE_tracking_solve_reconstruction(struct MovieReconstructContext *context,
                        short *stop, short *do_update, float *progress, char *stats_message, int message_size);
 int BKE_tracking_finish_reconstruction(struct MovieReconstructContext *context, struct MovieTracking *tracking);
 
-struct MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(struct MovieTracking *tracking, int framenr);
-void BKE_tracking_get_interpolated_camera(struct MovieTracking *tracking, int framenr, float mat[4][4]);
+struct MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(struct MovieTracking *tracking,
+                       struct MovieTrackingObject *object, int framenr);
+void BKE_tracking_get_interpolated_camera(struct MovieTracking *tracking,
+                       struct MovieTrackingObject *object, int framenr, float mat[4][4]);
 
 /* Feature detection */
-void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ImBuf *imbuf,
+void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ListBase *tracksbase, struct ImBuf *imbuf,
                        int framenr, int margin, int min_trackness, int min_distance, struct bGPDlayer *layer,
                        int place_outside_layer);
 
@@ -127,8 +143,14 @@ void BKE_tracking_distortion_destroy(struct MovieDistortion *distortion);
 struct ImBuf *BKE_tracking_undistort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan);
 struct ImBuf *BKE_tracking_distort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan);
 
+/* Object tracking */
+struct MovieTrackingObject *BKE_tracking_new_object(struct MovieTracking *tracking, const char *name);
+void BKE_tracking_remove_object(struct MovieTracking *tracking, struct MovieTrackingObject *object);
+void BKE_tracking_object_unique_name(struct MovieTracking *tracking, struct MovieTrackingObject *object);
+struct MovieTrackingObject *BKE_tracking_named_object(struct MovieTracking *tracking, const char *name);
+
 /* Select */
-void BKE_tracking_select_track(struct MovieTracking *tracking, struct MovieTrackingTrack *track, int area, int extend);
+void BKE_tracking_select_track(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend);
 void BKE_tracking_deselect_track(struct MovieTrackingTrack *track, int area);
 
 #define TRACK_SELECTED(track)                          ((((track)->flag&TRACK_HIDDEN)==0) && ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT))
index 6f29594f811be000a4aa78ba6091bcdb31fe389d..9d8aae3bb52b54f1aa955421338ca7c71a554766 100644 (file)
@@ -3953,67 +3953,95 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
        Scene *scene= cob->scene;
        bFollowTrackConstraint *data= con->data;
        MovieClip *clip= data->clip;
+       MovieTracking *tracking;
        MovieTrackingTrack *track;
-       
+       MovieTrackingObject *tracking_object;
+
        if (data->flag & FOLLOWTRACK_ACTIVECLIP)
                clip= scene->clip;
-       
+
        if (!clip || !data->track[0])
                return;
-       
-       track= BKE_tracking_named_track(&clip->tracking, data->track);
-       
+
+       tracking= &clip->tracking;
+
+       if(data->object[0])
+               tracking_object= BKE_tracking_named_object(tracking, data->object);
+       else
+               tracking_object= BKE_tracking_get_camera_object(tracking);
+
+       if(!tracking_object)
+               return;
+
+       track= BKE_tracking_named_track(tracking, tracking_object, data->track);
+
        if (!track)
                return;
-       
+
        if (data->flag & FOLLOWTRACK_USE_3D_POSITION) {
                if (track->flag & TRACK_HAS_BUNDLE) {
-                       float pos[3], mat[4][4], obmat[4][4];
-                       
-                       copy_m4_m4(obmat, cob->matrix);
-                       
-                       BKE_get_tracking_mat(cob->scene, NULL, mat);
+                       MovieTracking *tracking= &clip->tracking;
+                       float pos[3], mat[4][4];
+
+                       if((tracking_object->flag&TRACKING_OBJECT_CAMERA)==0) {
+                               Object *camob= scene->camera;
+                               float obmat[4][4], imat[4][4];
+
+                               if(!camob)
+                                       return;
+
+                               copy_m4_m4(mat, camob->obmat);
+
+                               BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
+
+                               invert_m4_m4(imat, obmat);
+                               mul_m4_m4m4(mat, imat, mat);
+                       }
+                       else {
+                               BKE_get_tracking_mat(cob->scene, NULL, mat);
+                       }
+
                        mul_v3_m4v3(pos, mat, track->bundle_pos);
-                       
-                       cob->matrix[3][0] += pos[0];
-                       cob->matrix[3][1] += pos[1];
-                       cob->matrix[3][2] += pos[2];
+
+                       cob->matrix[3][0] = pos[0];
+                       cob->matrix[3][1] = pos[1];
+                       cob->matrix[3][2] = pos[2];
                }
        } 
        else {
-               Object *camob= cob->scene->camera;
-               
+               Object *camob= scene->camera;
+
                if (camob) {
                        MovieClipUser user;
                        MovieTrackingMarker *marker;
                        float vec[3], disp[3], axis[3], mat[4][4];
                        float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp);
                        float len, d;
-                       
+
                        where_is_object_mat(scene, camob, mat);
-                       
+
                        /* camera axis */
                        vec[0]= 0.0f;
                        vec[1]= 0.0f;
                        vec[2]= 1.0f;
                        mul_v3_m4v3(axis, mat, vec);
-                       
+
                        /* distance to projection plane */
                        copy_v3_v3(vec, cob->matrix[3]);
                        sub_v3_v3(vec, mat[3]);
                        project_v3_v3v3(disp, vec, axis);
-                       
+
                        len= len_v3(disp);
-                       
+
                        if (len > FLT_EPSILON) {
                                CameraParams params;
                                float pos[2], rmat[4][4];
-                               
+
                                user.framenr= scene->r.cfra;
                                marker= BKE_tracking_get_marker(track, user.framenr);
-                               
+
                                add_v2_v2v2(pos, marker->pos, track->offset);
-                               
+
                                camera_params_init(&params);
                                camera_params_from_object(&params, camob);
 
@@ -4021,35 +4049,35 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
                                        vec[0]= params.ortho_scale * (pos[0]-0.5f+params.shiftx);
                                        vec[1]= params.ortho_scale * (pos[1]-0.5f+params.shifty);
                                        vec[2]= -len;
-                                       
+
                                        if (aspect > 1.0f) vec[1] /= aspect;
                                        else vec[0] *= aspect;
-                                       
+
                                        mul_v3_m4v3(disp, camob->obmat, vec);
-                                       
+
                                        copy_m4_m4(rmat, camob->obmat);
                                        zero_v3(rmat[3]);
                                        mul_m4_m4m4(cob->matrix, rmat, cob->matrix);
-                                       
+
                                        copy_v3_v3(cob->matrix[3], disp);
                                }
                                else {
                                        d= (len*params.sensor_x) / (2.0f*params.lens);
-                                       
+
                                        vec[0]= d*(2.0f*(pos[0]+params.shiftx)-1.0f);
                                        vec[1]= d*(2.0f*(pos[1]+params.shifty)-1.0f);
                                        vec[2]= -len;
-                                       
+
                                        if (aspect > 1.0f) vec[1] /= aspect;
                                        else vec[0] *= aspect;
-                                       
+
                                        mul_v3_m4v3(disp, camob->obmat, vec);
-                                       
+
                                        /* apply camera rotation so Z-axis would be co-linear */
                                        copy_m4_m4(rmat, camob->obmat);
                                        zero_v3(rmat[3]);
                                        mul_m4_m4m4(cob->matrix, rmat, cob->matrix);
-                                       
+
                                        copy_v3_v3(cob->matrix[3], disp);
                                }
                        }
@@ -4095,16 +4123,19 @@ static void camerasolver_evaluate (bConstraint *con, bConstraintOb *cob, ListBas
        Scene *scene= cob->scene;
        bCameraSolverConstraint *data= con->data;
        MovieClip *clip= data->clip;
-       
+
        if (data->flag & CAMERASOLVER_ACTIVECLIP)
                clip= scene->clip;
-       
+
        if (clip) {
                float mat[4][4], obmat[4][4];
-               
-               BKE_tracking_get_interpolated_camera(&clip->tracking, scene->r.cfra, mat);
-               
+               MovieTracking *tracking= &clip->tracking;
+               MovieTrackingObject *object= BKE_tracking_get_camera_object(tracking);
+
+               BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat);
+
                copy_m4_m4(obmat, cob->matrix);
+
                mul_m4_m4m4(cob->matrix, mat, obmat);
        }
 }
@@ -4125,6 +4156,76 @@ static bConstraintTypeInfo CTI_CAMERASOLVER = {
        camerasolver_evaluate /* evaluate */
 };
 
+/* ----------- Object Solver ------------- */
+
+static void objectsolver_new_data (void *cdata)
+{
+       bObjectSolverConstraint *data= (bObjectSolverConstraint *)cdata;
+
+       data->clip = NULL;
+       data->flag |= OBJECTSOLVER_ACTIVECLIP;
+}
+
+static void objectsolver_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
+{
+       bObjectSolverConstraint *data= con->data;
+
+       func(con, (ID**)&data->clip, userdata);
+}
+
+static void objectsolver_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
+{
+       Scene *scene= cob->scene;
+       bObjectSolverConstraint *data= con->data;
+       MovieClip *clip= data->clip;
+
+       if (data->flag & OBJECTSOLVER_ACTIVECLIP)
+               clip= scene->clip;
+
+       if(!scene->camera)
+               return;
+
+       if (clip) {
+               MovieTracking *tracking= &clip->tracking;
+               MovieTrackingObject *object;
+
+               object= BKE_tracking_named_object(tracking, data->object);
+
+               if(object) {
+                       float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4];
+
+                       where_is_object_mat(scene, scene->camera, cammat);
+
+                       BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat);
+
+                       invert_m4_m4(camimat, cammat);
+
+                       copy_m4_m4(cammat, scene->camera->obmat);
+                       copy_m4_m4(obmat, cob->matrix);
+
+                       invert_m4_m4(imat, mat);
+
+                       mul_serie_m4(cob->matrix, cammat, imat, camimat, obmat, NULL, NULL, NULL, NULL);
+               }
+       }
+}
+
+static bConstraintTypeInfo CTI_OBJECTSOLVER = {
+       CONSTRAINT_TYPE_OBJECTSOLVER, /* type */
+       sizeof(bObjectSolverConstraint), /* size */
+       "Object Solver", /* name */
+       "bObjectSolverConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       objectsolver_id_looper, /* id looper */
+       NULL, /* copy data */
+       objectsolver_new_data, /* new data */
+       NULL, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       NULL, /* get target matrix */
+       objectsolver_evaluate /* evaluate */
+};
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
  * and operations that involve constraint specific code.
@@ -4165,6 +4266,7 @@ static void constraints_init_typeinfo (void)
        constraintsTypeInfo[25]= &CTI_PIVOT;                    /* Pivot Constraint */
        constraintsTypeInfo[26]= &CTI_FOLLOWTRACK;              /* Follow Track Constraint */
        constraintsTypeInfo[27]= &CTI_CAMERASOLVER;             /* Camera Solver Constraint */
+       constraintsTypeInfo[28]= &CTI_OBJECTSOLVER;             /* Object Solver Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only
index 4eaf49dc679acdb7535ff663fcbd496b5924ebbb..b0776a0b51ba2feb3f772dbe93e17f9daddb72aa 100644 (file)
@@ -647,16 +647,21 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
                        continue;
 
                /* special case for camera tracking -- it doesn't use targets to define relations */
-               if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER)) {
+               if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+                       int depends_on_camera= 0;
+
                        if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
                                bFollowTrackConstraint *data= (bFollowTrackConstraint *)con->data;
 
-                               if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0]) {
-                                       if(scene->camera) {
-                                               node2 = dag_get_node(dag, scene->camera);
-                                               dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
-                                       }
-                               }
+                               if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0])
+                                       depends_on_camera= 1;
+                       }
+                       else if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER)
+                               depends_on_camera= 1;
+
+                       if(depends_on_camera && scene->camera) {
+                               node2 = dag_get_node(dag, scene->camera);
+                               dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name);
                        }
 
                        dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation");
@@ -2160,7 +2165,7 @@ static void dag_object_time_update_flags(Object *ob)
                        
                        if (cti) {
                                /* special case for camera tracking -- it doesn't use targets to define relations */
-                               if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER)) {
+                               if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
                                        ob->recalc |= OB_RECALC_OB;
                                }
                                else if (cti->get_constraint_targets) {
index 75d8ec584e85ddfeac56380258a89603b3b0ea40..04686e6a8976e3e19e6a58fd8869f68cdad068bb 100644 (file)
@@ -813,7 +813,8 @@ void BKE_movieclip_reload(MovieClip *clip)
 
 void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes)
 {
-       if(scopes->ok) return;
+       if(scopes->ok)
+               return;
 
        if(scopes->track_preview) {
                IMB_freeImBuf(scopes->track_preview);
@@ -824,8 +825,10 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
        scopes->track= NULL;
 
        if(clip) {
-               if(clip->tracking.act_track) {
-                       MovieTrackingTrack *track= clip->tracking.act_track;
+               MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking);
+
+               if(act_track) {
+                       MovieTrackingTrack *track= act_track;
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
 
                        if(marker->flag&MARKER_DISABLED) {
index 66c0c0265a1a734cc171e0a9cd6a597ff2ca49fa..e7f99990dc59cb435bf06d89fb7f2a42e8d853ad 100644 (file)
@@ -54,6 +54,7 @@
 #include "BKE_movieclip.h"
 #include "BKE_object.h"
 #include "BKE_scene.h"
+#include "BKE_main.h"  // XXX: ...
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
@@ -77,7 +78,6 @@ void BKE_tracking_init_settings(MovieTracking *tracking)
        tracking->camera.units= CAMERA_UNITS_MM;
 
        tracking->settings.default_tracker= TRACKER_KLT;
-       tracking->settings.default_pyramid_levels= 2;
        tracking->settings.default_minimum_correlation= 0.75;
        tracking->settings.default_pattern_size= 11;
        tracking->settings.default_search_size= 51;
@@ -90,6 +90,8 @@ void BKE_tracking_init_settings(MovieTracking *tracking)
        tracking->stabilization.locinf= 1.0f;
        tracking->stabilization.rotinf= 1.0f;
        tracking->stabilization.maxscale= 2.0f;
+
+       BKE_tracking_new_object(tracking, "Camera");
 }
 
 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
@@ -208,7 +210,7 @@ void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int
        }
 }
 
-MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, float y,
+MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
                        int framenr, int width, int height)
 {
        MovieTrackingTrack *track;
@@ -251,8 +253,8 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, flo
        if(track->tracker == TRACKER_KLT)
                BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS);
 
-       BLI_addtail(&tracking->tracks, track);
-       BKE_track_unique_name(tracking, track);
+       BLI_addtail(tracksbase, track);
+       BKE_track_unique_name(tracksbase, track);
 
        return track;
 }
@@ -524,18 +526,44 @@ void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack
        dst_track->markersnr= tot;
 }
 
-void BKE_tracking_free(MovieTracking *tracking)
+static void tracking_tracks_free(ListBase *tracks)
 {
        MovieTrackingTrack *track;
 
-       for(track= tracking->tracks.first; track; track= track->next) {
+       for(track= tracks->first; track; track= track->next) {
                BKE_tracking_free_track(track);
        }
 
-       BLI_freelistN(&tracking->tracks);
+       BLI_freelistN(tracks);
+}
+
+static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
+{
+       if(reconstruction->cameras)
+               MEM_freeN(reconstruction->cameras);
+}
+
+static void tracking_object_free(MovieTrackingObject *object)
+{
+       tracking_tracks_free(&object->tracks);
+       tracking_reconstruction_free(&object->reconstruction);
+}
+
+static void tracking_objects_free(ListBase *objects)
+{
+       MovieTrackingObject *object;
+
+       for(object= objects->first; object; object= object->next)
+               tracking_object_free(object);
 
-       if(tracking->reconstruction.cameras)
-               MEM_freeN(tracking->reconstruction.cameras);
+       BLI_freelistN(objects);
+}
+
+void BKE_tracking_free(MovieTracking *tracking)
+{
+       tracking_tracks_free(&tracking->tracks);
+       tracking_reconstruction_free(&tracking->reconstruction);
+       tracking_objects_free(&tracking->objects);
 
        if(tracking->stabilization.scaleibuf)
                IMB_freeImBuf(tracking->stabilization.scaleibuf);
@@ -547,6 +575,9 @@ void BKE_tracking_free(MovieTracking *tracking)
 /*********************** tracks map *************************/
 
 typedef struct TracksMap {
+       char object_name[32];
+       int is_camera;
+
        int num_tracks;
        int customdata_size;
 
@@ -558,10 +589,13 @@ typedef struct TracksMap {
        int ptr;
 } TracksMap;
 
-static TracksMap *tracks_map_new(int num_tracks, int customdata_size)
+static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
 {
        TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap");
 
+       strcpy(map->object_name, object_name);
+       map->is_camera= is_camera;
+
        map->num_tracks= num_tracks;
        map->customdata_size= customdata_size;
 
@@ -607,10 +641,24 @@ static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *c
 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
 {
        MovieTrackingTrack *track;
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
        ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
-       ListBase *old_tracks= &tracking->tracks;
+       ListBase *old_tracks;
        int a;
 
+       if(map->is_camera) {
+               old_tracks= &tracking->tracks;
+       } else {
+               MovieTrackingObject *object= BKE_tracking_named_object(tracking, map->object_name);
+
+               if(!object) {
+                       /* object was deleted by user, create new one */
+                       object= BKE_tracking_new_object(tracking, map->object_name);
+               }
+
+               old_tracks= &object->tracks;
+       }
+
        /* duplicate currently operating tracks to temporary list.
           this is needed to keep names in unique state and it's faster to change names
           of currently operating tracks (if needed) */
@@ -634,7 +682,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
 
                        /* original track was found, re-use flags and remove this track */
                        if(cur) {
-                               if(cur==tracking->act_track)
+                               if(act_track)
                                        replace_sel= 1;
 
                                track->flag= cur->flag;
@@ -685,7 +733,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
                track= next;
        }
 
-       tracking->tracks= new_tracks;
+       *old_tracks= new_tracks;
 }
 
 static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata))
@@ -745,7 +793,9 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
        MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
        MovieTracking *tracking= &clip->tracking;
        MovieTrackingSettings *settings= &tracking->settings;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
+       MovieTrackingObject *object= BKE_tracking_active_object(tracking);
        int num_tracks= 0;
 
        context->settings= *settings;
@@ -755,7 +805,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
        context->first_time= 1;
 
        /* count */
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
@@ -770,12 +820,13 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
        if(num_tracks) {
                int width, height;
 
-               context->tracks_map= tracks_map_new(num_tracks, sizeof(TrackContext));
+               context->tracks_map= tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
+                                       num_tracks, sizeof(TrackContext));
 
                BKE_movieclip_get_size(clip, user, &width, &height);
 
                /* create tracking data */
-               track= tracking->tracks.first;
+               track= tracksbase->first;
                while(track) {
                        if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
                                MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
@@ -810,9 +861,9 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u
                                                        int level= MIN2(track->pyramid_levels, max_pyramid_levels);
 
                                                        if(track->tracker==TRACKER_KLT)
-                                                               track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy));
+                                                               track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy), track->minimum_correlation);
                                                        else
-                                                               track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy));
+                                                               track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy), track->minimum_correlation);
                                                }
                                                else if(track->tracker==TRACKER_SAD) {
                                                        track_context.pattern_size= MAX2(patx, paty);
@@ -862,29 +913,53 @@ void BKE_tracking_context_free(MovieTrackingContext *context)
        MEM_freeN(context);
 }
 
-static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track)
+/* zap channels from the imbuf that are disabled by the user. this can lead to
+ * better tracks sometimes. however, instead of simply zeroing the channels
+ * out, do a partial grayscale conversion so the display is better. */
+static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
 {
        int x, y;
+       float scale;
 
-       if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0)
+       if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0 && !grayscale)
                return;
 
+       /* If only some components are selected, it's important to rescale the result
+        * appropriately so that e.g. if only blue is selected, it's not zeroed out. */
+       scale = ((track->flag&TRACK_DISABLE_RED  ) ? 0.0f : 0.2126f) +
+               ((track->flag&TRACK_DISABLE_GREEN) ? 0.0f : 0.7152f) +
+               ((track->flag&TRACK_DISABLE_BLUE)  ? 0.0f : 0.0722f);
+
        for(y= 0; y<ibuf->y; y++) {
                for (x= 0; x<ibuf->x; x++) {
                        int pixel= ibuf->x*y + x;
 
                        if(ibuf->rect_float) {
                                float *rrgbf= ibuf->rect_float + pixel*4;
-
-                               if(track->flag&TRACK_DISABLE_RED)       rrgbf[0]= 0;
-                               if(track->flag&TRACK_DISABLE_GREEN)     rrgbf[1]= 0;
-                               if(track->flag&TRACK_DISABLE_BLUE)      rrgbf[2]= 0;
+                               float r = (track->flag&TRACK_DISABLE_RED)   ? 0.0f : rrgbf[0];
+                               float g = (track->flag&TRACK_DISABLE_GREEN) ? 0.0f : rrgbf[1];
+                               float b = (track->flag&TRACK_DISABLE_BLUE)  ? 0.0f : rrgbf[2];
+                               if (grayscale) {
+                                       float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
+                                       rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
+                               } else {
+                                       rrgbf[0] = r;
+                                       rrgbf[1] = g;
+                                       rrgbf[2] = b;
+                               }
                        } else {
                                char *rrgb= (char*)ibuf->rect + pixel*4;
-
-                               if(track->flag&TRACK_DISABLE_RED)       rrgb[0]= 0;
-                               if(track->flag&TRACK_DISABLE_GREEN)     rrgb[1]= 0;
-                               if(track->flag&TRACK_DISABLE_BLUE)      rrgb[2]= 0;
+                               char r = (track->flag&TRACK_DISABLE_RED)   ? 0 : rrgb[0];
+                               char g = (track->flag&TRACK_DISABLE_GREEN) ? 0 : rrgb[1];
+                               char b = (track->flag&TRACK_DISABLE_BLUE)  ? 0 : rrgb[2];
+                               if (grayscale) {
+                                       float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
+                                       rrgb[0] = rrgb[1] = rrgb[2] = gray;
+                               } else {
+                                       rrgb[0] = r;
+                                       rrgb[1] = g;
+                                       rrgb[2] = b;
+                               }
                        }
                }
        }
@@ -926,7 +1001,12 @@ static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTracki
                origin[1]= y1-margin;
        }
 
-       disable_imbuf_channels(tmpibuf, track);
+       if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
+                       (track->flag & TRACK_DISABLE_RED)       ||
+                       (track->flag & TRACK_DISABLE_GREEN)     ||
+                       (track->flag & TRACK_DISABLE_BLUE) ) {
+               disable_imbuf_channels(tmpibuf, track, 1 /* grayscale */);
+       }
 
        return tmpibuf;
 }
@@ -955,7 +1035,7 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT
        height= (track->search_max[1]-track->search_min[1])*ibuf->y;
 
        tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
-       disable_imbuf_channels(tmpibuf, track);
+       disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
 
        *width_r= width;
        *height_r= height;
@@ -967,14 +1047,11 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT
 
                        if(tmpibuf->rect_float) {
                                float *rrgbf= tmpibuf->rect_float + pixel*4;
-
                                *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2];
                        } else {
                                unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4;
-
                                *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f;
                        }
-
                        fp++;
                }
        }
@@ -996,14 +1073,11 @@ static unsigned char *get_ucharbuf(ImBuf *ibuf)
 
                        if(ibuf->rect_float) {
                                float *rrgbf= ibuf->rect_float + pixel*4;
-
                                *cp= FTOCHAR(0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]);
                        } else {
                                unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4;
-
                                *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
                        }
-
                        cp++;
                }
        }
@@ -1018,7 +1092,7 @@ static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track,
        unsigned char *pixels;
 
        tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
-       disable_imbuf_channels(tmpibuf, track);
+       disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
 
        *width_r= tmpibuf->x;
        *height_r= tmpibuf->y;
@@ -1348,6 +1422,8 @@ typedef struct MovieReconstructContext {
 
        struct libmv_Reconstruction *reconstruction;
 #endif
+       char object_name[32];
+       int is_camera;
 
        float focal_length;
        float principal_point[2];
@@ -1369,13 +1445,13 @@ typedef struct ReconstructProgressData {
 } ReconstructProgressData;
 
 #if WITH_LIBMV
-static struct libmv_Tracks *create_libmv_tracks(MovieTracking *tracking, int width, int height)
+static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height)
 {
        int tracknr= 0;
        MovieTrackingTrack *track;
        struct libmv_Tracks *tracks= libmv_tracksNew();
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                int a= 0;
 
@@ -1419,16 +1495,28 @@ static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *conte
 static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking)
 {
        struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
-       MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
+       MovieTrackingReconstruction *reconstruction= NULL;
        MovieReconstructedCamera *reconstructed;
        MovieTrackingTrack *track;
+       ListBase *tracksbase=  NULL;
        int ok= 1, tracknr= 0, a, origin_set= 0;
        int sfra= context->sfra, efra= context->efra;
        float imat[4][4];
 
+       if(context->is_camera) {
+               tracksbase= &tracking->tracks;
+               reconstruction= &tracking->reconstruction;
+       }
+       else {
+               MovieTrackingObject *object= BKE_tracking_named_object(tracking, context->object_name);
+
+               tracksbase= &object->tracks;
+               reconstruction= &object->reconstruction;
+       }
+
        unit_m4(imat);
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                double pos[3];
 
@@ -1494,7 +1582,7 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M
        }
 
        if(origin_set) {
-               track= tracking->tracks.first;
+               track= tracksbase->first;
                while(track) {
                        if(track->flag&TRACK_HAS_BUNDLE)
                                mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos);
@@ -1510,19 +1598,20 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M
 
 static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking)
 {
-       tracks_map_merge(context->tracks_map, tracking);
-
        /* take the intrinscis back from libmv */
        retrieve_libmv_reconstruct_intrinscis(context, tracking);
 
        return retrieve_libmv_reconstruct_tracks(context, tracking);
 }
 
-static int get_refine_intrinsics_flags(MovieTracking *tracking)
+static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object)
 {
        int refine= tracking->settings.refine_camera_intrinsics;
        int flags= 0;
 
+       if((object->flag&TRACKING_OBJECT_CAMERA)==0)
+               return 0;
+
        if(refine&REFINE_FOCAL_LENGTH)
                flags|= LIBMV_REFINE_FOCAL_LENGTH;
 
@@ -1538,13 +1627,13 @@ static int get_refine_intrinsics_flags(MovieTracking *tracking)
        return flags;
 }
 
-static int count_tracks_on_both_keyframes(MovieTracking *tracking)
+static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase)
 {
        int tot= 0;
        int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2;
        MovieTrackingTrack *track;
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(BKE_tracking_has_marker(track, frame1))
                        if(BKE_tracking_has_marker(track, frame2))
@@ -1557,10 +1646,12 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking)
 }
 #endif
 
-int BKE_tracking_can_reconstruct(MovieTracking *tracking, char *error_msg, int error_size)
+int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
 {
 #if WITH_LIBMV
-       if(count_tracks_on_both_keyframes(tracking)<8) {
+       ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
+
+       if(count_tracks_on_both_keyframes(tracking, tracksbase)<8) {
                BLI_strncpy(error_msg, "At least 8 tracks on both of keyframes are needed for reconstruction", error_size);
                return 0;
        }
@@ -1575,17 +1666,22 @@ int BKE_tracking_can_reconstruct(MovieTracking *tracking, char *error_msg, int e
 }
 
 MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking,
-                       int keyframe1, int keyframe2, int width, int height)
+                       MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height)
 {
        MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
        MovieTrackingCamera *camera= &tracking->camera;
+       ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
        float aspy= 1.0f/tracking->camera.pixel_aspect;
-       int num_tracks= BLI_countlist(&tracking->tracks);
+       int num_tracks= BLI_countlist(tracksbase);
        int sfra= INT_MAX, efra= INT_MIN;
        MovieTrackingTrack *track;
 
-       context->tracks_map= tracks_map_new(num_tracks, 0);
-       track= tracking->tracks.first;
+       strcpy(context->object_name, object->name);
+       context->is_camera = object->flag&TRACKING_OBJECT_CAMERA;
+
+       context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
+
+       track= tracksbase->first;
        while(track) {
                int first= 0, last= track->markersnr;
                MovieTrackingMarker *first_marker= &track->markers[0];
@@ -1618,10 +1714,10 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *
        context->efra= efra;
 
 #ifdef WITH_LIBMV
-       context->tracks= create_libmv_tracks(tracking, width, height*aspy);
+       context->tracks= create_libmv_tracks(tracksbase, width, height*aspy);
        context->keyframe1= keyframe1;
        context->keyframe2= keyframe2;
-       context->refine_flags= get_refine_intrinsics_flags(tracking);
+       context->refine_flags= get_refine_intrinsics_flags(tracking, object);
 #else
        (void) width;
        (void) height;
@@ -1718,8 +1814,22 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *
 
 int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking)
 {
-       tracking->reconstruction.error= context->reprojection_error;
-       tracking->reconstruction.flag|= TRACKING_RECONSTRUCTED;
+       MovieTrackingReconstruction *reconstruction;
+
+       tracks_map_merge(context->tracks_map, tracking);
+
+       if(context->is_camera) {
+               reconstruction= &tracking->reconstruction;
+       }
+       else {
+               MovieTrackingObject *object;
+
+               object= BKE_tracking_named_object(tracking, context->object_name);
+               reconstruction= &object->reconstruction;
+       }
+
+       reconstruction->error= context->reprojection_error;
+       reconstruction->flag|= TRACKING_RECONSTRUCTED;
 
 #ifdef WITH_LIBMV
        if(!retrieve_libmv_reconstruct(context, tracking))
@@ -1729,14 +1839,15 @@ int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTr
        return 1;
 }
 
-void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track)
+void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
 {
-       BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
+       BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
 }
 
-MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char *name)
+MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
 {
-       MovieTrackingTrack *track= tracking->tracks.first;
+       ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
+       MovieTrackingTrack *track= tracksbase->first;
 
        while(track) {
                if(!strcmp(track->name, name))
@@ -1748,9 +1859,8 @@ MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char
        return NULL;
 }
 
-static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int nearest)
+static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest)
 {
-       MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
        MovieReconstructedCamera *cameras= reconstruction->cameras;
        int a= 0, d= 1;
 
@@ -1802,21 +1912,31 @@ static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int
        return -1;
 }
 
-MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr)
+MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking,
+                       MovieTrackingObject *object, int framenr)
 {
-       int a= reconstruction_camera_index(tracking, framenr, 0);
+       MovieTrackingReconstruction *reconstruction;
+       int a;
+
+       reconstruction= BKE_tracking_object_reconstruction(tracking, object);
+       a= reconstruction_camera_index(reconstruction, framenr, 0);
 
        if(a==-1)
                return NULL;
 
-       return &tracking->reconstruction.cameras[a];
+       return &reconstruction->cameras[a];
 }
 
-void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, float mat[4][4])
+void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object,
+                       int framenr, float mat[4][4])
 {
-       MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
-       MovieReconstructedCamera *cameras= reconstruction->cameras;
-       int a= reconstruction_camera_index(tracking, framenr, 1);
+       MovieTrackingReconstruction *reconstruction;
+       MovieReconstructedCamera *cameras;
+       int a;
+
+       reconstruction= BKE_tracking_object_reconstruction(tracking, object);
+       cameras= reconstruction->cameras;
+       a= reconstruction_camera_index(reconstruction, framenr, 1);
 
        if(a==-1) {
                unit_m4(mat);
@@ -1868,7 +1988,8 @@ void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camer
        BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
 }
 
-void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4])
+void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
+                       int framenr, int winx, int winy, float mat[4][4])
 {
        MovieReconstructedCamera *camera;
        float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
@@ -1901,7 +2022,8 @@ void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int wi
 
        perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
 
-       camera= BKE_tracking_get_reconstructed_camera(tracking, framenr);
+       camera= BKE_tracking_get_reconstructed_camera(tracking, object, framenr);
+
        if(camera) {
                float imat[4][4];
 
@@ -1910,6 +2032,77 @@ void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int wi
        } else copy_m4_m4(mat, winmat);
 }
 
+ListBase *BKE_tracking_get_tracks(MovieTracking *tracking)
+{
+       MovieTrackingObject *object= BKE_tracking_active_object(tracking);
+
+       if(object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+               return &object->tracks;
+       }
+
+       return &tracking->tracks;
+}
+
+MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking)
+{
+       ListBase *tracksbase;
+
+       if(!tracking->act_track)
+               return NULL;
+
+       tracksbase= BKE_tracking_get_tracks(tracking);
+
+       /* check that active track is in current tracks list */
+       if(BLI_findindex(tracksbase, tracking->act_track) >= 0)
+               return tracking->act_track;
+
+       return NULL;
+}
+
+MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking)
+{
+       return BLI_findlink(&tracking->objects, tracking->objectnr);
+}
+
+MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking)
+{
+       MovieTrackingObject *object= tracking->objects.first;
+
+       while(object) {
+               if(object->flag & TRACKING_OBJECT_CAMERA)
+                       return object;
+
+               object= object->next;
+       }
+
+       return NULL;
+}
+
+ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object)
+{
+       if(object->flag & TRACKING_OBJECT_CAMERA) {
+               return &tracking->tracks;
+       }
+
+       return &object->tracks;
+}
+
+MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object)
+{
+       if(object->flag & TRACKING_OBJECT_CAMERA) {
+               return &tracking->reconstruction;
+       }
+
+       return &object->reconstruction;
+}
+
+MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking)
+{
+       MovieTrackingObject *object= BKE_tracking_active_object(tracking);
+
+       return BKE_tracking_object_reconstruction(tracking, object);
+}
+
 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
 {
        MovieTrackingCamera *camera= &tracking->camera;
@@ -1996,8 +2189,9 @@ static int point_in_layer(bGPDlayer *layer, float x, float y)
        return 0;
 }
 
-static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Features *features,
-                       int framenr, int width, int height, bGPDlayer *layer, int place_outside_layer)
+static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
+                       struct libmv_Features *features, int framenr, int width, int height,
+                       bGPDlayer *layer, int place_outside_layer)
 {
        int a;
 
@@ -2017,7 +2211,7 @@ static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Featur
                        ok= point_in_layer(layer, xu, yu)!=place_outside_layer;
 
                if(ok) {
-                       track= BKE_tracking_add_track(tracking, xu, yu, framenr, width, height);
+                       track= BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height);
                        track->flag|= SELECT;
                        track->pat_flag|= SELECT;
                        track->search_flag|= SELECT;
@@ -2026,7 +2220,7 @@ static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Featur
 }
 #endif
 
-void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf,
+void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
                        int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
                        int place_outside_layer)
 {
@@ -2034,11 +2228,13 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf,
        struct libmv_Features *features;
        unsigned char *pixels= get_ucharbuf(ibuf);
 
-       features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, margin, min_trackness, min_distance);
+       features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
+                       margin, min_trackness, min_distance);
 
        MEM_freeN(pixels);
 
-       retrieve_libmv_features(tracking, features, framenr, ibuf->x, ibuf->y, layer, place_outside_layer);
+       retrieve_libmv_features(tracking, tracksbase, features, framenr,
+                       ibuf->x, ibuf->y, layer, place_outside_layer);
 
        libmv_destroyFeatures(features);
 #else
@@ -2055,7 +2251,8 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf,
 
 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr)
 {
-       MovieTrackingTrack *track= tracking->tracks.first;
+       ListBase *tracksbase= &tracking->tracks;        /* XXX: need proper tracks base */
+       MovieTrackingTrack *track= tracksbase->first;
        int cur= 1;
 
        while(track) {
@@ -2080,6 +2277,8 @@ static int stabilization_median_point(MovieTracking *tracking, int framenr, floa
 
        INIT_MINMAX2(min, max);
 
+       (void) tracking;
+
        track= tracking->tracks.first;
        while(track) {
                if(track->flag&TRACK_USE_2D_STAB) {
@@ -2517,12 +2716,12 @@ ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int
 }
 
 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
-void BKE_tracking_select_track(MovieTracking *tracking, MovieTrackingTrack *track, int area, int extend)
+void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend)
 {
        if(extend) {
                BKE_tracking_track_flag(track, area, SELECT, 0);
        } else {
-               MovieTrackingTrack *cur= tracking->tracks.first;
+               MovieTrackingTrack *cur= tracksbase->first;
 
                while(cur) {
                        if(cur==track) {
@@ -2542,3 +2741,78 @@ void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area)
 {
        BKE_tracking_track_flag(track, area, SELECT, 1);
 }
+
+MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name)
+{
+       MovieTrackingObject *object= MEM_callocN(sizeof(MovieTrackingObject), "tracking object");
+
+       if(tracking->tot_object==0) {
+               /* first object is always camera */
+               BLI_strncpy(object->name, "Camera", sizeof(object->name));
+
+               object->flag|= TRACKING_OBJECT_CAMERA;
+       }
+       else {
+               BLI_strncpy(object->name, name, sizeof(object->name));
+       }
+
+       BLI_addtail(&tracking->objects, object);
+
+       tracking->tot_object++;
+       tracking->objectnr= BLI_countlist(&tracking->objects) - 1;
+
+       BKE_tracking_object_unique_name(tracking, object);
+
+       return object;
+}
+
+void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object)
+{
+       MovieTrackingTrack *track;
+       int index= BLI_findindex(&tracking->objects, object);
+
+       if(index<0)
+               return;
+
+       if(object->flag & TRACKING_OBJECT_CAMERA) {
+               /* object used for camera solving can't be deleted */
+               return;
+       }
+
+       track= object->tracks.first;
+       while(track) {
+               if(track==tracking->act_track)
+                       tracking->act_track= NULL;
+
+               track= track->next;
+       }
+
+       tracking_object_free(object);
+       BLI_freelinkN(&tracking->objects, object);
+
+       tracking->tot_object--;
+
+       if(index>0)
+               tracking->objectnr= index-1;
+       else
+               tracking->objectnr= 0;
+}
+
+void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
+{
+       BLI_uniquename(&tracking->objects, object, "Object", '.', offsetof(MovieTrackingObject, name), sizeof(object->name));
+}
+
+MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name)
+{
+       MovieTrackingObject *object= tracking->objects.first;
+
+       while(object) {
+               if(!strcmp(object->name, name))
+                       return object;
+
+               object= object->next;
+       }
+
+       return NULL;
+}
index 13e2ed49e6aaeb64b53c64af1fe0f36ac25447dc..6479c3ee04ddb8b42952777fcb03e1996d9af025 100644 (file)
@@ -5934,10 +5934,29 @@ static void lib_link_group(FileData *fd, Main *main)
 
 /* ***************** READ MOVIECLIP *************** */
 
+static void direct_link_movieReconstruction(FileData *fd, MovieTrackingReconstruction *reconstruction)
+{
+       reconstruction->cameras= newdataadr(fd, reconstruction->cameras);
+}
+
+static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase)
+{
+       MovieTrackingTrack *track;
+
+       link_list(fd, tracksbase);
+
+       track= tracksbase->first;
+       while(track) {
+               track->markers= newdataadr(fd, track->markers);
+
+               track= track->next;
+       }
+}
+
 static void direct_link_movieclip(FileData *fd, MovieClip *clip)
 {
        MovieTracking *tracking= &clip->tracking;
-       MovieTrackingTrack *track;
+       MovieTrackingObject *object;
 
        if(fd->movieclipmap) clip->cache= newmclipadr(fd, clip->cache);
        else clip->cache= NULL;
@@ -5945,16 +5964,8 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
        if(fd->movieclipmap) clip->tracking.camera.intrinsics= newmclipadr(fd, clip->tracking.camera.intrinsics);
        else clip->tracking.camera.intrinsics= NULL;
 
-       tracking->reconstruction.cameras= newdataadr(fd, tracking->reconstruction.cameras);
-
-       link_list(fd, &tracking->tracks);
-
-       track= tracking->tracks.first;
-       while(track) {
-               track->markers= newdataadr(fd, track->markers);
-
-               track= track->next;
-       }
+       direct_link_movieTracks(fd, &tracking->tracks);
+       direct_link_movieReconstruction(fd, &tracking->reconstruction);
 
        clip->tracking.act_track= newdataadr(fd, clip->tracking.act_track);
 
@@ -5965,6 +5976,16 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
        clip->tracking.stabilization.ok= 0;
        clip->tracking.stabilization.scaleibuf= NULL;
        clip->tracking.stabilization.rot_track= newdataadr(fd, clip->tracking.stabilization.rot_track);
+
+       link_list(fd, &tracking->objects);
+
+       object= tracking->objects.first;
+       while(object) {
+               direct_link_movieTracks(fd, &object->tracks);
+               direct_link_movieReconstruction(fd, &object->reconstruction);
+
+               object= object->next;
+       }
 }
 
 static void lib_link_movieclip(FileData *fd, Main *main)
@@ -12657,7 +12678,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
        /* put compatibility code here until next subversion bump */
        {
-               /* nothing! */
+               MovieClip *clip;
+
+               for (clip= main->movieclip.first; clip; clip= clip->id.next) {
+                       MovieTracking *tracking= &clip->tracking;
+
+                       if(tracking->objects.first == NULL)
+                               BKE_tracking_new_object(tracking, "Camera");
+               }
        }
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
index 00710e67cf2eac3fe21149e0ade0b9a3d7afde1e..4828e9703fb80b0a844ecc547650234f9c3a756f 100644 (file)
@@ -2522,6 +2522,27 @@ static void write_scripts(WriteData *wd, ListBase *idbase)
        }
 }
 
+static void write_movieTracks(WriteData *wd, ListBase *tracks)
+{
+       MovieTrackingTrack *track;
+
+       track= tracks->first;
+       while(track) {
+               writestruct(wd, DATA, "MovieTrackingTrack", 1, track);
+
+               if(track->markers)
+                       writestruct(wd, DATA, "MovieTrackingMarker", track->markersnr, track->markers);
+
+               track= track->next;
+       }
+}
+
+static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction)
+{
+       if(reconstruction->camnr)
+               writestruct(wd, DATA, "MovieReconstructedCamera", reconstruction->camnr, reconstruction->cameras);
+}
+
 static void write_movieclips(WriteData *wd, ListBase *idbase)
 {
        MovieClip *clip;
@@ -2530,20 +2551,20 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
        while(clip) {
                if(clip->id.us>0 || wd->current) {
                        MovieTracking *tracking= &clip->tracking;
-                       MovieTrackingTrack *track;
+                       MovieTrackingObject *object;
                        writestruct(wd, ID_MC, "MovieClip", 1, clip);
 
-                       if(tracking->reconstruction.camnr)
-                               writestruct(wd, DATA, "MovieReconstructedCamera", tracking->reconstruction.camnr, tracking->reconstruction.cameras);
+                       write_movieTracks(wd, &tracking->tracks);
+                       write_movieReconstruction(wd, &tracking->reconstruction);
 
-                       track= tracking->tracks.first;
-                       while(track) {
-                               writestruct(wd, DATA, "MovieTrackingTrack", 1, track);
+                       object= tracking->objects.first;
+                       while(object) {
+                               writestruct(wd, DATA, "MovieTrackingObject", 1, object);
 
-                               if(track->markers)
-                                       writestruct(wd, DATA, "MovieTrackingMarker", track->markersnr, track->markers);
+                               write_movieTracks(wd, &object->tracks);
+                               write_movieReconstruction(wd, &object->reconstruction);
 
-                               track= track->next;
+                               object= object->next;
                        }
                }
 
index f3a99ecf6b8a70606da7ee47b46467b0262794f3..767c6b0353cd87014b2c17f199f803c9c0425568 100644 (file)
@@ -1475,6 +1475,8 @@ static ImBuf *scale_trackpreview_ibuf(ImBuf *ibuf, float zoomx, float zoomy)
 {
        ImBuf *scaleibuf;
        int x, y, w= ibuf->x*zoomx, h= ibuf->y*zoomy;
+       const float max_x= ibuf->x-1.0f;
+       const float max_y= ibuf->y-1.0f;
        const float scalex= 1.0f/zoomx;
        const float scaley= 1.0f/zoomy;
 
@@ -1482,15 +1484,13 @@ static ImBuf *scale_trackpreview_ibuf(ImBuf *ibuf, float zoomx, float zoomy)
 
        for(y= 0; y<scaleibuf->y; y++) {
                for (x= 0; x<scaleibuf->x; x++) {
-                       int pixel= scaleibuf->x*y + x;
-                       int orig_pixel= ibuf->x*(int)(scaley*(float)y) + (int)(scalex*(float)x);
-                       char *rrgb= (char*)scaleibuf->rect + pixel*4;
-                       char *orig_rrgb= (char*)ibuf->rect + orig_pixel*4;
-
-                       rrgb[0]= orig_rrgb[0];
-                       rrgb[1]= orig_rrgb[1];
-                       rrgb[2]= orig_rrgb[2];
-                       rrgb[3]= orig_rrgb[3];
+                       float src_x= scalex*x;
+                       float src_y= scaley*y;
+
+                       CLAMP(src_x, 0, max_x);
+                       CLAMP(src_y, 0, max_y);
+
+                       bilinear_interpolation(ibuf, scaleibuf, src_x, src_y, x, y);
                }
        }
 
index 7f01d4f031da5683f6be81c5679b08990e84c75b..ea45337ddb3e5befc43c5778fc472dd794dcaa4d 100644 (file)
@@ -2198,6 +2198,17 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
                }
                uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0,  NULL);
        }
+       else if(itemptr->type == &RNA_MovieTrackingObject) {
+               MovieTrackingObject *tracking_object= (MovieTrackingObject*)itemptr->data;
+
+               split= uiLayoutSplit(sub, 0.75f, 0);
+               if(tracking_object->flag&TRACKING_OBJECT_CAMERA) {
+                       uiItemL(split, name, ICON_CAMERA_DATA);
+               }
+               else {
+                       uiItemL(split, name, ICON_OBJECT_DATA);
+               }
+       }
 
        /* There is a last chance to display custom controls (in addition to the name/label):
         * If the given item property group features a string property named as prop_list,
index 2a45a7df735bf7af3c3e6bf967ecf3f38f642531..7b9e809fffcb98b162e3a1fdd08c094a72554350 100644 (file)
@@ -408,8 +408,21 @@ static void test_constraints (Object *owner, bPoseChannel *pchan)
 
                                if((data->flag&CAMERASOLVER_ACTIVECLIP)==0) {
                                        if(data->clip != NULL && data->track[0]) {
-                                               if (!BKE_tracking_named_track(&data->clip->tracking, data->track))
+                                               MovieTracking *tracking= &data->clip->tracking;
+                                               MovieTrackingObject *tracking_object;
+
+                                               if(data->object[0])
+                                                       tracking_object= BKE_tracking_named_object(tracking, data->object);
+                                               else
+                                                       tracking_object= BKE_tracking_get_camera_object(tracking);
+
+                                               if(!tracking_object) {
                                                        curcon->flag |= CONSTRAINT_DISABLE;
+                                               }
+                                               else {
+                                                       if (!BKE_tracking_named_track(tracking, tracking_object, data->track))
+                                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               }
                                        }
                                        else curcon->flag |= CONSTRAINT_DISABLE;
                                }
index 3f9ec3f3c8292692951077a3d0f35a0973e58162..8f2398b156baa51594141d3914301ffdc5286cda 100644 (file)
@@ -96,6 +96,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
        float x;
        int *points, totseg, i, a;
        float sfra= SFRA, efra= EFRA, framelen= ar->winx/(efra-sfra+1);
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking);
 
        glEnable(GL_BLEND);
 
@@ -119,8 +120,8 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
        }
 
        /* track */
-       if(clip->tracking.act_track) {
-               MovieTrackingTrack *track= clip->tracking.act_track;
+       if(act_track) {
+               MovieTrackingTrack *track= act_track;
 
                for(i= sfra, a= 0; i <= efra; i++) {
                        int framenr;
@@ -835,8 +836,9 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
 {
        float x, y;
        MovieTracking* tracking= &clip->tracking;
-       MovieTrackingMarker *marker;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track, *act_track;
+       MovieTrackingMarker *marker;
        int framenr= sc->user.framenr;
        int undistort= sc->user.render_flag&MCLIP_PROXY_RENDER_UNDISTORT;
        float *marker_pos= NULL, *fp, *active_pos= NULL, cur_pos[2];
@@ -858,13 +860,13 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
        glMultMatrixf(sc->stabmat);
        glScalef(width, height, 0);
 
-       act_track= clip->tracking.act_track;
+       act_track= BKE_tracking_active_track(tracking);
 
        if(sc->user.render_flag&MCLIP_PROXY_RENDER_UNDISTORT) {
                int count= 0;
 
                /* count */
-               track= tracking->tracks.first;
+               track= tracksbase->first;
                while(track) {
                        if((track->flag&TRACK_HIDDEN)==0) {
                                marker= BKE_tracking_get_marker(track, framenr);
@@ -880,7 +882,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                if(count) {
                        marker_pos= MEM_callocN(2*sizeof(float)*count, "draw_tracking_tracks marker_pos");
 
-                       track= tracking->tracks.first;
+                       track= tracksbase->first;
                        fp= marker_pos;
                        while(track) {
                                if((track->flag&TRACK_HIDDEN)==0) {
@@ -902,7 +904,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
        }
 
        if(sc->flag&SC_SHOW_TRACK_PATH) {
-               track= tracking->tracks.first;
+               track= tracksbase->first;
                while(track) {
                        if((track->flag&TRACK_HIDDEN)==0)
                                draw_track_path(sc, clip, track);
@@ -912,7 +914,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
        }
 
        /* markers outline and non-selected areas */
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        fp= marker_pos;
        while(track) {
                if((track->flag&TRACK_HIDDEN)==0) {
@@ -936,7 +938,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
 
        /* selected areas only, so selection wouldn't be overlapped by
           non-selected areas */
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        fp= marker_pos;
        while(track) {
                if((track->flag&TRACK_HIDDEN)==0) {
@@ -974,15 +976,16 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
        }
 
        if(sc->flag&SC_SHOW_BUNDLES) {
+               MovieTrackingObject *object= BKE_tracking_active_object(tracking);
                float pos[4], vec[4], mat[4][4], aspy;
 
                glEnable(GL_POINT_SMOOTH);
                glPointSize(3.0f);
 
                aspy= 1.0f/clip->tracking.camera.pixel_aspect;
-               BKE_tracking_projection_matrix(tracking, framenr, width, height, mat);
+               BKE_tracking_projection_matrix(tracking, object, framenr, width, height, mat);
 
-               track= tracking->tracks.first;
+               track= tracksbase->first;
                while(track) {
                        if((track->flag&TRACK_HIDDEN)==0 && track->flag&TRACK_HAS_BUNDLE) {
                                marker= BKE_tracking_get_marker(track, framenr);
@@ -1027,7 +1030,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
 
        if(sc->flag&SC_SHOW_NAMES) {
                /* scaling should be cleared before drawing texts, otherwise font would also be scaled */
-               track= tracking->tracks.first;
+               track= tracksbase->first;
                fp= marker_pos;
                while(track) {
                        if((track->flag&TRACK_HIDDEN)==0) {
index c503614579214c902f39bb1433837805efced1a4..d75df0ab51e579ca48f5dde694ebbfdcee6c2630 100644 (file)
@@ -171,12 +171,13 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2])
        MovieClip *clip= ED_space_clip(sc);
        MovieTrackingTrack *track;
        int width, height, ok= 0;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
 
        INIT_MINMAX2(min, max);
 
        ED_space_clip_size(sc, &width, &height);
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track)) {
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr);
index 7b14783d4ca3c14884593ecf838993b808043fac..d1e7c86d473b6025f91e044964265b90e019ed0f 100644 (file)
@@ -177,6 +177,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
 {
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
        int width, height;
        struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } userdata;
 
@@ -188,13 +189,13 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc)
        /* non-selected knot handles */
        userdata.hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
        userdata.sel= 0;
-       userdata.act_track= clip->tracking.act_track;
+       userdata.act_track= act_track;
        UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale);
        clip_graph_tracking_values_iterate(sc, &userdata, tracking_segment_knot_cb, NULL, NULL);
 
        /* draw graph lines */
        glEnable(GL_BLEND);
-       clip_graph_tracking_values_iterate(sc, tracking->act_track, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb);
+       clip_graph_tracking_values_iterate(sc, act_track, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb);
        glDisable(GL_BLEND);
 
        /* selected knot handles on top of curves */
index 56ca1632bae001d780a2167fe713b95d520cb901..08d6bcf47bc80ce9c8e8b0d1ef963914c6d15bc3 100644 (file)
@@ -155,13 +155,14 @@ static int mouse_select_knot(bContext *C, float co[2], int extend)
        ARegion *ar= CTX_wm_region(C);
        View2D *v2d= &ar->v2d;
        MovieTracking *tracking= &clip->tracking;
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
        static const int delta= 6;
 
-       if(tracking->act_track) {
+       if(act_track) {
                MouseSelectUserData userdata;
 
                mouse_select_init_data(&userdata, co);
-               clip_graph_tracking_values_iterate_track(sc, tracking->act_track,
+               clip_graph_tracking_values_iterate_track(sc, act_track,
                                        &userdata, find_nearest_tracking_knot_cb, NULL, NULL);
 
                if(userdata.marker) {
@@ -191,6 +192,7 @@ static int mouse_select_curve(bContext *C, float co[2], int extend)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
        MouseSelectUserData userdata;
 
        mouse_select_init_data(&userdata, co);
@@ -198,12 +200,12 @@ static int mouse_select_curve(bContext *C, float co[2], int extend)
 
        if(userdata.track) {
                if(extend) {
-                       if(tracking->act_track==userdata.track) {
+                       if(act_track==userdata.track) {
                                /* currently only single curve can be selected (selected curve represents active track) */
-                               tracking->act_track= NULL;
+                               act_track= NULL;
                        }
                }
-               else if(tracking->act_track!=userdata.track) {
+               else if(act_track!=userdata.track) {
                        MovieTrackingMarker *marker;
                        SelectUserData selectdata = {SEL_DESELECT};
 
@@ -292,9 +294,11 @@ static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
 
-       if(tracking->act_track)
-               clip_delete_track(C, clip, tracking->act_track);
+       if(act_track)
+               clip_delete_track(C, clip, tracksbase, act_track);
 
        return OPERATOR_FINISHED;
 }
@@ -322,16 +326,17 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
 
-       if(tracking->act_track) {
+       if(act_track) {
                int a= 0;
-               MovieTrackingTrack *track= tracking->act_track;
 
-               while(a<track->markersnr) {
-                       MovieTrackingMarker *marker= &track->markers[a];
+               while(a<act_track->markersnr) {
+                       MovieTrackingMarker *marker= &act_track->markers[a];
 
                        if(marker->flag&MARKER_GRAPH_SEL)
-                               clip_delete_marker(C, clip, track, marker);
+                               clip_delete_marker(C, clip, tracksbase, act_track, marker);
                        else
                                a++;
                }
index da0b589652edda5bb171a74db55a429bf89e868e..38da4dd86ff7e413b68c917890b3823b447cb497 100644 (file)
@@ -92,8 +92,8 @@ void clip_graph_tracking_values_iterate(struct SpaceClip *sc, void *userdata,
 void clip_graph_tracking_iterate(struct SpaceClip *sc, void *userdata,
                        void (*func) (void *userdata, 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_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_view_center_to_point(struct SpaceClip *sc, float x, float y);
 
@@ -139,6 +139,9 @@ void CLIP_OT_stabilize_2d_remove(struct wmOperatorType *ot);
 void CLIP_OT_stabilize_2d_select(struct wmOperatorType *ot);
 void CLIP_OT_stabilize_2d_set_rotation(struct wmOperatorType *ot);
 
-void CLIP_OT_clean_tracks(wmOperatorType *ot);
+void CLIP_OT_clean_tracks(struct wmOperatorType *ot);
+
+void CLIP_OT_tracking_object_new(struct wmOperatorType *ot);
+void CLIP_OT_tracking_object_remove(struct wmOperatorType *ot);
 
 #endif /* ED_CLIP_INTERN_H */
index 649b278ab3d9d7b15b5ee27ba6d2a9ab57d85567..3ca8fc35c7fc1d3710ae9876200c3e5dd15bab3f 100644 (file)
@@ -119,9 +119,10 @@ void clip_graph_tracking_values_iterate(SpaceClip *sc, void *userdata,
 {
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track)) {
                        clip_graph_tracking_values_iterate_track(sc, track, userdata, func, segment_start, segment_end);
@@ -136,9 +137,10 @@ void clip_graph_tracking_iterate(SpaceClip *sc, void *userdata,
 {
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track)) {
                        int i;
@@ -158,14 +160,15 @@ void clip_graph_tracking_iterate(SpaceClip *sc, void *userdata,
        }
 }
 
-void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
+void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, MovieTrackingTrack *track)
 {
        MovieTracking *tracking= &clip->tracking;
        MovieTrackingStabilization *stab= &tracking->stabilization;
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
 
        int has_bundle= 0, update_stab= 0;
 
-       if(track==tracking->act_track)
+       if(track==act_track)
                tracking->act_track= NULL;
 
        if(track==stab->rot_track) {
@@ -179,7 +182,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
                has_bundle= 1;
 
        BKE_tracking_free_track(track);
-       BLI_freelinkN(&tracking->tracks, track);
+       BLI_freelinkN(tracksbase, track);
 
        WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
 
@@ -194,10 +197,10 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
                WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, NULL);
 }
 
-void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker)
+void clip_delete_marker(bContext *C, MovieClip *clip, ListBase *tracksbase, MovieTrackingTrack *track, MovieTrackingMarker *marker)
 {
        if(track->markersnr==1) {
-               clip_delete_track(C, clip, track);
+               clip_delete_track(C, clip, tracksbase, track);
        }
        else {
                BKE_tracking_delete_marker(track, marker->framenr);
index c8577f7760ef7168b7544092a51ac3ea9342ec48..01779a806b9818d397e4b65ded64a659ea1119e0 100644 (file)
@@ -372,6 +372,10 @@ static void clip_operatortypes(void)
        WM_operatortype_append(CLIP_OT_graph_select);
        WM_operatortype_append(CLIP_OT_graph_delete_curve);
        WM_operatortype_append(CLIP_OT_graph_delete_knot);
+
+       /* object tracking */
+       WM_operatortype_append(CLIP_OT_tracking_object_new);
+       WM_operatortype_append(CLIP_OT_tracking_object_remove);
 }
 
 static void clip_keymap(struct wmKeyConfig *keyconf)
index 3d004ab73da2d73cf723a5a3a44e0090e7716c91..59631e3a18165975f31ce2a2cf8f10d02a03cfc8 100644 (file)
@@ -117,14 +117,16 @@ static int space_clip_camera_poll(bContext *C)
 static void add_marker(SpaceClip *sc, float x, float y)
 {
        MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
        int width, height;
        
        ED_space_clip_size(sc, &width, &height);
 
-       track= BKE_tracking_add_track(&clip->tracking, x, y, sc->user.framenr, width, height);
+       track= BKE_tracking_add_track(tracking, tracksbase, x, y, sc->user.framenr, width, height);
 
-       BKE_tracking_select_track(&clip->tracking, track, TRACK_AREA_ALL, 0);
+       BKE_tracking_select_track(tracksbase, track, TRACK_AREA_ALL, 0);
 
        clip->tracking.act_track= track;
 }
@@ -191,13 +193,14 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
-       MovieTrackingTrack *track= tracking->tracks.first, *next;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *track= tracksbase->first, *next;
 
        while(track) {
                next= track->next;
 
                if(TRACK_VIEW_SELECTED(sc, track))
-                       clip_delete_track(C, clip, track);
+                       clip_delete_track(C, clip, tracksbase, track);
 
                track= next;
        }
@@ -230,7 +233,8 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
-       MovieTrackingTrack *track= clip->tracking.tracks.first, *next;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
+       MovieTrackingTrack *track= tracksbase->first, *next;
        int framenr= sc->user.framenr;
        int has_selection= 0;
 
@@ -243,7 +247,7 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
                        if(marker) {
                                has_selection|= track->markersnr>1;
 
-                               clip_delete_marker(C, clip, track, marker);
+                               clip_delete_marker(C, clip, tracksbase, track, marker);
                        }
                }
 
@@ -429,6 +433,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event)
        int width, height;
        float co[2];
        void *customdata= NULL;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
 
        ED_space_clip_size(sc, &width, &height);
 
@@ -437,7 +442,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event)
 
        ED_clip_mouse_pos(C, event, co);
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) {
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr);
@@ -721,12 +726,12 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
        return MIN4(d1, d2, d3, d4);
 }
 
-static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, MovieClip *clip, float co[2])
+static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2])
 {
        MovieTrackingTrack *track= NULL, *cur;
        float mindist= 0.0f;
 
-       cur= clip->tracking.tracks.first;
+       cur= tracksbase->first;
        while(cur) {
                MovieTrackingMarker *marker= BKE_tracking_get_marker(cur, sc->user.framenr);
 
@@ -764,10 +769,11 @@ static int mouse_select(bContext *C, float co[2], int extend)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
-       MovieTrackingTrack *act_track= tracking->act_track;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
        MovieTrackingTrack *track= NULL;        /* selected marker */
 
-       track= find_nearest_track(sc, clip, co);
+       track= find_nearest_track(sc, tracksbase, co);
 
        if(track) {
                int area= track_mouse_area(sc, co, track);
@@ -784,7 +790,7 @@ static int mouse_select(bContext *C, float co[2], int extend)
                        if(area==TRACK_AREA_POINT)
                                area= TRACK_AREA_ALL;
 
-                       BKE_tracking_select_track(tracking, track, area, extend);
+                       BKE_tracking_select_track(tracksbase, track, area, extend);
                        clip->tracking.act_track= track;
                }
        }
@@ -867,6 +873,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTrackingTrack *track;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        rcti rect;
        rctf rectf;
        int change= 0, mode, extend;
@@ -884,7 +891,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
        extend= RNA_boolean_get(op->ptr, "extend");
 
        /* do actual selection */
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if((track->flag&TRACK_HIDDEN)==0) {
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr);
@@ -952,6 +959,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        MovieClip *clip= ED_space_clip(sc);
        ARegion *ar= CTX_wm_region(C);
        MovieTrackingTrack *track;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        int x, y, radius, width, height, mode, change= 0;
        float zoomx, zoomy, offset[2], ellipse[2];
 
@@ -972,7 +980,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        ED_clip_point_stable_pos(C, x, y, &offset[0], &offset[1]);
 
        /* do selection */
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if((track->flag&TRACK_HIDDEN)==0) {
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr);
@@ -1026,13 +1034,14 @@ static int select_all_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTrackingTrack *track= NULL;        /* selected track */
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        int action= RNA_enum_get(op->ptr, "action");
        int framenr= sc->user.framenr;
        int has_selection= 0;
 
        if(action == SEL_TOGGLE){
                action= SEL_SELECT;
-               track= clip->tracking.tracks.first;
+               track= tracksbase->first;
                while(track) {
                        if(TRACK_VIEW_SELECTED(sc, track)) {
                                action= SEL_DESELECT;
@@ -1043,7 +1052,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
                }
        }
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if((track->flag&TRACK_HIDDEN)==0) {
                        MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
@@ -1108,9 +1117,11 @@ static int select_groped_exec(bContext *C, wmOperator *op)
        MovieClip *clip= ED_space_clip(sc);
        MovieTrackingTrack *track;
        MovieTrackingMarker *marker;
+       MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        int group= RNA_enum_get(op->ptr, "group");
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                int ok= 0;
 
@@ -1132,11 +1143,13 @@ static int select_groped_exec(bContext *C, wmOperator *op)
                        ok= marker->flag&MARKER_DISABLED;
                }
                else if(group==5) { /* color */
-                       if(clip->tracking.act_track) {
-                               ok= (track->flag&TRACK_CUSTOMCOLOR) == (clip->tracking.act_track->flag&TRACK_CUSTOMCOLOR);
+                       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
+
+                       if(act_track) {
+                               ok= (track->flag&TRACK_CUSTOMCOLOR) == (act_track->flag&TRACK_CUSTOMCOLOR);
 
                                if(ok && track->flag&TRACK_CUSTOMCOLOR)
-                                       ok= equals_v3v3(track->color, clip->tracking.act_track->color);
+                                       ok= equals_v3v3(track->color, act_track->color);
                        }
                }
                else if(group==6) { /* failed */
@@ -1208,10 +1221,11 @@ static int track_markers_testbreak(void)
 static int track_count_markers(SpaceClip *sc, MovieClip *clip)
 {
        int tot= 0;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
        int framenr= sc->user.framenr;
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) {
                        MovieTrackingMarker *marker= BKE_tracking_exact_marker(track, framenr);
@@ -1228,6 +1242,7 @@ static int track_count_markers(SpaceClip *sc, MovieClip *clip)
 
 static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit_r)
 {
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
        int framenr= sc->user.framenr, hidden= 0;
        int frames_limit= 0;
@@ -1235,7 +1250,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit
        if((sc->flag&SC_SHOW_MARKER_PATTERN)==0) hidden|= TRACK_AREA_PAT;
        if((sc->flag&SC_SHOW_MARKER_SEARCH)==0) hidden|= TRACK_AREA_SEARCH;
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(hidden)
                        BKE_tracking_track_flag(track, hidden, SELECT, 1);
@@ -1448,6 +1463,11 @@ static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
        int backwards= RNA_boolean_get(op->ptr, "backwards");
        int sequence= RNA_boolean_get(op->ptr, "sequence");
 
+       if(WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C))) {
+               /* only one tracking is allowed at a time */
+               return OPERATOR_CANCELLED;
+       }
+
        if(clip->tracking_context)
                return OPERATOR_CANCELLED;
 
@@ -1546,9 +1566,10 @@ static int solve_camera_initjob(bContext *C, SolveCameraJob *scj, wmOperator *op
        Scene *scene= CTX_data_scene(C);
        MovieTracking *tracking= &clip->tracking;
        MovieTrackingSettings *settings= &clip->tracking.settings;
+       MovieTrackingObject *object= BKE_tracking_active_object(tracking);
        int width, height;
 
-       if(!BKE_tracking_can_reconstruct(tracking, error_msg, max_error))
+       if(!BKE_tracking_can_reconstruct(tracking, object, error_msg, max_error))
                return 0;
 
        /* could fail if footage uses images with different sizes */
@@ -1559,7 +1580,7 @@ static int solve_camera_initjob(bContext *C, SolveCameraJob *scj, wmOperator *op
        scj->reports= op->reports;
        scj->user= sc->user;
 
-       scj->context= BKE_tracking_reconstruction_context_new(tracking,
+       scj->context= BKE_tracking_reconstruction_context_new(tracking, object,
                        settings->keyframe1, settings->keyframe2, width, height);
 
        tracking->stats= MEM_callocN(sizeof(MovieTrackingStats), "solve camera stats");
@@ -1670,9 +1691,15 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       MovieTrackingReconstruction *reconstruction= BKE_tracking_get_reconstruction(tracking);
        wmJob *steve;
        char error_msg[256]= "\0";
 
+       if(WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C))) {
+               /* only one solve is allowed at a time */
+               return OPERATOR_CANCELLED;
+       }
+
        scj= MEM_callocN(sizeof(SolveCameraJob), "SolveCameraJob data");
        if(!solve_camera_initjob(C, scj, op, error_msg, sizeof(error_msg))) {
                if(error_msg[0])
@@ -1686,7 +1713,7 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
        BLI_strncpy(tracking->stats->message, "Solving camera | Preparing solve", sizeof(tracking->stats->message));
 
        /* hide reconstruction statistics from previous solve */
-       clip->tracking.reconstruction.flag&= ~TRACKING_RECONSTRUCTED;
+       reconstruction->flag&= ~TRACKING_RECONSTRUCTED;
        WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
 
        /* setup job */
@@ -1746,7 +1773,9 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
-       MovieTrackingTrack *track= tracking->tracks.first;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
+       MovieTrackingReconstruction *reconstruction= BKE_tracking_get_reconstruction(tracking);
+       MovieTrackingTrack *track= tracksbase->first;
 
        while(track) {
                track->flag&= ~TRACK_HAS_BUNDLE;
@@ -1754,13 +1783,13 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op))
                track= track->next;
        }
 
-       if(tracking->reconstruction.cameras)
-               MEM_freeN(tracking->reconstruction.cameras);
+       if(reconstruction->cameras)
+               MEM_freeN(reconstruction->cameras);
 
-       tracking->reconstruction.cameras= NULL;
-       tracking->reconstruction.camnr= 0;
+       reconstruction->cameras= NULL;
+       reconstruction->camnr= 0;
 
-       tracking->reconstruction.flag&= ~TRACKING_RECONSTRUCTED;
+       reconstruction->flag&= ~TRACKING_RECONSTRUCTED;
 
        DAG_id_tag_update(&clip->id, 0);
 
@@ -1792,9 +1821,10 @@ static int clear_track_path_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTrackingTrack *track;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        int action= RNA_enum_get(op->ptr, "action");
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track))
                        BKE_tracking_clear_path(track, sc->user.framenr, action);
@@ -1839,7 +1869,8 @@ static int disable_markers_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
-       MovieTrackingTrack *track= tracking->tracks.first;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *track= tracksbase->first;
        int action= RNA_enum_get(op->ptr, "action");
 
        while(track) {
@@ -1892,10 +1923,11 @@ static int count_selected_bundles(bContext *C)
 {
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
        int tot= 0;
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_HAS_BUNDLE))
                        tot++;
@@ -1910,20 +1942,33 @@ static int set_origin_exec(bContext *C, wmOperator *op)
 {
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
        MovieTrackingTrack *track;
+       MovieTrackingObject *tracking_object;
        Scene *scene= CTX_data_scene(C);
-       Object *parent= scene->camera;
+       Object *object;
+       ListBase *tracksbase;
        float mat[4][4], vec[3];
 
        if(count_selected_bundles(C)!=1) {
                BKE_report(op->reports, RPT_ERROR, "Track with bundle should be selected to define origin position");
+
                return OPERATOR_CANCELLED;
        }
 
-       if(scene->camera->parent)
-               parent= scene->camera->parent;
+       tracking_object= BKE_tracking_active_object(tracking);
+
+       if(tracking_object->flag&TRACKING_OBJECT_CAMERA)
+               object= scene->camera;
+       else
+               object= OBACT;
 
-       track= clip->tracking.tracks.first;
+       if(object->parent)
+               object= object->parent;
+
+       tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
+
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track))
                        break;
@@ -1932,12 +1977,16 @@ static int set_origin_exec(bContext *C, wmOperator *op)
        }
 
        BKE_get_tracking_mat(scene, NULL, mat);
+
        mul_v3_m4v3(vec, mat, track->bundle_pos);
 
-       sub_v3_v3(parent->loc, vec);
+       if(tracking_object->flag&TRACKING_OBJECT_CAMERA)
+               sub_v3_v3(object->loc, vec);
+       else
+               copy_v3_v3(object->loc, vec);
 
        DAG_id_tag_update(&clip->id, 0);
-       DAG_id_tag_update(&parent->id, OB_RECALC_OB);
+       DAG_id_tag_update(&object->id, OB_RECALC_OB);
 
        WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
@@ -1962,12 +2011,27 @@ void CLIP_OT_set_origin(wmOperatorType *ot)
 
 /********************** set floor operator *********************/
 
-static void set_axis(Scene *scene,  Object *ob, MovieTrackingTrack *track, char axis)
+static void set_axis(Scene *scene,  Object *ob, MovieTrackingObject *tracking_object,
+                       MovieTrackingTrack *track, char axis)
 {
-       float mat[4][4], vec[3], obmat[4][4];
+       int is_camera= tracking_object->flag&TRACKING_OBJECT_CAMERA;
+       int  flip= 0;
+       float mat[4][4], vec[3], obmat[4][4], dvec[3];
+
+       object_to_mat4(ob, obmat);
 
        BKE_get_tracking_mat(scene, NULL, mat);
        mul_v3_m4v3(vec, mat, track->bundle_pos);
+       copy_v3_v3(dvec, vec);
+
+       if(!is_camera) {
+               float imat[4][4];
+
+               invert_m4_m4(imat, obmat);
+               mul_v3_m4v3(dvec, imat, vec);
+
+               sub_v3_v3(vec, obmat[3]);
+       }
 
        if(len_v2(vec) < 1e-3f)
                return;
@@ -1975,26 +2039,48 @@ static void set_axis(Scene *scene,  Object *ob, MovieTrackingTrack *track, char
        unit_m4(mat);
 
        if(axis=='X') {
-               if(fabsf(vec[1])<1e-3f) {
+               if(fabsf(dvec[1])<1e-3f) {
+                       flip= 1;
+
                        mat[0][0]= -1.0f; mat[0][1]= 0.0f; mat[0][2]= 0.0f;
                        mat[1][0]= 0.0f; mat[1][1]= -1.0f; mat[1][2]= 0.0f;
                        mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f;
                } else {
                        copy_v3_v3(mat[0], vec);
-                       mat[0][2]= 0.0f;
-                       mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f;
-                       cross_v3_v3v3(mat[1], mat[2], mat[0]);
+
+                       if(is_camera || fabsf(vec[2])<1e-3f) {
+                               mat[0][2]= 0.0f;
+                               mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f;
+                               cross_v3_v3v3(mat[1], mat[2], mat[0]);
+                       }
+                       else {
+                               vec[2]= 0.0f;
+
+                               cross_v3_v3v3(mat[1], mat[0], vec);
+                               cross_v3_v3v3(mat[2], mat[0], mat[1]);
+                       }
                }
        } else {
-               if(fabsf(vec[0])<1e-3f) {
+               if(fabsf(dvec[0])<1e-3f) {
+                       flip= 1;
+
                        mat[0][0]= -1.0f; mat[0][1]= 0.0f; mat[0][2]= 0.0f;
                        mat[1][0]= 0.0f; mat[1][1]= -1.0f; mat[1][2]= 0.0f;
                        mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f;
                } else {
                        copy_v3_v3(mat[1], vec);
-                       mat[1][2]= 0.0f;
-                       mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f;
-                       cross_v3_v3v3(mat[0], mat[1], mat[2]);
+
+                       if(is_camera || fabsf(vec[2])<1e-3f) {
+                               mat[1][2]= 0.0f;
+                               mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f;
+                               cross_v3_v3v3(mat[0], mat[1], mat[2]);
+                       }
+                       else {
+                               vec[2]= 0.0f;
+
+                               cross_v3_v3v3(mat[0], vec, mat[1]);
+                               cross_v3_v3v3(mat[2], mat[0], mat[1]);
+                       }
                }
        }
 
@@ -2002,10 +2088,31 @@ static void set_axis(Scene *scene,  Object *ob, MovieTrackingTrack *track, char
        normalize_v3(mat[1]);
        normalize_v3(mat[2]);
 
-       invert_m4(mat);
+       if(is_camera) {
+               invert_m4(mat);
+
+               mul_m4_m4m4(mat, obmat, mat);
+       }
+       else {
+               float lmat[4][4], ilmat[4][4], m[4][4];
+
+               unit_m4(lmat);
+               copy_v3_v3(lmat[3], obmat[3]);
+               invert_m4_m4(ilmat, lmat);
+
+               if(!flip) {
+                       float rmat[3][3], tmat[4][4];
+
+                       object_rot_to_mat3(ob, rmat);
+                       copy_m4_m3(tmat, rmat);
+                       invert_m4(tmat);
+
+                       mul_m4_m4m4(mat, mat, tmat);
+               }
+
+               mul_serie_m4(mat, lmat, mat, ilmat, obmat, NULL, NULL, NULL, NULL);
+       }
 
-       object_to_mat4(ob, obmat);
-       mul_m4_m4m4(mat, obmat, mat);
        object_apply_mat4(ob, mat, 0, 0);
 }
 
@@ -2014,9 +2121,11 @@ static int set_floor_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        Scene *scene= CTX_data_scene(C);
-       MovieTrackingTrack *track, *axis_track= NULL;
-       Object *camera= scene->camera;
-       Object *parent= camera;
+       MovieTracking *tracking= &clip->tracking;
+       MovieTrackingObject *tracking_object;
+       MovieTrackingTrack *track, *axis_track= NULL, *act_track;
+       ListBase *tracksbase;
+       Object *object;
        int tot= 0;
        float vec[3][3], mat[4][4], obmat[4][4], newmat[4][4], orig[3]= {0.0f, 0.0f, 0.0f};
        float rot[4][4]={{0.0f, 0.0f, -1.0f, 0.0f},
@@ -2026,21 +2135,31 @@ static int set_floor_exec(bContext *C, wmOperator *op)
 
        if(count_selected_bundles(C)!=3) {
                BKE_report(op->reports, RPT_ERROR, "Three tracks with bundles are needed to orient the floor");
+
                return OPERATOR_CANCELLED;
        }
 
-       if(scene->camera->parent)
-               parent= scene->camera->parent;
+       tracking_object= BKE_tracking_active_object(tracking);
+       tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
+       act_track= BKE_tracking_active_track(tracking);
+
+       if(tracking_object->flag&TRACKING_OBJECT_CAMERA)
+               object= scene->camera;
+       else
+               object= OBACT;
+
+       if(object->parent)
+               object= object->parent;
 
        BKE_get_tracking_mat(scene, NULL, mat);
 
        /* get 3 bundles to use as reference */
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track && tot<3) {
                if(track->flag&TRACK_HAS_BUNDLE && TRACK_VIEW_SELECTED(sc, track)) {
                        mul_v3_m4v3(vec[tot], mat, track->bundle_pos);
 
-                       if(tot==0 || track==clip->tracking.act_track)
+                       if(tot==0 || track==act_track)
                                copy_v3_v3(orig, vec[tot]);
                        else
                                axis_track= track;
@@ -2070,25 +2189,30 @@ static int set_floor_exec(bContext *C, wmOperator *op)
        mat[3][1]= orig[1];
        mat[3][2]= orig[2];
 
-       invert_m4(mat);
+       if(tracking_object->flag&TRACKING_OBJECT_CAMERA) {
+               invert_m4(mat);
 
-       object_to_mat4(parent, obmat);
-       mul_m4_m4m4(mat, obmat, mat);
-       mul_m4_m4m4(newmat, mat, rot);
-       object_apply_mat4(parent, newmat, 0, 0);
-
-       /* make camera have positive z-coordinate */
-       if(parent->loc[2]<0) {
-               invert_m4(rot);
+               object_to_mat4(object, obmat);
+               mul_m4_m4m4(mat, obmat, mat);
                mul_m4_m4m4(newmat, mat, rot);
-               object_apply_mat4(parent, newmat, 0, 0);
+               object_apply_mat4(object, newmat, 0, 0);
+
+               /* make camera have positive z-coordinate */
+               if(object->loc[2]<0) {
+                 invert_m4(rot);
+                 mul_m4_m4m4(newmat, mat, rot);
+                 object_apply_mat4(object, newmat, 0, 0);
+               }
+       }
+       else {
+               object_apply_mat4(object, mat, 0, 0);
        }
 
-       where_is_object(scene, parent);
-       set_axis(scene, parent, axis_track, 'X');
+       where_is_object(scene, object);
+       set_axis(scene, object, tracking_object, axis_track, 'X');
 
        DAG_id_tag_update(&clip->id, 0);
-       DAG_id_tag_update(&parent->id, OB_RECALC_OB);
+       DAG_id_tag_update(&object->id, OB_RECALC_OB);
 
        WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
@@ -2117,9 +2241,12 @@ static int set_axis_exec(bContext *C, wmOperator *op)
 {
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+       MovieTrackingObject *tracking_object= BKE_tracking_active_object(tracking);
        MovieTrackingTrack *track;
        Scene *scene= CTX_data_scene(C);
-       Object *parent= scene->camera;
+       Object *object;
+       ListBase *tracksbase;
        int axis= RNA_enum_get(op->ptr, "axis");
 
        if(count_selected_bundles(C)!=1) {
@@ -2128,10 +2255,17 @@ static int set_axis_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
 
-       if(scene->camera->parent)
-               parent= scene->camera->parent;
+       if(tracking_object->flag & TRACKING_OBJECT_CAMERA)
+               object= scene->camera;
+       else
+               object= OBACT;
+
+       if(object->parent)
+               object= object->parent;
 
-       track= clip->tracking.tracks.first;
+       tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
+
+       track=tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track))
                        break;
@@ -2139,10 +2273,10 @@ static int set_axis_exec(bContext *C, wmOperator *op)
                track= track->next;
        }
 
-       set_axis(scene, parent, track, axis==0?'X':'Y');
+       set_axis(scene, object, tracking_object, track, axis==0?'X':'Y');
 
        DAG_id_tag_update(&clip->id, 0);
-       DAG_id_tag_update(&parent->id, OB_RECALC_OB);
+       DAG_id_tag_update(&object->id, OB_RECALC_OB);
 
        WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip);
        WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
@@ -2183,6 +2317,7 @@ static int set_scale_exec(bContext *C, wmOperator *op)
        MovieTrackingTrack *track;
        Scene *scene= CTX_data_scene(C);
        Object *parent= scene->camera;
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        int tot= 0;
        float vec[2][3], mat[4][4], scale;
        float dist= RNA_float_get(op->ptr, "distance");
@@ -2198,7 +2333,7 @@ static int set_scale_exec(bContext *C, wmOperator *op)
 
        BKE_get_tracking_mat(scene, NULL, mat);
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track)) {
                        mul_v3_m4v3(vec[tot], mat, track->bundle_pos);
@@ -2301,11 +2436,14 @@ static int hide_tracks_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTrackingTrack *track;
+       MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
        int unselected;
 
        unselected= RNA_boolean_get(op->ptr, "unselected");
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(unselected==0 && TRACK_VIEW_SELECTED(sc, track)) {
                        track->flag|= TRACK_HIDDEN;
@@ -2316,7 +2454,7 @@ static int hide_tracks_exec(bContext *C, wmOperator *op)
                track= track->next;
        }
 
-       if(clip->tracking.act_track && clip->tracking.act_track->flag&TRACK_HIDDEN)
+       if(act_track && act_track->flag&TRACK_HIDDEN)
                clip->tracking.act_track= NULL;
 
        if(unselected==0) {
@@ -2353,9 +2491,10 @@ static int hide_tracks_clear_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                track->flag&= ~TRACK_HIDDEN;
 
@@ -2407,7 +2546,9 @@ static int detect_features_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        ImBuf *ibuf= BKE_movieclip_get_ibuf_flag(clip, &sc->user, 0);
-       MovieTrackingTrack *track= clip->tracking.tracks.first;
+       MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *track= tracksbase->first;
        int placement= RNA_enum_get(op->ptr, "placement");
        int margin= RNA_int_get(op->ptr, "margin");
        int min_trackability= RNA_int_get(op->ptr, "min_trackability");
@@ -2429,7 +2570,8 @@ static int detect_features_exec(bContext *C, wmOperator *op)
                track= track->next;
        }
 
-       BKE_tracking_detect_fast(&clip->tracking, ibuf, sc->user.framenr, margin, min_trackability, min_distance, layer, place_outside_layer);
+       BKE_tracking_detect_fast(tracking, tracksbase, ibuf, sc->user.framenr, margin,
+                               min_trackability, min_distance, layer, place_outside_layer);
 
        IMB_freeImBuf(ibuf);
 
@@ -2478,7 +2620,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
        int delta;
 
        if(pos<=1) {    /* jump to path */
-               track= clip->tracking.act_track;
+               track= BKE_tracking_active_track(&clip->tracking);
 
                if(!track)
                        return OPERATOR_CANCELLED;
@@ -2498,13 +2640,16 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
                if(clip->tracking.reconstruction.flag&TRACKING_RECONSTRUCTED) {
                        int a= sc->user.framenr;
                        MovieTracking *tracking= &clip->tracking;
+                       MovieTrackingObject *object= BKE_tracking_active_object(tracking);
 
                        delta= pos == 3 ? 1 : -1;
 
                        a+= delta;
 
                        while(a+delta >= SFRA && a+delta <= EFRA) {
-                               MovieReconstructedCamera *cam= BKE_tracking_get_reconstructed_camera(tracking, a);
+                               MovieReconstructedCamera *cam;
+
+                               cam= BKE_tracking_get_reconstructed_camera(tracking, object, a);
 
                                if(!cam) {
                                        sc->user.framenr= a;
@@ -2561,16 +2706,18 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
 {
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *act_track, *track, *next;
 
-       act_track= clip->tracking.act_track;
+       act_track= BKE_tracking_active_track(tracking);
 
        if(!act_track) {
                BKE_report(op->reports, RPT_ERROR, "No active track to join to");
                return OPERATOR_CANCELLED;
        }
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && track!=act_track) {
                        if(!BKE_tracking_test_join_tracks(act_track, track)) {
@@ -2582,7 +2729,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
                track= track->next;
        }
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                next= track->next;
 
@@ -2590,7 +2737,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
                        BKE_tracking_join_tracks(act_track, track);
 
                        BKE_tracking_free_track(track);
-                       BLI_freelinkN(&clip->tracking.tracks, track);
+                       BLI_freelinkN(tracksbase, track);
                }
 
                track= next;
@@ -2623,7 +2770,8 @@ static int lock_tracks_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
-       MovieTrackingTrack *track= tracking->tracks.first;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *track= tracksbase->first;
        int action= RNA_enum_get(op->ptr, "action");
 
        while(track) {
@@ -2672,12 +2820,14 @@ static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
 {
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
-       MovieTrackingTrack *track, *act_track= clip->tracking.act_track;
+       MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *track, *act_track= BKE_tracking_active_track(tracking);
 
        if(!act_track)
                return OPERATOR_CANCELLED;
 
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && track!=act_track) {
                        track->flag&= ~TRACK_CUSTOMCOLOR;
@@ -2718,11 +2868,12 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
        MovieTrackingStabilization *stab= &tracking->stabilization;
        int update= 0;
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_USE_2D_STAB)==0) {
                        track->flag|= TRACK_USE_2D_STAB;
@@ -2767,10 +2918,11 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op))
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
        MovieTrackingStabilization *stab= &tracking->stabilization;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
        int a= 0, update= 0;
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(track->flag&TRACK_USE_2D_STAB) {
                        if(a==stab->act_track) {
@@ -2825,10 +2977,11 @@ static int stabilize_2d_select_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
        MovieTrackingTrack *track;
        int update= 0;
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(track->flag&TRACK_USE_2D_STAB) {
                        BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, 0);
@@ -2867,11 +3020,12 @@ static int stabilize_2d_set_rotation_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
 
-       if(tracking->act_track) {
+       if(act_track) {
                MovieTrackingStabilization *stab= &tracking->stabilization;
 
-               stab->rot_track= tracking->act_track;
+               stab->rot_track= act_track;
                stab->ok= 0;
 
                DAG_id_tag_update(&clip->id, 0);
@@ -2996,7 +3150,8 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
        SpaceClip *sc= CTX_wm_space_clip(C);
        MovieClip *clip= ED_space_clip(sc);
        MovieTracking *tracking= &clip->tracking;
-       MovieTrackingTrack *track, *next, *act_track= clip->tracking.act_track;
+       ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
+       MovieTrackingTrack *track, *next, *act_track= BKE_tracking_active_track(tracking);
        int frames= RNA_int_get(op->ptr, "frames");
        int action= RNA_enum_get(op->ptr, "action");
        float error= RNA_float_get(op->ptr, "error");
@@ -3004,7 +3159,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
        if(error && action==TRACKING_CLEAN_DELETE_SEGMENT)
                action= TRACKING_CLEAN_DELETE_TRACK;
 
-       track= tracking->tracks.first;
+       track= tracksbase->first;
        while(track) {
                next= track->next;
 
@@ -3023,7 +3178,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
                                                clip->tracking.act_track= NULL;
 
                                        BKE_tracking_free_track(track);
-                                       BLI_freelinkN(&clip->tracking.tracks, track);
+                                       BLI_freelinkN(tracksbase, track);
                                        track= NULL;
                                }
 
@@ -3033,7 +3188,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
                                                clip->tracking.act_track= NULL;
 
                                        BKE_tracking_free_track(track);
-                                       BLI_freelinkN(&clip->tracking.tracks, track);
+                                       BLI_freelinkN(tracksbase, track);
                                }
                        }
                }
@@ -3090,3 +3245,71 @@ void CLIP_OT_clean_tracks(wmOperatorType *ot)
        RNA_def_float(ot->srna, "error", 0.0f, 0.0f, FLT_MAX, "Reprojection Error", "Effect on tracks with have got larger reprojection error", 0.0f, 100.0f);
        RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Cleanup action to execute");
 }
+
+/********************** add tracking object *********************/
+
+static int tracking_object_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceClip *sc= CTX_wm_space_clip(C);
+       MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+
+       BKE_tracking_new_object(tracking, "Object");
+
+       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+
+       return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_tracking_object_new(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Tracking Object";
+       ot->description= "Add new object for tracking";
+       ot->idname= "CLIP_OT_tracking_object_new";
+
+       /* api callbacks */
+       ot->exec= tracking_object_new_exec;
+       ot->poll= ED_space_clip_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** remove tracking object *********************/
+
+static int tracking_object_remove_exec(bContext *C, wmOperator *op)
+{
+       SpaceClip *sc= CTX_wm_space_clip(C);
+       MovieClip *clip= ED_space_clip(sc);
+       MovieTracking *tracking= &clip->tracking;
+       MovieTrackingObject *object;
+
+       object= BKE_tracking_active_object(tracking);
+
+       if(object->flag&TRACKING_OBJECT_CAMERA) {
+               BKE_report(op->reports, RPT_WARNING, "Object used for camera tracking can't be deleted");
+               return OPERATOR_CANCELLED;
+       }
+
+       BKE_tracking_remove_object(tracking, object);
+
+       WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
+
+       return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_tracking_object_remove(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Movie Tracking Object";
+       ot->description= "Remove object for tracking";
+       ot->idname= "CLIP_OT_tracking_object_remove";
+
+       /* api callbacks */
+       ot->exec= tracking_object_remove_exec;
+       ot->poll= ED_space_clip_poll;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
index 9505ea5098d341a97704f90653e79e8033e46675..3333149ec37fc45f0f0311982445ae0f13211969 100644 (file)
@@ -1458,43 +1458,44 @@ static void draw_bundle_sphere(void)
        glCallList(displist);
 }
 
-static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, int flag)
+static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
+                       MovieClip *clip, MovieTrackingObject *tracking_object, int flag)
 {
        MovieTracking *tracking= &clip->tracking;
        MovieTrackingTrack *track;
-       float mat[4][4], imat[4][4], curcol[4];
+       float mat[4][4], imat[4][4];
        unsigned char col[4], scol[4];
        int bundlenr= 1;
-
-       if((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0)
-               return;
-
-       if(v3d->flag2&V3D_RENDER_OVERRIDE)
-               return;
-
-       glGetFloatv(GL_CURRENT_COLOR, curcol);
+       ListBase *tracksbase= BKE_tracking_object_tracks(tracking, tracking_object);
 
        UI_GetThemeColor4ubv(TH_TEXT, col);
        UI_GetThemeColor4ubv(TH_SELECT, scol);
 
        BKE_get_tracking_mat(scene, base->object, mat);
 
-       glEnable(GL_LIGHTING);
-       glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-       glEnable(GL_COLOR_MATERIAL);
-       glShadeModel(GL_SMOOTH);
+       glPushMatrix();
 
-       /* current ogl matrix is translated in camera space, bundles should
-          be rendered in world space, so camera matrix should be "removed"
-          from current ogl matrix */
-       invert_m4_m4(imat, base->object->obmat);
+       if(tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+               /* current ogl matrix is translated in camera space, bundles should
+                  be rendered in world space, so camera matrix should be "removed"
+                  from current ogl matrix */
+               invert_m4_m4(imat, base->object->obmat);
 
-       glPushMatrix();
-       glMultMatrixf(imat);
-       glMultMatrixf(mat);
+               glMultMatrixf(imat);
+               glMultMatrixf(mat);
+       }
+       else {
+               float obmat[4][4];
+
+               BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat);
+
+               invert_m4_m4(imat, obmat);
+               glMultMatrixf(imat);
+       }
+
+       for (track= tracksbase->first; track; track= track->next) {
+               int selected= TRACK_SELECTED(track);
 
-       for ( track= tracking->tracks.first; track; track= track->next) {
-               int selected= track->flag&SELECT || track->pat_flag&SELECT || track->search_flag&SELECT;
                if((track->flag&TRACK_HAS_BUNDLE)==0)
                        continue;
 
@@ -1581,27 +1582,58 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d,
        }
 
        if((flag & DRAW_PICKING)==0) {
-               if(v3d->flag2&V3D_SHOW_CAMERAPATH && clip->tracking.reconstruction.camnr) {
-                       int a= 0;
-                       MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
-                       MovieReconstructedCamera *camera= tracking->reconstruction.cameras;
+               if((v3d->flag2&V3D_SHOW_CAMERAPATH) && (tracking_object->flag&TRACKING_OBJECT_CAMERA)) {
+                       MovieTrackingReconstruction *reconstruction;
+                       reconstruction= BKE_tracking_object_reconstruction(tracking, tracking_object);
 
-                       glDisable(GL_LIGHTING);
-                       UI_ThemeColor(TH_CAMERA_PATH);
-                       glLineWidth(2.0f);
+                       if(reconstruction->camnr) {
+                               MovieReconstructedCamera *camera= reconstruction->cameras;
+                               int a= 0;
 
-                       glBegin(GL_LINE_STRIP);
-                               for(a= 0; a<reconstruction->camnr; a++, camera++) {
-                                       glVertex3fv(camera->mat[3]);
-                               }
-                       glEnd();
+                               glDisable(GL_LIGHTING);
+                               UI_ThemeColor(TH_CAMERA_PATH);
+                               glLineWidth(2.0f);
 
-                       glLineWidth(1.0f);
-                       glEnable(GL_LIGHTING);
+                               glBegin(GL_LINE_STRIP);
+                                       for(a= 0; a<reconstruction->camnr; a++, camera++) {
+                                               glVertex3fv(camera->mat[3]);
+                                       }
+                                       glEnd();
+
+                                       glLineWidth(1.0f);
+                                       glEnable(GL_LIGHTING);
+                       }
                }
        }
 
        glPopMatrix();
+}
+
+static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, int flag)
+{
+       MovieTracking *tracking= &clip->tracking;
+       MovieTrackingObject *tracking_object;
+       float curcol[4];
+
+       if((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0)
+               return;
+
+       if(v3d->flag2&V3D_RENDER_OVERRIDE)
+               return;
+
+       glGetFloatv(GL_CURRENT_COLOR, curcol);
+
+       glEnable(GL_LIGHTING);
+       glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+       glEnable(GL_COLOR_MATERIAL);
+       glShadeModel(GL_SMOOTH);
+
+       tracking_object= tracking->objects.first;
+       while(tracking_object) {
+               draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object, flag);
+
+               tracking_object= tracking_object->next;
+       }
 
        /* restore */
        glShadeModel(GL_FLAT);
index 33f7acf2a3782c4cbe2a988fe386d12233b0a4ab..d8ff01a880df26e2f6403b47de0d5b44bf177752 100644 (file)
@@ -1405,13 +1405,17 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short obce
                                                           in hight word, this buffer value belongs to camera,. not to bundle */
                                                        if(buffer[4*i+3] & 0xFFFF0000) {
                                                                MovieClip *clip= object_get_movieclip(scene, basact->object, 0);
+                                                               MovieTracking *tracking= &clip->tracking;
                                                                int selected;
+
                                                                track= BKE_tracking_indexed_track(&clip->tracking, hitresult >> 16);
 
                                                                selected= (track->flag&SELECT) || (track->pat_flag&SELECT) || (track->search_flag&SELECT);
 
-                                                               if(selected && extend)  BKE_tracking_deselect_track(track, TRACK_AREA_ALL);
-                                                               else BKE_tracking_select_track(&clip->tracking, track, TRACK_AREA_ALL, extend);
+                                                               if(selected && extend)
+                                                                       BKE_tracking_deselect_track(track, TRACK_AREA_ALL);
+                                                               else
+                                                                       BKE_tracking_select_track(&tracking->tracks, track, TRACK_AREA_ALL, extend);
 
                                                                basact->flag|= SELECT;
                                                                basact->object->flag= basact->flag;
index 5527ab0d331f453a1a6d1e07830e25bb83bf0d8d..96eb60272c15e5fff594f81cbb420902d2bcecbb 100644 (file)
@@ -5391,6 +5391,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
        TransData2D *td2d;
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip(sc);
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
        MovieTrackingMarker *marker;
        TransDataTracking *tdt;
@@ -5404,7 +5405,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
        /* count */
        t->total = 0;
 
-       track = clip->tracking.tracks.first;
+       track = tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) {
                        marker= BKE_tracking_get_marker(track, framenr);
@@ -5431,7 +5432,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
        t->customFree= transDataTrackingFree;
 
        /* create actual data */
-       track = clip->tracking.tracks.first;
+       track = tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) {
                        marker= BKE_tracking_get_marker(track, framenr);
index d0857958a4b132aba7a7d8f2a040ab4563bb3b14..0b0a0eb2e2d4c354be8e64865f9b62bfad93d707 100644 (file)
@@ -641,10 +641,11 @@ static void recalcData_clip(TransInfo *t)
 {
        SpaceClip *sc= t->sa->spacedata.first;
        MovieClip *clip= ED_space_clip(sc);
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
        MovieTrackingTrack *track;
        
        if(t->state == TRANS_CANCEL) {
-               track= clip->tracking.tracks.first;
+               track= tracksbase->first;
                while(track) {
                        if(TRACK_VIEW_SELECTED(sc, track)) {
                                MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr);
@@ -658,7 +659,7 @@ static void recalcData_clip(TransInfo *t)
        
        flushTransTracking(t);
        
-       track= clip->tracking.tracks.first;
+       track= tracksbase->first;
        while(track) {
                if(TRACK_VIEW_SELECTED(sc, track)) {
                        if (t->mode == TFM_TRANSLATION) {
index 4aff540a94894dce62875318ef60cc89dc0f9e48..10c4153702da58b2d231bf70e0675242f8cf7a20 100644 (file)
@@ -412,6 +412,7 @@ typedef struct bFollowTrackConstraint {
        struct MovieClip        *clip;
        char    track[24];
        int             flag, pad;
+       char            object[24];
 } bFollowTrackConstraint;
 
 /* Camera Solver constraints */
@@ -420,6 +421,13 @@ typedef struct bCameraSolverConstraint {
        int             flag, pad;
 } bCameraSolverConstraint;
 
+/* Camera Solver constraints */
+typedef struct bObjectSolverConstraint {
+       struct MovieClip        *clip;
+       int             flag, pad;
+       char            object[24];
+} bObjectSolverConstraint;
+
 /* ------------------------------------------ */
 
 /* bConstraint->type 
@@ -455,6 +463,7 @@ typedef enum eBConstraint_Types {
        CONSTRAINT_TYPE_PIVOT,                          /* Pivot Constraint */
        CONSTRAINT_TYPE_FOLLOWTRACK,            /* Follow Track Constraint */
        CONSTRAINT_TYPE_CAMERASOLVER,           /* Camera Solver Constraint */
+       CONSTRAINT_TYPE_OBJECTSOLVER,           /* Object Solver Constraint */
        
        /* NOTE: no constraints are allowed to be added after this */
        NUM_CONSTRAINT_TYPES
@@ -762,6 +771,11 @@ typedef enum eCameraSolver_Flags {
        CAMERASOLVER_ACTIVECLIP = (1<<0)
 } eCameraSolver_Flags;
 
+/* ObjectSolver Constraint -> flag */
+typedef enum eObjectSolver_Flags {
+       OBJECTSOLVER_ACTIVECLIP = (1<<0)
+} eObjectSolver_Flags;
+
 /* Rigid-Body Constraint */
 #define CONSTRAINT_DRAW_PIVOT 0x40
 #define        CONSTRAINT_DISABLE_LINKED_COLLISION 0x80
index 82ccbf87c0b5508875332b6da78e6d3e9ca56727..fd0e281b60fe267ae1f5f19eca0b16616e74561a 100644 (file)
@@ -172,6 +172,15 @@ typedef struct MovieTrackingReconstruction {
        struct MovieReconstructedCamera *cameras;       /* reconstructed cameras */
 } MovieTrackingReconstruction;
 
+typedef struct MovieTrackingObject {
+       struct MovieTrackingObject *next, *prev;
+
+       char name[24];                  /* Name of tracking object */
+       int flag, pad;
+       ListBase tracks;                /* list of tracks use to tracking this object */
+       MovieTrackingReconstruction reconstruction;     /* reconstruction data for this object */
+} MovieTrackingObject;
+
 typedef struct MovieTrackingStats {
        char message[256];
 } MovieTrackingStats;
@@ -179,11 +188,14 @@ typedef struct MovieTrackingStats {
 typedef struct MovieTracking {
        MovieTrackingSettings settings; /* different tracking-related settings */
        MovieTrackingCamera camera;             /* camera intrinsics */
-       ListBase tracks;                                /* all tracks */
-       MovieTrackingReconstruction reconstruction;     /* reconstruction data */
+       ListBase tracks;                                /* list of tracks used for camera object */
+       MovieTrackingReconstruction reconstruction;     /* reconstruction data for camera object */
        MovieTrackingStabilization stabilization;       /* stabilization data */
        MovieTrackingTrack *act_track;          /* active track */
 
+       ListBase objects;
+       int objectnr, tot_object;               /* index of active object and total number of objects */
+
        MovieTrackingStats *stats;              /* statistics displaying in clip editor */
 } MovieTracking;
 
@@ -207,6 +219,7 @@ enum {
 #define TRACK_LOCKED           (1<<6)
 #define TRACK_CUSTOMCOLOR      (1<<7)
 #define TRACK_USE_2D_STAB      (1<<8)
+#define TRACK_PREVIEW_GRAYSCALE        (1<<9)
 
 /* MovieTrackingTrack->tracker */
 #define TRACKER_KLT            0
@@ -241,6 +254,9 @@ enum {
 /* MovieTrackingReconstruction->flag */
 #define TRACKING_RECONSTRUCTED (1<<0)
 
+/* MovieTrackingObject->flag */
+#define TRACKING_OBJECT_CAMERA         (1<<0)
+
 #define TRACKING_CLEAN_SELECT                  0
 #define TRACKING_CLEAN_DELETE_TRACK            1
 #define TRACKING_CLEAN_DELETE_SEGMENT  2
index 37a5b5643b840fb95c8459be55f009564f4a2356..215c7992ff3757187695689c19e28fc58e6965bf 100644 (file)
@@ -329,6 +329,7 @@ extern StructRNA RNA_MotionPath;
 extern StructRNA RNA_MotionPathVert;
 extern StructRNA RNA_MouseSensor;
 extern StructRNA RNA_MovieSequence;
+extern StructRNA RNA_MovieTrackingObject;
 extern StructRNA RNA_MulticamSequence;
 extern StructRNA RNA_MultiresModifier;
 extern StructRNA RNA_MusgraveTexture;
index 4ab14550fd1a5ff2aebe00727b03c308945ba9c9..4d064c01faed109b92de70f5cf24315af4cf2c71 100644 (file)
@@ -45,6 +45,7 @@
 EnumPropertyItem constraint_type_items[] ={
        {0, "", 0, "Motion Tracking", ""},
        {CONSTRAINT_TYPE_CAMERASOLVER, "CAMERA_SOLVER", ICON_CONSTRAINT_DATA, "Camera Solver", ""},
+       {CONSTRAINT_TYPE_OBJECTSOLVER, "OBJECT_SOLVER", ICON_CONSTRAINT_DATA, "Object Solver", ""},
        {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""},
        {0, "", 0, "Transform", ""},
        {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", ""},
@@ -163,6 +164,8 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr)
                        return &RNA_FollowTrackConstraint;
                case CONSTRAINT_TYPE_CAMERASOLVER:
                        return &RNA_CameraSolverConstraint;
+               case CONSTRAINT_TYPE_OBJECTSOLVER:
+                       return &RNA_ObjectSolverConstraint;
                default:
                        return &RNA_UnknownType;
        }
@@ -2066,6 +2069,12 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", FOLLOWTRACK_USE_3D_POSITION);
        RNA_def_property_ui_text(prop, "3D Position", "Use 3D position of track to parent to");
        RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
+       /* object */
+       prop= RNA_def_property(srna, "object", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "object");
+       RNA_def_property_ui_text(prop, "Object", "Movie tracking object to follow");
+       RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
 }
 
 static void rna_def_constraint_camera_solver(BlenderRNA *brna)
@@ -2074,7 +2083,7 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna)
        PropertyRNA *prop;
 
        srna= RNA_def_struct(brna, "CameraSolverConstraint", "Constraint");
-       RNA_def_struct_ui_text(srna, "Follow Track Constraint", "Lock motion to the reconstructed camera movement");
+       RNA_def_struct_ui_text(srna, "Camera Solver Constraint", "Lock motion to the reconstructed camera movement");
        RNA_def_struct_sdna_from(srna, "bCameraSolverConstraint", "data");
 
        /* movie clip */
@@ -2091,6 +2100,35 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
 }
 
+static void rna_def_constraint_object_solver(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna= RNA_def_struct(brna, "ObjectSolverConstraint", "Constraint");
+       RNA_def_struct_ui_text(srna, "Object Solver Constraint", "Lock motion to the reconstructed object movement");
+       RNA_def_struct_sdna_from(srna, "bObjectSolverConstraint", "data");
+
+       /* movie clip */
+       prop= RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "clip");
+       RNA_def_property_ui_text(prop, "Movie Clip", "Movie Clip to get tracking data from");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+       /* use default clip */
+       prop= RNA_def_property(srna, "use_active_clip", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", CAMERASOLVER_ACTIVECLIP);
+       RNA_def_property_ui_text(prop, "Active Clip", "Use active clip defined in scene");
+       RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
+       /* object */
+       prop= RNA_def_property(srna, "object", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "object");
+       RNA_def_property_ui_text(prop, "Object", "Movie tracking object to follow");
+       RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
+}
+
 /* base struct for constraints */
 void RNA_def_constraint(BlenderRNA *brna)
 {
@@ -2203,6 +2241,7 @@ void RNA_def_constraint(BlenderRNA *brna)
        rna_def_constraint_pivot(brna);
        rna_def_constraint_follow_track(brna);
        rna_def_constraint_camera_solver(brna);
+       rna_def_constraint_object_solver(brna);
 }
 
 #endif
index 5a2ef54cfc1ef8b1d28486b67e4f678650246a49..6332cd40bcad7660d8ee9dea223af6b65abd6587 100644 (file)
@@ -90,43 +90,87 @@ static void rna_tracking_defaultSettings_searchUpdate(Main *UNUSED(bmain), Scene
 static void rna_tracking_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
        MovieClip *clip= (MovieClip*)ptr->id.data;
+
        rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL);
 }
 
-static void rna_tracking_tracks_add(MovieTracking *tracking, int frame, int number)
+static void rna_tracking_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
-       int a;
+       MovieClip *clip= (MovieClip*)ptr->id.data;
 
-       for(a= 0; a<number; a++)
-               BKE_tracking_add_track(tracking, 0, 0, frame, 1, 1);
+       rna_iterator_listbase_begin(iter, &clip->tracking.objects, NULL);
+}
 
-       WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL);
+static int rna_tracking_active_object_index_get(PointerRNA *ptr)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+
+       return clip->tracking.objectnr;
+}
+
+static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+
+       clip->tracking.objectnr= value;
+}
+
+static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, int *max)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+
+       *min= 0;
+       *max= clip->tracking.tot_object-1;
+       *max= MAX2(0, *max);
 }
 
 static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr)
 {
        MovieClip *clip= (MovieClip*)ptr->id.data;
+       MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking);
 
-       return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, clip->tracking.act_track);
+       return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, act_track);
 }
 
 static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value)
 {
        MovieClip *clip= (MovieClip*)ptr->id.data;
        MovieTrackingTrack *track= (MovieTrackingTrack *)value.data;
-       int index= BLI_findindex(&clip->tracking.tracks, track);
+       ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
+       int index= BLI_findindex(tracksbase, track);
 
-       if(index>=0) clip->tracking.act_track= track;
-       else clip->tracking.act_track= NULL;
+       if(index>=0)
+               clip->tracking.act_track= track;
+       else
+               clip->tracking.act_track= NULL;
 }
 
 void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
 {
        MovieClip *clip= (MovieClip *)ptr->id.data;
+       MovieTracking *tracking= &clip->tracking;
        MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data;
+       ListBase *tracksbase= &tracking->tracks;
+
        BLI_strncpy(track->name, value, sizeof(track->name));
 
-       BKE_track_unique_name(&clip->tracking, track);
+       /* 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(tracksbase, track) < 0) {
+               MovieTrackingObject *object= tracking->objects.first;
+
+               while(object) {
+                       if(BLI_findindex(&object->tracks, track)) {
+                               tracksbase= &object->tracks;
+                               break;
+                       }
+
+                       object= object->next;
+               }
+       }
+
+       BKE_track_unique_name(tracksbase, track);
 }
 
 static int rna_trackingTrack_select_get(PointerRNA *ptr)
@@ -257,8 +301,94 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR
        DAG_id_tag_update(&clip->id, 0);
 }
 
+static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+       MovieTrackingObject *object= (MovieTrackingObject* )ptr->data;
+
+       rna_iterator_listbase_begin(iter, &object->tracks, NULL);
+}
+
+static PointerRNA rna_tracking_active_object_get(PointerRNA *ptr)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+       MovieTrackingObject *object= BLI_findlink(&clip->tracking.objects, clip->tracking.objectnr);
+
+       return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingObject, object);
+}
+
+static void rna_tracking_active_object_set(PointerRNA *ptr, PointerRNA value)
+{
+       MovieClip *clip= (MovieClip*)ptr->id.data;
+       MovieTrackingObject *object= (MovieTrackingObject *)value.data;
+       int index= BLI_findindex(&clip->tracking.objects, object);
+
+       if(index>=0) clip->tracking.objectnr= index;
+       else clip->tracking.objectnr= 0;
+}
+
+void rna_trackingObject_name_set(PointerRNA *ptr, const char *value)
+{
+       MovieClip *clip= (MovieClip *)ptr->id.data;
+       MovieTrackingObject *object= (MovieTrackingObject *)ptr->data;
+
+       BLI_strncpy(object->name, value, sizeof(object->name));
+
+       BKE_tracking_object_unique_name(&clip->tracking, object);
+}
+
 /* API */
 
+static void add_tracks_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, int frame, int number)
+{
+       int a, width, height;
+       MovieClipUser user= {0};
+
+       user.framenr= 1;
+
+       BKE_movieclip_get_size(clip, &user, &width, &height);
+
+       for(a= 0; a<number; a++)
+               BKE_tracking_add_track(tracking, tracksbase, 0, 0, frame, width, height);
+}
+
+static void rna_tracking_tracks_add(ID *id, MovieTracking *tracking, int frame, int number)
+{
+       MovieClip *clip= (MovieClip *) id;
+
+       add_tracks_to_base(clip, tracking, &tracking->tracks, frame, number);
+
+       WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL);
+}
+
+static void rna_trackingObject_tracks_add(ID *id, MovieTrackingObject *object, int frame, int number)
+{
+       MovieClip *clip= (MovieClip *) id;
+       ListBase *tracksbase= &object->tracks;
+
+       if(object->flag&TRACKING_OBJECT_CAMERA)
+               tracksbase= &clip->tracking.tracks;
+
+       add_tracks_to_base(clip, &clip->tracking, tracksbase, frame, number);
+
+       WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL);
+}
+
+static MovieTrackingObject *rna_tracking_object_new(MovieTracking *tracking, const char *name)
+{
+       MovieTrackingObject *object= BKE_tracking_new_object(tracking, name);
+
+       WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL);
+
+       return object;
+}
+
+void rna_tracking_object_remove(MovieTracking *tracking, MovieTrackingObject *object)
+{
+       BKE_tracking_remove_object(tracking, object);
+
+       WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL);
+}
+
 static MovieTrackingMarker *rna_trackingTrack_marker_find_frame(MovieTrackingTrack *track, int framenr)
 {
        return BKE_tracking_get_marker(track, framenr);
@@ -673,6 +803,12 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Use Blue Channel", "Use blue channel from footage for tracking");
        RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL);
 
+       /* preview_grayscale */
+       prop= RNA_def_property(srna, "use_grayscale_preview", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACK_PREVIEW_GRAYSCALE);
+       RNA_def_property_ui_text(prop, "Grayscale", "Display what the tracking algorithm sees in the preview");
+       RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL);
+
        /* has bundle */
        prop= RNA_def_property(srna, "has_bundle", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACK_HAS_BUNDLE);
@@ -883,18 +1019,18 @@ static void rna_def_trackingReconstruction(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Cameras", "Collection of solved cameras");
 }
 
-static void rna_def_trackingTracks(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_trackingTracks(BlenderRNA *brna)
 {
        StructRNA *srna;
        FunctionRNA *func;
        PropertyRNA *prop;
 
-       RNA_def_property_srna(cprop, "MovieTrackingTracks");
        srna= RNA_def_struct(brna, "MovieTrackingTracks", NULL);
        RNA_def_struct_sdna(srna, "MovieTracking");
        RNA_def_struct_ui_text(srna, "Movie Tracks", "Collection of movie tracking tracks");
 
        func= RNA_def_function(srna, "add", "rna_tracking_tracks_add");
+       RNA_def_function_flag(func, FUNC_USE_SELF_ID);
        RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip");
        RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add tracks on", MINFRAME, MAXFRAME);
        RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of tracks to add to the movie clip", 0, INT_MAX);
@@ -907,6 +1043,96 @@ static void rna_def_trackingTracks(BlenderRNA *brna, PropertyRNA *cprop)
        RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
 }
 
+static void rna_def_trackingObjectTracks(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       FunctionRNA *func;
+       PropertyRNA *prop;
+
+       srna= RNA_def_struct(brna, "MovieTrackingObjectTracks", NULL);
+       RNA_def_struct_sdna(srna, "MovieTrackingObject");
+       RNA_def_struct_ui_text(srna, "Movie Tracks", "Collection of movie tracking tracks");
+
+       func= RNA_def_function(srna, "add", "rna_trackingObject_tracks_add");
+       RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+       RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip");
+       RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add tracks on", MINFRAME, MAXFRAME);
+       RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of tracks to add to the movie clip", 0, INT_MAX);
+
+       /* 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_track_get", "rna_tracking_active_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;
+       PropertyRNA *prop;
+
+       srna= RNA_def_struct(brna, "MovieTrackingObject", NULL);
+       RNA_def_struct_ui_text(srna, "Movie tracking object data", "Match-moving object tracking and reconstruction data");
+
+       /* name */
+       prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Name", "Unique name of object");
+       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_trackingObject_name_set");
+       RNA_def_property_string_maxlength(prop, MAX_ID_NAME);
+       RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL);
+       RNA_def_struct_name_property(srna, prop);
+
+       /* is_camera */
+       prop= RNA_def_property(srna, "is_camera", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_OBJECT_CAMERA);
+       RNA_def_property_ui_text(prop, "Camera", "Object is used for camera tracking");
+       RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL);
+
+       /* tracks */
+       prop= RNA_def_property(srna, "tracks", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_funcs(prop, "rna_trackingObject_tracks_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0);
+       RNA_def_property_struct_type(prop, "MovieTrackingTrack");
+       RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
+       RNA_def_property_srna(prop, "MovieTrackingObjectTracks");
+
+       /* reconstruction */
+       prop= RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "MovieTrackingReconstruction");
+}
+
+static void rna_def_trackingObjects(BlenderRNA *brna, PropertyRNA *cprop)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       FunctionRNA *func;
+       PropertyRNA *parm;
+
+       RNA_def_property_srna(cprop, "MovieTrackingObjects");
+       srna= RNA_def_struct(brna, "MovieTrackingObjects", NULL);
+       RNA_def_struct_sdna(srna, "MovieTracking");
+       RNA_def_struct_ui_text(srna, "Movie Objects", "Collection of movie trackingobjects");
+
+       func= RNA_def_function(srna, "new", "rna_tracking_object_new");
+       RNA_def_function_ui_description(func, "Add tracking object to this movie clip");
+       RNA_def_string(func, "name", "", 0, "", "Name of new object");
+       parm= RNA_def_pointer(func, "object", "MovieTrackingObject", "", "New motion tracking object");
+       RNA_def_function_return(func, parm);
+
+       func= RNA_def_function(srna, "remove", "rna_tracking_object_remove");
+       RNA_def_function_ui_description(func, "Remove tracking object from this movie clip");
+       parm= RNA_def_pointer(func, "object", "MovieTrackingObject", "", "Motion tracking object to be removed");
+
+       /* active object */
+       prop= RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "MovieTrackingObject");
+       RNA_def_property_pointer_funcs(prop, "rna_tracking_active_object_get", "rna_tracking_active_object_set", NULL, NULL);
+       RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK);
+       RNA_def_property_ui_text(prop, "Active Object", "Active object in this tracking data object");
+}
+
 static void rna_def_tracking(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -915,8 +1141,11 @@ static void rna_def_tracking(BlenderRNA *brna)
        rna_def_trackingSettings(brna);
        rna_def_trackingCamera(brna);
        rna_def_trackingTrack(brna);
+       rna_def_trackingTracks(brna);
+       rna_def_trackingObjectTracks(brna);
        rna_def_trackingStabilization(brna);
        rna_def_trackingReconstruction(brna);
+       rna_def_trackingObject(brna);
 
        srna= RNA_def_struct(brna, "MovieTracking", NULL);
        RNA_def_struct_ui_text(srna, "Movie tracking data", "Match-moving data for tracking");
@@ -934,7 +1163,7 @@ static void rna_def_tracking(BlenderRNA *brna)
        RNA_def_property_collection_funcs(prop, "rna_tracking_tracks_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0);
        RNA_def_property_struct_type(prop, "MovieTrackingTrack");
        RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
-       rna_def_trackingTracks(brna, prop);
+       RNA_def_property_srna(prop, "MovieTrackingTracks");
 
        /* stabilization */
        prop= RNA_def_property(srna, "stabilization", PROP_POINTER, PROP_NONE);
@@ -943,6 +1172,20 @@ static void rna_def_tracking(BlenderRNA *brna)
        /* reconstruction */
        prop= RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "MovieTrackingReconstruction");
+
+       /* objects */
+       prop= RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_funcs(prop, "rna_tracking_objects_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0);
+       RNA_def_property_struct_type(prop, "MovieTrackingObject");
+       RNA_def_property_ui_text(prop, "Objects", "Collection of objects in this tracking data object");
+       rna_def_trackingObjects(brna, prop);
+
+       /* active object index */
+       prop= RNA_def_property(srna, "active_object_index", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "objectnr");
+       RNA_def_property_int_funcs(prop, "rna_tracking_active_object_index_get", "rna_tracking_active_object_index_set", "rna_tracking_active_object_index_range");
+       RNA_def_property_ui_text(prop, "Active Object Index", "Index of active object");
+       RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL);
 }
 
 void RNA_def_tracking(BlenderRNA *brna)