0ce4d54a74cd166de2bafed71083a14bb01ee885
[blender.git] / source / blender / blenkernel / intern / tracking.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *                 Keir Mierle
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/tracking.c
29  *  \ingroup bke
30  */
31
32 #include <stddef.h>
33 #include <limits.h>
34 #include <math.h>
35 #include <memory.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_gpencil_types.h"
40 #include "DNA_camera_types.h"
41 #include "DNA_movieclip_types.h"
42 #include "DNA_object_types.h"   /* SELECT */
43 #include "DNA_scene_types.h"
44
45 #include "BLI_utildefines.h"
46 #include "BLI_math.h"
47 #include "BLI_math_base.h"
48 #include "BLI_listbase.h"
49 #include "BLI_ghash.h"
50 #include "BLI_path_util.h"
51 #include "BLI_string.h"
52 #include "BLI_threads.h"
53
54 #include "BLF_translation.h"
55
56 #include "BKE_global.h"
57 #include "BKE_tracking.h"
58 #include "BKE_movieclip.h"
59 #include "BKE_object.h"
60 #include "BKE_scene.h"
61
62 #include "IMB_imbuf_types.h"
63 #include "IMB_imbuf.h"
64
65 #include "raskter.h"
66
67 #include "libmv-capi.h"
68
69 typedef struct MovieDistortion {
70         struct libmv_CameraIntrinsics *intrinsics;
71 } MovieDistortion;
72
73 static struct {
74         ListBase tracks;
75 } tracking_clipboard;
76
77 /*********************** Common functions *************************/
78
79 /* Duplicate the specified track, result will no belong to any list. */
80 static MovieTrackingTrack *tracking_track_duplicate(MovieTrackingTrack *track)
81 {
82         MovieTrackingTrack *new_track;
83
84         new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracking_track_duplicate new_track");
85
86         *new_track = *track;
87         new_track->next = new_track->prev = NULL;
88
89         new_track->markers = MEM_dupallocN(new_track->markers);
90
91         return new_track;
92 }
93
94 /* Free the whole list of tracks, list's head and tail are set to NULL. */
95 static void tracking_tracks_free(ListBase *tracks)
96 {
97         MovieTrackingTrack *track;
98
99         for (track = tracks->first; track; track = track->next) {
100                 BKE_tracking_track_free(track);
101         }
102
103         BLI_freelistN(tracks);
104 }
105
106 /* Free the whole list of plane tracks, list's head and tail are set to NULL. */
107 static void tracking_plane_tracks_free(ListBase *plane_tracks)
108 {
109         MovieTrackingPlaneTrack *plane_track;
110
111         for (plane_track = plane_tracks->first; plane_track; plane_track = plane_track->next) {
112                 BKE_tracking_plane_track_free(plane_track);
113         }
114
115         BLI_freelistN(plane_tracks);
116 }
117
118 /* Free reconstruction structures, only frees contents of a structure,
119  * (if structure is allocated in heap, it shall be handled outside).
120  *
121  * All the pointers inside structure becomes invalid after this call.
122  */
123 static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
124 {
125         if (reconstruction->cameras)
126                 MEM_freeN(reconstruction->cameras);
127 }
128
129 /* Free memory used by tracking object, only frees contents of the structure,
130  * (if structure is allocated in heap, it shall be handled outside).
131  *
132  * All the pointers inside structure becomes invalid after this call.
133  */
134 static void tracking_object_free(MovieTrackingObject *object)
135 {
136         tracking_tracks_free(&object->tracks);
137         tracking_plane_tracks_free(&object->plane_tracks);
138         tracking_reconstruction_free(&object->reconstruction);
139 }
140
141 /* Free list of tracking objects, list's head and tail is set to NULL. */
142 static void tracking_objects_free(ListBase *objects)
143 {
144         MovieTrackingObject *object;
145
146         /* Free objects contents. */
147         for (object = objects->first; object; object = object->next)
148                 tracking_object_free(object);
149
150         /* Free objects themselves. */
151         BLI_freelistN(objects);
152 }
153
154 /* Free memory used by a dopesheet, only frees dopesheet contents.
155  * leaving dopesheet crystal clean for further usage.
156  */
157 static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
158 {
159         MovieTrackingDopesheetChannel *channel;
160
161         /* Free channel's sergments. */
162         channel = dopesheet->channels.first;
163         while (channel) {
164                 if (channel->segments) {
165                         MEM_freeN(channel->segments);
166                 }
167
168                 channel = channel->next;
169         }
170
171         /* Free lists themselves. */
172         BLI_freelistN(&dopesheet->channels);
173         BLI_freelistN(&dopesheet->coverage_segments);
174
175         /* Ensure lists are clean. */
176         dopesheet->channels.first = dopesheet->channels.last = NULL;
177         dopesheet->coverage_segments.first = dopesheet->coverage_segments.last = NULL;
178         dopesheet->tot_channel = 0;
179 }
180
181 /* Free tracking structure, only frees structure contents
182  * (if structure is allocated in heap, it shall be handled outside).
183  *
184  * All the pointers inside structure becomes invalid after this call.
185  */
186 void BKE_tracking_free(MovieTracking *tracking)
187 {
188         tracking_tracks_free(&tracking->tracks);
189         tracking_plane_tracks_free(&tracking->plane_tracks);
190         tracking_reconstruction_free(&tracking->reconstruction);
191         tracking_objects_free(&tracking->objects);
192
193         if (tracking->camera.intrinsics)
194                 BKE_tracking_distortion_free(tracking->camera.intrinsics);
195
196         tracking_dopesheet_free(&tracking->dopesheet);
197 }
198
199 /* Initialize motion tracking settings to default values,
200  * used when new movie clip datablock is creating.
201  */
202 void BKE_tracking_settings_init(MovieTracking *tracking)
203 {
204         tracking->camera.sensor_width = 35.0f;
205         tracking->camera.pixel_aspect = 1.0f;
206         tracking->camera.units = CAMERA_UNITS_MM;
207
208         tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
209         tracking->settings.default_minimum_correlation = 0.75;
210         tracking->settings.default_pattern_size = 15;
211         tracking->settings.default_search_size = 61;
212         tracking->settings.default_algorithm_flag |= TRACK_ALGORITHM_FLAG_USE_BRUTE;
213         tracking->settings.dist = 1;
214         tracking->settings.object_distance = 1;
215
216         tracking->stabilization.scaleinf = 1.0f;
217         tracking->stabilization.locinf = 1.0f;
218         tracking->stabilization.rotinf = 1.0f;
219         tracking->stabilization.maxscale = 2.0f;
220         tracking->stabilization.filter = TRACKING_FILTER_BILINEAR;
221
222         BKE_tracking_object_add(tracking, "Camera");
223 }
224
225 /* Get list base of active object's tracks. */
226 ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
227 {
228         MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
229
230         if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
231                 return &object->tracks;
232         }
233
234         return &tracking->tracks;
235 }
236
237 /* Get list base of active object's plane tracks. */
238 ListBase *BKE_tracking_get_active_plane_tracks(MovieTracking *tracking)
239 {
240         MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
241
242         if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
243                 return &object->plane_tracks;
244         }
245
246         return &tracking->plane_tracks;
247 }
248
249 /* Get reconstruction data of active object. */
250 MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking)
251 {
252         MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
253
254         return BKE_tracking_object_get_reconstruction(tracking, object);
255 }
256
257 /* Get transformation matrix for a given object which is used
258  * for parenting motion tracker reconstruction to 3D world.
259  */
260 void BKE_tracking_get_camera_object_matrix(Scene *scene, Object *ob, float mat[4][4])
261 {
262         if (!ob) {
263                 if (scene->camera)
264                         ob = scene->camera;
265                 else
266                         ob = BKE_scene_camera_find(scene);
267         }
268
269         if (ob)
270                 BKE_object_where_is_calc_mat4(scene, ob, mat);
271         else
272                 unit_m4(mat);
273 }
274
275 /* Get projection matrix for camera specified by given tracking object
276  * and frame number.
277  *
278  * NOTE: frame number should be in clip space, not scene space
279  */
280 void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
281                                         int framenr, int winx, int winy, float mat[4][4])
282 {
283         MovieReconstructedCamera *camera;
284         float lens = tracking->camera.focal * tracking->camera.sensor_width / (float)winx;
285         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
286         float winmat[4][4];
287         float ycor =  1.0f / tracking->camera.pixel_aspect;
288         float shiftx, shifty, winside = (float)min_ii(winx, winy);
289
290         BKE_tracking_camera_shift_get(tracking, winx, winy, &shiftx, &shifty);
291
292         clipsta = 0.1f;
293         clipend = 1000.0f;
294
295         if (winx >= winy)
296                 viewfac = (lens * winx) / tracking->camera.sensor_width;
297         else
298                 viewfac = (ycor * lens * winy) / tracking->camera.sensor_width;
299
300         pixsize = clipsta / viewfac;
301
302         left = -0.5f * (float)winx + shiftx * winside;
303         bottom = -0.5f * (ycor) * (float)winy + shifty * winside;
304         right =  0.5f * (float)winx + shiftx * winside;
305         top =  0.5f * (ycor) * (float)winy + shifty * winside;
306
307         left *= pixsize;
308         right *= pixsize;
309         bottom *= pixsize;
310         top *= pixsize;
311
312         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
313
314         camera = BKE_tracking_camera_get_reconstructed(tracking, object, framenr);
315
316         if (camera) {
317                 float imat[4][4];
318
319                 invert_m4_m4(imat, camera->mat);
320                 mul_m4_m4m4(mat, winmat, imat);
321         }
322         else {
323                 copy_m4_m4(mat, winmat);
324         }
325 }
326
327 /* **** space transformation functions **** */
328
329 /* Three coordinate frames: Frame, Search, and Marker
330  * Two units: Pixels, Unified
331  * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search
332  * window relative coordinates in pixels, and "frame_unified" are unified 0..1
333  * coordinates relative to the entire frame.
334  */
335 static void unified_to_pixel(int frame_width, int frame_height,
336                              const float unified_coords[2], float pixel_coords[2])
337 {
338         pixel_coords[0] = unified_coords[0] * frame_width;
339         pixel_coords[1] = unified_coords[1] * frame_height;
340 }
341
342 static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2],
343                                     float frame_unified_coords[2])
344 {
345         frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0];
346         frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1];
347 }
348
349 static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height,
350                                                       const MovieTrackingMarker *marker,
351                                                       const float marker_unified_coords[2],
352                                                       float frame_pixel_coords[2])
353 {
354         marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords);
355         unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords);
356 }
357
358 static void get_search_origin_frame_pixel(int frame_width, int frame_height,
359                                           const MovieTrackingMarker *marker, float frame_pixel[2])
360 {
361         /* Get the lower left coordinate of the search window and snap to pixel coordinates */
362         marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker->search_min, frame_pixel);
363         frame_pixel[0] = (int)frame_pixel[0];
364         frame_pixel[1] = (int)frame_pixel[1];
365 }
366
367 static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2])
368 {
369         unified_coords[0] = pixel_coords[0] / frame_width;
370         unified_coords[1] = pixel_coords[1] / frame_height;
371 }
372
373 static void marker_unified_to_search_pixel(int frame_width, int frame_height,
374                                            const MovieTrackingMarker *marker,
375                                            const float marker_unified[2], float search_pixel[2])
376 {
377         float frame_pixel[2];
378         float search_origin_frame_pixel[2];
379
380         marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel);
381         get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
382         sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel);
383 }
384
385 static void search_pixel_to_marker_unified(int frame_width, int frame_height,
386                                            const MovieTrackingMarker *marker,
387                                            const float search_pixel[2], float marker_unified[2])
388 {
389         float frame_unified[2];
390         float search_origin_frame_pixel[2];
391
392         get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel);
393         add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel);
394         pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified);
395
396         /* marker pos is in frame unified */
397         sub_v2_v2v2(marker_unified, frame_unified, marker->pos);
398 }
399
400 /* Each marker has 5 coordinates associated with it that get warped with
401  * tracking: the four corners ("pattern_corners"), and the center ("pos").
402  * This function puts those 5 points into the appropriate frame for tracking
403  * (the "search" coordinate frame).
404  */
405 static void get_marker_coords_for_tracking(int frame_width, int frame_height,
406                                            const MovieTrackingMarker *marker,
407                                            double search_pixel_x[5], double search_pixel_y[5])
408 {
409         int i;
410         float unified_coords[2];
411         float pixel_coords[2];
412
413         /* Convert the corners into search space coordinates. */
414         for (i = 0; i < 4; i++) {
415                 marker_unified_to_search_pixel(frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords);
416                 search_pixel_x[i] = pixel_coords[0] - 0.5f;
417                 search_pixel_y[i] = pixel_coords[1] - 0.5f;
418         }
419
420         /* Convert the center position (aka "pos"); this is the origin */
421         unified_coords[0] = 0.0f;
422         unified_coords[1] = 0.0f;
423         marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords);
424
425         search_pixel_x[4] = pixel_coords[0] - 0.5f;
426         search_pixel_y[4] = pixel_coords[1] - 0.5f;
427 }
428
429 /* Inverse of above. */
430 static void set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker,
431                                             const double search_pixel_x[5], const double search_pixel_y[5])
432 {
433         int i;
434         float marker_unified[2];
435         float search_pixel[2];
436
437         /* Convert the corners into search space coordinates. */
438         for (i = 0; i < 4; i++) {
439                 search_pixel[0] = search_pixel_x[i] + 0.5;
440                 search_pixel[1] = search_pixel_y[i] + 0.5;
441                 search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]);
442         }
443
444         /* Convert the center position (aka "pos"); this is the origin */
445         search_pixel[0] = search_pixel_x[4] + 0.5;
446         search_pixel[1] = search_pixel_y[4] + 0.5;
447         search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified);
448
449         /* If the tracker tracked nothing, then "marker_unified" would be zero.
450          * Otherwise, the entire patch shifted, and that delta should be applied to
451          * all the coordinates.
452          */
453         for (i = 0; i < 4; i++) {
454                 marker->pattern_corners[i][0] -= marker_unified[0];
455                 marker->pattern_corners[i][1] -= marker_unified[1];
456         }
457
458         marker->pos[0] += marker_unified[0];
459         marker->pos[1] += marker_unified[1];
460 }
461
462 /*********************** clipboard *************************/
463
464 /* Free clipboard by freeing memory used by all tracks in it. */
465 void BKE_tracking_clipboard_free(void)
466 {
467         MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track;
468
469         while (track) {
470                 next_track = track->next;
471
472                 BKE_tracking_track_free(track);
473                 MEM_freeN(track);
474
475                 track = next_track;
476         }
477
478         tracking_clipboard.tracks.first = tracking_clipboard.tracks.last = NULL;
479 }
480
481 /* Copy selected tracks from specified object to the clipboard. */
482 void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object)
483 {
484         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
485         MovieTrackingTrack *track = tracksbase->first;
486
487         /* First drop all tracks from current clipboard. */
488         BKE_tracking_clipboard_free();
489
490         /* Then copy all selected visible tracks to it. */
491         while (track) {
492                 if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) {
493                         MovieTrackingTrack *new_track = tracking_track_duplicate(track);
494
495                         BLI_addtail(&tracking_clipboard.tracks, new_track);
496                 }
497
498                 track = track->next;
499         }
500 }
501
502 /* Check whether there're any tracks in the clipboard. */
503 bool BKE_tracking_clipboard_has_tracks(void)
504 {
505         return tracking_clipboard.tracks.first != NULL;
506 }
507
508 /* Paste tracks from clipboard to specified object.
509  *
510  * Names of new tracks in object are guaranteed to
511  * be unique here.
512  */
513 void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object)
514 {
515         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
516         MovieTrackingTrack *track = tracking_clipboard.tracks.first;
517
518         while (track) {
519                 MovieTrackingTrack *new_track = tracking_track_duplicate(track);
520
521                 BLI_addtail(tracksbase, new_track);
522                 BKE_tracking_track_unique_name(tracksbase, new_track);
523
524                 track = track->next;
525         }
526 }
527
528 /*********************** Tracks *************************/
529
530 /* Place a disabled marker before or after specified ref_marker.
531  *
532  * If before is truth, disabled marker is placed before reference
533  * one, and it's placed after it otherwise.
534  *
535  * If there's already a marker at the frame where disabled one
536  * is expected to be placed, nothing will happen if overwrite
537  * is false.
538  */
539 static void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker,
540                                             bool before, bool overwrite)
541 {
542         MovieTrackingMarker marker_new;
543
544         marker_new = *ref_marker;
545         marker_new.flag &= ~MARKER_TRACKED;
546         marker_new.flag |= MARKER_DISABLED;
547
548         if (before)
549                 marker_new.framenr--;
550         else
551                 marker_new.framenr++;
552
553         if (overwrite || !BKE_tracking_track_has_marker_at_frame(track, marker_new.framenr))
554                 BKE_tracking_marker_insert(track, &marker_new);
555 }
556
557 /* Add new track to a specified tracks base.
558  *
559  * Coordinates are expected to be in normalized 0..1 space,
560  * frame number is expected to be in clip space.
561  *
562  * Width and height are clip's dimension used to scale track's
563  * pattern and search regions.
564  */
565 MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
566                                            int framenr, int width, int height)
567 {
568         MovieTrackingTrack *track;
569         MovieTrackingMarker marker;
570         MovieTrackingSettings *settings = &tracking->settings;
571
572         float half_pattern = (float)settings->default_pattern_size / 2.0f;
573         float half_search = (float)settings->default_search_size / 2.0f;
574         float pat[2], search[2];
575
576         pat[0] = half_pattern / (float)width;
577         pat[1] = half_pattern / (float)height;
578
579         search[0] = half_search / (float)width;
580         search[1] = half_search / (float)height;
581
582         track = MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
583         strcpy(track->name, "Track");
584
585         /* fill track's settings from default settings */
586         track->motion_model = settings->default_motion_model;
587         track->minimum_correlation = settings->default_minimum_correlation;
588         track->margin = settings->default_margin;
589         track->pattern_match = settings->default_pattern_match;
590         track->frames_limit = settings->default_frames_limit;
591         track->flag = settings->default_flag;
592         track->algorithm_flag = settings->default_algorithm_flag;
593
594         memset(&marker, 0, sizeof(marker));
595         marker.pos[0] = x;
596         marker.pos[1] = y;
597         marker.framenr = framenr;
598
599         marker.pattern_corners[0][0] = -pat[0];
600         marker.pattern_corners[0][1] = -pat[1];
601
602         marker.pattern_corners[1][0] = pat[0];
603         marker.pattern_corners[1][1] = -pat[1];
604
605         negate_v2_v2(marker.pattern_corners[2], marker.pattern_corners[0]);
606         negate_v2_v2(marker.pattern_corners[3], marker.pattern_corners[1]);
607
608         copy_v2_v2(marker.search_max, search);
609         negate_v2_v2(marker.search_min, search);
610
611         BKE_tracking_marker_insert(track, &marker);
612
613         BLI_addtail(tracksbase, track);
614         BKE_tracking_track_unique_name(tracksbase, track);
615
616         return track;
617 }
618
619 /* Ensure specified track has got unique name,
620  * if it's not name of specified track will be changed
621  * keeping names of all other tracks unchanged.
622  */
623 void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
624 {
625         BLI_uniquename(tracksbase, track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.',
626                        offsetof(MovieTrackingTrack, name), sizeof(track->name));
627 }
628
629 /* Free specified track, only frees contents of a structure
630  * (if track is allocated in heap, it shall be handled outside).
631  *
632  * All the pointers inside track becomes invalid after this call.
633  */
634 void BKE_tracking_track_free(MovieTrackingTrack *track)
635 {
636         if (track->markers)
637                 MEM_freeN(track->markers);
638 }
639
640 /* Set flag for all specified track's areas.
641  *
642  * area - which part of marker should be selected. see TRACK_AREA_* constants.
643  * flag - flag to be set for areas.
644  */
645 void BKE_tracking_track_flag_set(MovieTrackingTrack *track, int area, int flag)
646 {
647         if (area == TRACK_AREA_NONE)
648                 return;
649
650         if (area & TRACK_AREA_POINT)
651                 track->flag |= flag;
652         if (area & TRACK_AREA_PAT)
653                 track->pat_flag |= flag;
654         if (area & TRACK_AREA_SEARCH)
655                 track->search_flag |= flag;
656 }
657
658 /* Clear flag from all specified track's areas.
659  *
660  * area - which part of marker should be selected. see TRACK_AREA_* constants.
661  * flag - flag to be cleared for areas.
662  */
663 void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag)
664 {
665         if (area == TRACK_AREA_NONE)
666                 return;
667
668         if (area & TRACK_AREA_POINT)
669                 track->flag &= ~flag;
670         if (area & TRACK_AREA_PAT)
671                 track->pat_flag &= ~flag;
672         if (area & TRACK_AREA_SEARCH)
673                 track->search_flag &= ~flag;
674 }
675
676 /* Check whether track has got marker at specified frame.
677  *
678  * NOTE: frame number should be in clip space, not scene space.
679  */
680 bool BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr)
681 {
682         return BKE_tracking_marker_get_exact(track, framenr) != NULL;
683 }
684
685 /* Check whether track has got enabled marker at specified frame.
686  *
687  * NOTE: frame number should be in clip space, not scene space.
688  */
689 bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr)
690 {
691         MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
692
693         return marker && (marker->flag & MARKER_DISABLED) == 0;
694 }
695
696 /* Clear track's path:
697  *
698  * - If action is TRACK_CLEAR_REMAINED path from ref_frame+1 up to
699  *   end will be clear.
700  *
701  * - If action is TRACK_CLEAR_UPTO path from the beginning up to
702  *   ref_frame-1 will be clear.
703  *
704  * - If action is TRACK_CLEAR_ALL only mareker at frame ref_frame will remain.
705  *
706  * NOTE: frame number should be in clip space, not scene space
707  */
708 void BKE_tracking_track_path_clear(MovieTrackingTrack *track, int ref_frame, int action)
709 {
710         int a;
711
712         if (action == TRACK_CLEAR_REMAINED) {
713                 a = 1;
714
715                 while (a < track->markersnr) {
716                         if (track->markers[a].framenr > ref_frame) {
717                                 track->markersnr = a;
718                                 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
719
720                                 break;
721                         }
722
723                         a++;
724                 }
725
726                 if (track->markersnr)
727                         tracking_marker_insert_disabled(track, &track->markers[track->markersnr - 1], false, true);
728         }
729         else if (action == TRACK_CLEAR_UPTO) {
730                 a = track->markersnr - 1;
731
732                 while (a >= 0) {
733                         if (track->markers[a].framenr <= ref_frame) {
734                                 memmove(track->markers, track->markers + a, (track->markersnr - a) * sizeof(MovieTrackingMarker));
735
736                                 track->markersnr = track->markersnr - a;
737                                 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
738
739                                 break;
740                         }
741
742                         a--;
743                 }
744
745                 if (track->markersnr)
746                         tracking_marker_insert_disabled(track, &track->markers[0], true, true);
747         }
748         else if (action == TRACK_CLEAR_ALL) {
749                 MovieTrackingMarker *marker, marker_new;
750
751                 marker = BKE_tracking_marker_get(track, ref_frame);
752                 marker_new = *marker;
753
754                 MEM_freeN(track->markers);
755                 track->markers = NULL;
756                 track->markersnr = 0;
757
758                 BKE_tracking_marker_insert(track, &marker_new);
759
760                 tracking_marker_insert_disabled(track, &marker_new, true, true);
761                 tracking_marker_insert_disabled(track, &marker_new, false, true);
762         }
763 }
764
765 void BKE_tracking_tracks_join(MovieTracking *tracking, MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
766 {
767         int i = 0, a = 0, b = 0, tot;
768         MovieTrackingMarker *markers;
769
770         tot = dst_track->markersnr + src_track->markersnr;
771         markers = MEM_callocN(tot * sizeof(MovieTrackingMarker), "tmp tracking joined tracks");
772
773         while (a < src_track->markersnr || b < dst_track->markersnr) {
774                 if (b >= dst_track->markersnr) {
775                         markers[i] = src_track->markers[a++];
776                 }
777                 else if (a >= src_track->markersnr) {
778                         markers[i] = dst_track->markers[b++];
779                 }
780                 else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) {
781                         markers[i] = src_track->markers[a++];
782                 }
783                 else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) {
784                         markers[i] = dst_track->markers[b++];
785                 }
786                 else {
787                         if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) {
788                                 if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) {
789                                         /* both tracks are enabled on this frame, so find the whole segment
790                                          * on which tracks are intersecting and blend tracks using linear
791                                          * interpolation to prevent jumps
792                                          */
793
794                                         MovieTrackingMarker *marker_a, *marker_b;
795                                         int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr;
796                                         int j, inverse = 0;
797
798                                         inverse = (b == 0) ||
799                                                   (dst_track->markers[b - 1].flag & MARKER_DISABLED) ||
800                                                   (dst_track->markers[b - 1].framenr != frame - 1);
801
802                                         /* find length of intersection */
803                                         while (a < src_track->markersnr && b < dst_track->markersnr) {
804                                                 marker_a = &src_track->markers[a];
805                                                 marker_b = &dst_track->markers[b];
806
807                                                 if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED)
808                                                         break;
809
810                                                 if (marker_a->framenr != frame || marker_b->framenr != frame)
811                                                         break;
812
813                                                 frame++;
814                                                 len++;
815                                                 a++;
816                                                 b++;
817                                         }
818
819                                         a = start_a;
820                                         b = start_b;
821
822                                         /* linear interpolation for intersecting frames */
823                                         for (j = 0; j < len; j++) {
824                                                 float fac = 0.5f;
825
826                                                 if (len > 1)
827                                                         fac = 1.0f / (len - 1) * j;
828
829                                                 if (inverse)
830                                                         fac = 1.0f - fac;
831
832                                                 marker_a = &src_track->markers[a];
833                                                 marker_b = &dst_track->markers[b];
834
835                                                 markers[i] = dst_track->markers[b];
836                                                 interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac);
837                                                 a++;
838                                                 b++;
839                                                 i++;
840                                         }
841
842                                         /* this values will be incremented at the end of the loop cycle */
843                                         a--; b--; i--;
844                                 }
845                                 else {
846                                         markers[i] = src_track->markers[a];
847                                 }
848                         }
849                         else {
850                                 markers[i] = dst_track->markers[b];
851                         }
852
853                         a++;
854                         b++;
855                 }
856
857                 i++;
858         }
859
860         MEM_freeN(dst_track->markers);
861
862         dst_track->markers = MEM_callocN(i * sizeof(MovieTrackingMarker), "tracking joined tracks");
863         memcpy(dst_track->markers, markers, i * sizeof(MovieTrackingMarker));
864
865         dst_track->markersnr = i;
866
867         MEM_freeN(markers);
868
869         BKE_tracking_dopesheet_tag_update(tracking);
870 }
871
872 MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
873 {
874         ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
875         MovieTrackingTrack *track = tracksbase->first;
876
877         while (track) {
878                 if (!strcmp(track->name, name))
879                         return track;
880
881                 track = track->next;
882         }
883
884         return NULL;
885 }
886
887 MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
888 {
889         MovieTrackingObject *object;
890         int cur = 1;
891
892         object = tracking->objects.first;
893         while (object) {
894                 ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
895                 MovieTrackingTrack *track = tracksbase->first;
896
897                 while (track) {
898                         if (track->flag & TRACK_HAS_BUNDLE) {
899                                 if (cur == tracknr) {
900                                         *tracksbase_r = tracksbase;
901                                         return track;
902                                 }
903
904                                 cur++;
905                         }
906
907                         track = track->next;
908                 }
909
910                 object = object->next;
911         }
912
913         *tracksbase_r = NULL;
914
915         return NULL;
916 }
917
918 MovieTrackingTrack *BKE_tracking_track_get_active(MovieTracking *tracking)
919 {
920         ListBase *tracksbase;
921
922         if (!tracking->act_track)
923                 return NULL;
924
925         tracksbase = BKE_tracking_get_active_tracks(tracking);
926
927         /* check that active track is in current tracks list */
928         if (BLI_findindex(tracksbase, tracking->act_track) >= 0)
929                 return tracking->act_track;
930
931         return NULL;
932 }
933
934 static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track)
935 {
936         bGPDlayer *layer;
937
938         if (!track->gpd)
939                 return NULL;
940
941         layer = track->gpd->layers.first;
942
943         while (layer) {
944                 if (layer->flag & GP_LAYER_ACTIVE) {
945                         bGPDframe *frame = layer->frames.first;
946                         bool ok = false;
947
948                         while (frame) {
949                                 if (frame->strokes.first) {
950                                         ok = true;
951                                         break;
952                                 }
953
954                                 frame = frame->next;
955                         }
956
957                         if (ok)
958                                 return layer;
959                 }
960
961                 layer = layer->next;
962         }
963
964         return NULL;
965 }
966
967 static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height,
968                                                MovieTrackingMarker *marker, bGPDlayer *layer,
969                                                float *mask, int mask_width, int mask_height)
970 {
971         bGPDframe *frame = layer->frames.first;
972
973         while (frame) {
974                 bGPDstroke *stroke = frame->strokes.first;
975
976                 while (stroke) {
977                         bGPDspoint *stroke_points = stroke->points;
978                         float *mask_points, *fp;
979                         int i;
980
981                         if (stroke->flag & GP_STROKE_2DSPACE) {
982                                 fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float),
983                                                                "track mask rasterization points");
984
985                                 for (i = 0; i < stroke->totpoints; i++, fp += 2) {
986                                         fp[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width / mask_width;
987                                         fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height;
988                                 }
989
990                                 /* TODO: add an option to control whether AA is enabled or not */
991                                 PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height);
992
993                                 MEM_freeN(mask_points);
994                         }
995
996                         stroke = stroke->next;
997                 }
998
999                 frame = frame->next;
1000         }
1001 }
1002
1003 float *BKE_tracking_track_get_mask(int frame_width, int frame_height,
1004                                    MovieTrackingTrack *track, MovieTrackingMarker *marker)
1005 {
1006         float *mask = NULL;
1007         bGPDlayer *layer = track_mask_gpencil_layer_get(track);
1008         int mask_width, mask_height;
1009
1010         mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width;
1011         mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height;
1012
1013         if (layer) {
1014                 mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask");
1015
1016                 track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer,
1017                                                    mask, mask_width, mask_height);
1018         }
1019
1020         return mask;
1021 }
1022
1023 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
1024 void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, bool extend)
1025 {
1026         if (extend) {
1027                 BKE_tracking_track_flag_set(track, area, SELECT);
1028         }
1029         else {
1030                 MovieTrackingTrack *cur = tracksbase->first;
1031
1032                 while (cur) {
1033                         if ((cur->flag & TRACK_HIDDEN) == 0) {
1034                                 if (cur == track) {
1035                                         BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT);
1036                                         BKE_tracking_track_flag_set(cur, area, SELECT);
1037                                 }
1038                                 else {
1039                                         BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT);
1040                                 }
1041                         }
1042
1043                         cur = cur->next;
1044                 }
1045         }
1046 }
1047
1048 void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area)
1049 {
1050         BKE_tracking_track_flag_clear(track, area, SELECT);
1051 }
1052
1053 void BKE_tracking_tracks_deselect_all(ListBase *tracksbase)
1054 {
1055         MovieTrackingTrack *track;
1056
1057         for (track = tracksbase->first; track; track = track->next) {
1058                 if ((track->flag & TRACK_HIDDEN) == 0) {
1059                         BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
1060                 }
1061         }
1062 }
1063
1064 /*********************** Marker *************************/
1065
1066 MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker)
1067 {
1068         MovieTrackingMarker *old_marker = NULL;
1069
1070         if (track->markersnr)
1071                 old_marker = BKE_tracking_marker_get_exact(track, marker->framenr);
1072
1073         if (old_marker) {
1074                 /* simply replace settings for already allocated marker */
1075                 *old_marker = *marker;
1076
1077                 return old_marker;
1078         }
1079         else {
1080                 int a = track->markersnr;
1081
1082                 /* find position in array where to add new marker */
1083                 while (a--) {
1084                         if (track->markers[a].framenr < marker->framenr)
1085                                 break;
1086                 }
1087
1088                 track->markersnr++;
1089
1090                 if (track->markers)
1091                         track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
1092                 else
1093                         track->markers = MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
1094
1095                 /* shift array to "free" space for new marker */
1096                 memmove(track->markers + a + 2, track->markers + a + 1,
1097                         (track->markersnr - a - 2) * sizeof(MovieTrackingMarker));
1098
1099                 /* put new marker */
1100                 track->markers[a + 1] = *marker;
1101
1102                 track->last_marker = a + 1;
1103
1104                 return &track->markers[a + 1];
1105         }
1106 }
1107
1108 void BKE_tracking_marker_delete(MovieTrackingTrack *track, int framenr)
1109 {
1110         int a = 0;
1111
1112         while (a < track->markersnr) {
1113                 if (track->markers[a].framenr == framenr) {
1114                         if (track->markersnr > 1) {
1115                                 memmove(track->markers + a, track->markers + a + 1,
1116                                         (track->markersnr - a - 1) * sizeof(MovieTrackingMarker));
1117                                 track->markersnr--;
1118                                 track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr);
1119                         }
1120                         else {
1121                                 MEM_freeN(track->markers);
1122                                 track->markers = NULL;
1123                                 track->markersnr = 0;
1124                         }
1125
1126                         break;
1127                 }
1128
1129                 a++;
1130         }
1131 }
1132
1133 void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
1134 {
1135         int a;
1136         float pat_min[2], pat_max[2];
1137
1138         BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1139
1140         if (event == CLAMP_PAT_DIM) {
1141                 for (a = 0; a < 2; a++) {
1142                         /* search shouldn't be resized smaller than pattern */
1143                         marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]);
1144                         marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]);
1145                 }
1146         }
1147         else if (event == CLAMP_PAT_POS) {
1148                 float dim[2];
1149
1150                 sub_v2_v2v2(dim, pat_max, pat_min);
1151
1152                 for (a = 0; a < 2; a++) {
1153                         int b;
1154                         /* pattern shouldn't be moved outside of search */
1155                         if (pat_min[a] < marker->search_min[a]) {
1156                                 for (b = 0; b < 4; b++)
1157                                         marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a];
1158                         }
1159                         if (pat_max[a] > marker->search_max[a]) {
1160                                 for (b = 0; b < 4; b++)
1161                                         marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a];
1162                         }
1163                 }
1164         }
1165         else if (event == CLAMP_SEARCH_DIM) {
1166                 for (a = 0; a < 2; a++) {
1167                         /* search shouldn't be resized smaller than pattern */
1168                         marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]);
1169                         marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]);
1170                 }
1171         }
1172         else if (event == CLAMP_SEARCH_POS) {
1173                 float dim[2];
1174
1175                 sub_v2_v2v2(dim, marker->search_max, marker->search_min);
1176
1177                 for (a = 0; a < 2; a++) {
1178                         /* search shouldn't be moved inside pattern */
1179                         if (marker->search_min[a] > pat_min[a]) {
1180                                 marker->search_min[a] = pat_min[a];
1181                                 marker->search_max[a] = marker->search_min[a] + dim[a];
1182                         }
1183                         if (marker->search_max[a] < pat_max[a]) {
1184                                 marker->search_max[a] = pat_max[a];
1185                                 marker->search_min[a] = marker->search_max[a] - dim[a];
1186                         }
1187                 }
1188         }
1189 }
1190
1191 MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr)
1192 {
1193         int a = track->markersnr - 1;
1194
1195         if (!track->markersnr)
1196                 return NULL;
1197
1198         /* approximate pre-first framenr marker with first marker */
1199         if (framenr < track->markers[0].framenr)
1200                 return &track->markers[0];
1201
1202         if (track->last_marker < track->markersnr)
1203                 a = track->last_marker;
1204
1205         if (track->markers[a].framenr <= framenr) {
1206                 while (a < track->markersnr && track->markers[a].framenr <= framenr) {
1207                         if (track->markers[a].framenr == framenr) {
1208                                 track->last_marker = a;
1209
1210                                 return &track->markers[a];
1211                         }
1212                         a++;
1213                 }
1214
1215                 /* if there's no marker for exact position, use nearest marker from left side */
1216                 return &track->markers[a - 1];
1217         }
1218         else {
1219                 while (a >= 0 && track->markers[a].framenr >= framenr) {
1220                         if (track->markers[a].framenr == framenr) {
1221                                 track->last_marker = a;
1222
1223                                 return &track->markers[a];
1224                         }
1225
1226                         a--;
1227                 }
1228
1229                 /* if there's no marker for exact position, use nearest marker from left side */
1230                 return &track->markers[a];
1231         }
1232
1233         return NULL;
1234 }
1235
1236 MovieTrackingMarker *BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr)
1237 {
1238         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1239
1240         if (marker->framenr != framenr)
1241                 return NULL;
1242
1243         return marker;
1244 }
1245
1246 MovieTrackingMarker *BKE_tracking_marker_ensure(MovieTrackingTrack *track, int framenr)
1247 {
1248         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1249
1250         if (marker->framenr != framenr) {
1251                 MovieTrackingMarker marker_new;
1252
1253                 marker_new = *marker;
1254                 marker_new.framenr = framenr;
1255
1256                 BKE_tracking_marker_insert(track, &marker_new);
1257                 marker = BKE_tracking_marker_get(track, framenr);
1258         }
1259
1260         return marker;
1261 }
1262
1263 void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2])
1264 {
1265         INIT_MINMAX2(min, max);
1266
1267         minmax_v2v2_v2(min, max, marker->pattern_corners[0]);
1268         minmax_v2v2_v2(min, max, marker->pattern_corners[1]);
1269         minmax_v2v2_v2(min, max, marker->pattern_corners[2]);
1270         minmax_v2v2_v2(min, max, marker->pattern_corners[3]);
1271 }
1272
1273 void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float framenr, float pos[2])
1274 {
1275         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, (int) framenr);
1276         MovieTrackingMarker *marker_last = track->markers + (track->markersnr - 1);
1277
1278         if (marker != marker_last) {
1279                 MovieTrackingMarker *marker_next = marker + 1;
1280
1281                 if (marker_next->framenr == marker->framenr + 1) {
1282                         /* currently only do subframing inside tracked ranges, do not extrapolate tracked segments
1283                          * could be changed when / if mask parent would be interpolating position in-between
1284                          * tracked segments
1285                          */
1286
1287                         float fac = (framenr - (int) framenr) / (marker_next->framenr - marker->framenr);
1288
1289                         interp_v2_v2v2(pos, marker->pos, marker_next->pos, fac);
1290                 }
1291                 else {
1292                         copy_v2_v2(pos, marker->pos);
1293                 }
1294         }
1295         else {
1296                 copy_v2_v2(pos, marker->pos);
1297         }
1298
1299         /* currently track offset is always wanted to be applied here, could be made an option later */
1300         add_v2_v2(pos, track->offset);
1301 }
1302
1303 /*********************** Plane Track *************************/
1304
1305 /* Creates new plane track out of selected point tracks */
1306 MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, ListBase *plane_tracks_base,
1307                                                       ListBase *tracks, int framenr)
1308 {
1309         MovieTrackingPlaneTrack *plane_track;
1310         MovieTrackingPlaneMarker plane_marker;
1311         MovieTrackingTrack *track;
1312         float tracks_min[2], tracks_max[2];
1313         int track_index, num_selected_tracks = 0;
1314
1315         (void) tracking;  /* Ignored. */
1316
1317         /* Use bounding box of selected markers as an initial size of plane. */
1318         INIT_MINMAX2(tracks_min, tracks_max);
1319         for (track = tracks->first; track; track = track->next) {
1320                 if (TRACK_SELECTED(track)) {
1321                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1322                         float pattern_min[2], pattern_max[2];
1323                         BKE_tracking_marker_pattern_minmax(marker, pattern_min, pattern_max);
1324                         add_v2_v2(pattern_min, marker->pos);
1325                         add_v2_v2(pattern_max, marker->pos);
1326                         minmax_v2v2_v2(tracks_min, tracks_max, pattern_min);
1327                         minmax_v2v2_v2(tracks_min, tracks_max, pattern_max);
1328                         num_selected_tracks++;
1329                 }
1330         }
1331
1332         if (num_selected_tracks < 4) {
1333                 return NULL;
1334         }
1335
1336         /* Allocate new plane track. */
1337         plane_track = MEM_callocN(sizeof(MovieTrackingPlaneTrack), "new plane track");
1338
1339         /* Use some default name. */
1340         strcpy(plane_track->name, "Plane Track");
1341
1342         /* Use selected tracks from given list as a plane. */
1343         plane_track->point_tracks = MEM_mallocN(sizeof(MovieTrackingTrack *) * num_selected_tracks, "new plane tracks array");
1344         for (track = tracks->first, track_index = 0; track; track = track->next) {
1345                 if (TRACK_SELECTED(track)) {
1346                         plane_track->point_tracks[track_index] = track;
1347                         track_index++;
1348                 }
1349         }
1350         plane_track->point_tracksnr = num_selected_tracks;
1351
1352         /* Setup new plane marker and add it to the track. */
1353         plane_marker.framenr = framenr;
1354         plane_marker.flag = 0;
1355
1356         copy_v2_v2(plane_marker.corners[0], tracks_min);
1357         copy_v2_v2(plane_marker.corners[2], tracks_max);
1358
1359         plane_marker.corners[1][0] = tracks_max[0];
1360         plane_marker.corners[1][1] = tracks_min[1];
1361         plane_marker.corners[3][0] = tracks_min[0];
1362         plane_marker.corners[3][1] = tracks_max[1];
1363
1364         BKE_tracking_plane_marker_insert(plane_track, &plane_marker);
1365
1366         /* Put new plane track to the list, ensure it's name is unique. */
1367         BLI_addtail(plane_tracks_base, plane_track);
1368         BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
1369
1370         return plane_track;
1371 }
1372
1373 void BKE_tracking_plane_track_unique_name(ListBase *plane_tracks_base, MovieTrackingPlaneTrack *plane_track)
1374 {
1375         BLI_uniquename(plane_tracks_base, plane_track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Plane Track"), '.',
1376                        offsetof(MovieTrackingPlaneTrack, name), sizeof(plane_track->name));
1377 }
1378
1379 /* Free specified plane track, only frees contents of a structure
1380  * (if track is allocated in heap, it shall be handled outside).
1381  *
1382  * All the pointers inside track becomes invalid after this call.
1383  */
1384 void BKE_tracking_plane_track_free(MovieTrackingPlaneTrack *plane_track)
1385 {
1386         if (plane_track->markers) {
1387                 MEM_freeN(plane_track->markers);
1388         }
1389
1390         MEM_freeN(plane_track->point_tracks);
1391 }
1392
1393 MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *tracking,
1394                                                             MovieTrackingObject *object,
1395                                                             const char *name)
1396 {
1397         ListBase *plane_tracks_base = BKE_tracking_object_get_plane_tracks(tracking, object);
1398         MovieTrackingPlaneTrack *plane_track;
1399
1400         for (plane_track = plane_tracks_base->first;
1401              plane_track;
1402              plane_track = plane_track->next)
1403         {
1404                 if (!strcmp(plane_track->name, name)) {
1405                         return plane_track;
1406                 }
1407         }
1408
1409         return NULL;
1410 }
1411
1412 MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking)
1413 {
1414         ListBase *plane_tracks_base;
1415
1416         if (tracking->act_plane_track == NULL) {
1417                 return NULL;
1418         }
1419
1420         plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
1421
1422         /* Check that active track is in current plane tracks list */
1423         if (BLI_findindex(plane_tracks_base, tracking->act_plane_track) >= 0) {
1424                 return tracking->act_plane_track;
1425         }
1426
1427         return NULL;
1428 }
1429
1430 void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
1431 {
1432         MovieTrackingPlaneTrack *plane_track;
1433
1434         for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
1435                 plane_track->flag &= ~SELECT;
1436         }
1437 }
1438
1439 /*********************** Plane Marker *************************/
1440
1441 MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track,
1442                                                            MovieTrackingPlaneMarker *plane_marker)
1443 {
1444         MovieTrackingPlaneMarker *old_plane_marker = NULL;
1445
1446         if (plane_track->markersnr)
1447                 old_plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, plane_marker->framenr);
1448
1449         if (old_plane_marker) {
1450                 /* Simply replace settings in existing marker. */
1451                 *old_plane_marker = *plane_marker;
1452
1453                 return old_plane_marker;
1454         }
1455         else {
1456                 int a = plane_track->markersnr;
1457
1458                 /* Find position in array where to add new marker. */
1459                 /* TODO(sergey): we coud use bisect to speed things up. */
1460                 while (a--) {
1461                         if (plane_track->markers[a].framenr < plane_marker->framenr) {
1462                                 break;
1463                         }
1464                 }
1465
1466                 plane_track->markersnr++;
1467                 plane_track->markers = MEM_reallocN(plane_track->markers,
1468                                                     sizeof(MovieTrackingPlaneMarker) * plane_track->markersnr);
1469
1470                 /* Shift array to "free" space for new marker. */
1471                 memmove(plane_track->markers + a + 2, plane_track->markers + a + 1,
1472                         (plane_track->markersnr - a - 2) * sizeof(MovieTrackingPlaneMarker));
1473
1474                 /* Put new marker to an array. */
1475                 plane_track->markers[a + 1] = *plane_marker;
1476                 plane_track->last_marker = a + 1;
1477
1478                 return &plane_track->markers[a + 1];
1479         }
1480 }
1481
1482 void BKE_tracking_plane_marker_delete(MovieTrackingPlaneTrack *plane_track, int framenr)
1483 {
1484         int a = 0;
1485
1486         while (a < plane_track->markersnr) {
1487                 if (plane_track->markers[a].framenr == framenr) {
1488                         if (plane_track->markersnr > 1) {
1489                                 memmove(plane_track->markers + a, plane_track->markers + a + 1,
1490                                         (plane_track->markersnr - a - 1) * sizeof(MovieTrackingPlaneMarker));
1491                                 plane_track->markersnr--;
1492                                 plane_track->markers = MEM_reallocN(plane_track->markers,
1493                                                                     sizeof(MovieTrackingMarker) * plane_track->markersnr);
1494                         }
1495                         else {
1496                                 MEM_freeN(plane_track->markers);
1497                                 plane_track->markers = NULL;
1498                                 plane_track->markersnr = 0;
1499                         }
1500
1501                         break;
1502                 }
1503
1504                 a++;
1505         }
1506 }
1507
1508 /* TODO(sergey): The next couple of functions are really quite the same as point marker version,
1509  *               would be nice to de-duplicate them somehow..
1510  */
1511
1512 /* Get a plane marker at given frame,
1513  * If there's no such marker, closest one from the left side will be returned.
1514  */
1515 MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(MovieTrackingPlaneTrack *plane_track, int framenr)
1516 {
1517         int a = plane_track->markersnr - 1;
1518
1519         if (!plane_track->markersnr)
1520                 return NULL;
1521
1522         /* Approximate pre-first framenr marker with first marker. */
1523         if (framenr < plane_track->markers[0].framenr) {
1524                 return &plane_track->markers[0];
1525         }
1526
1527         if (plane_track->last_marker < plane_track->markersnr) {
1528                 a = plane_track->last_marker;
1529         }
1530
1531         if (plane_track->markers[a].framenr <= framenr) {
1532                 while (a < plane_track->markersnr && plane_track->markers[a].framenr <= framenr) {
1533                         if (plane_track->markers[a].framenr == framenr) {
1534                                 plane_track->last_marker = a;
1535
1536                                 return &plane_track->markers[a];
1537                         }
1538                         a++;
1539                 }
1540
1541                 /* If there's no marker for exact position, use nearest marker from left side. */
1542                 return &plane_track->markers[a - 1];
1543         }
1544         else {
1545                 while (a >= 0 && plane_track->markers[a].framenr >= framenr) {
1546                         if (plane_track->markers[a].framenr == framenr) {
1547                                 plane_track->last_marker = a;
1548
1549                                 return &plane_track->markers[a];
1550                         }
1551
1552                         a--;
1553                 }
1554
1555                 /* If there's no marker for exact position, use nearest marker from left side. */
1556                 return &plane_track->markers[a];
1557         }
1558
1559         return NULL;
1560 }
1561
1562 /* Get a plane marker at exact given frame, if there's no marker at the frame,
1563  * NULL will be returned.
1564  */
1565 MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(MovieTrackingPlaneTrack *plane_track, int framenr)
1566 {
1567         MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
1568
1569         if (plane_marker->framenr != framenr) {
1570                 return NULL;
1571         }
1572
1573         return plane_marker;
1574 }
1575
1576 /* Ensure there's a marker for the given frame. */
1577 MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTrack *plane_track, int framenr)
1578 {
1579         MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
1580
1581         if (plane_marker->framenr != framenr) {
1582                 MovieTrackingPlaneMarker plane_marker_new;
1583
1584                 plane_marker_new = *plane_marker;
1585                 plane_marker_new.framenr = framenr;
1586
1587                 plane_marker = BKE_tracking_plane_marker_insert(plane_track, &plane_marker_new);
1588         }
1589
1590         return plane_marker;
1591 }
1592
1593 /*********************** Object *************************/
1594
1595 MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name)
1596 {
1597         MovieTrackingObject *object = MEM_callocN(sizeof(MovieTrackingObject), "tracking object");
1598
1599         if (tracking->tot_object == 0) {
1600                 /* first object is always camera */
1601                 BLI_strncpy(object->name, "Camera", sizeof(object->name));
1602
1603                 object->flag |= TRACKING_OBJECT_CAMERA;
1604         }
1605         else {
1606                 BLI_strncpy(object->name, name, sizeof(object->name));
1607         }
1608
1609         BLI_addtail(&tracking->objects, object);
1610
1611         tracking->tot_object++;
1612         tracking->objectnr = BLI_countlist(&tracking->objects) - 1;
1613
1614         object->scale = 1.0f;
1615         object->keyframe1 = 1;
1616         object->keyframe2 = 30;
1617
1618         BKE_tracking_object_unique_name(tracking, object);
1619         BKE_tracking_dopesheet_tag_update(tracking);
1620
1621         return object;
1622 }
1623
1624 bool BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object)
1625 {
1626         MovieTrackingTrack *track;
1627         int index = BLI_findindex(&tracking->objects, object);
1628
1629         if (index == -1)
1630                 return false;
1631
1632         if (object->flag & TRACKING_OBJECT_CAMERA) {
1633                 /* object used for camera solving can't be deleted */
1634                 return false;
1635         }
1636
1637         track = object->tracks.first;
1638         while (track) {
1639                 if (track == tracking->act_track)
1640                         tracking->act_track = NULL;
1641
1642                 track = track->next;
1643         }
1644
1645         tracking_object_free(object);
1646         BLI_freelinkN(&tracking->objects, object);
1647
1648         tracking->tot_object--;
1649
1650         if (index != 0)
1651                 tracking->objectnr = index - 1;
1652         else
1653                 tracking->objectnr = 0;
1654
1655         BKE_tracking_dopesheet_tag_update(tracking);
1656
1657         return true;
1658 }
1659
1660 void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
1661 {
1662         BLI_uniquename(&tracking->objects, object, DATA_("Object"), '.',
1663                        offsetof(MovieTrackingObject, name), sizeof(object->name));
1664 }
1665
1666 MovieTrackingObject *BKE_tracking_object_get_named(MovieTracking *tracking, const char *name)
1667 {
1668         MovieTrackingObject *object = tracking->objects.first;
1669
1670         while (object) {
1671                 if (!strcmp(object->name, name))
1672                         return object;
1673
1674                 object = object->next;
1675         }
1676
1677         return NULL;
1678 }
1679
1680 MovieTrackingObject *BKE_tracking_object_get_active(MovieTracking *tracking)
1681 {
1682         return BLI_findlink(&tracking->objects, tracking->objectnr);
1683 }
1684
1685 MovieTrackingObject *BKE_tracking_object_get_camera(MovieTracking *tracking)
1686 {
1687         MovieTrackingObject *object = tracking->objects.first;
1688
1689         while (object) {
1690                 if (object->flag & TRACKING_OBJECT_CAMERA)
1691                         return object;
1692
1693                 object = object->next;
1694         }
1695
1696         return NULL;
1697 }
1698
1699 ListBase *BKE_tracking_object_get_tracks(MovieTracking *tracking, MovieTrackingObject *object)
1700 {
1701         if (object->flag & TRACKING_OBJECT_CAMERA) {
1702                 return &tracking->tracks;
1703         }
1704
1705         return &object->tracks;
1706 }
1707
1708 ListBase *BKE_tracking_object_get_plane_tracks(MovieTracking *tracking, MovieTrackingObject *object)
1709 {
1710         if (object->flag & TRACKING_OBJECT_CAMERA) {
1711                 return &tracking->plane_tracks;
1712         }
1713
1714         return &object->plane_tracks;
1715 }
1716
1717 MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(MovieTracking *tracking,
1718                                                                     MovieTrackingObject *object)
1719 {
1720         if (object->flag & TRACKING_OBJECT_CAMERA) {
1721                 return &tracking->reconstruction;
1722         }
1723
1724         return &object->reconstruction;
1725 }
1726
1727 /*********************** Camera *************************/
1728
1729 static int reconstructed_camera_index_get(MovieTrackingReconstruction *reconstruction, int framenr, bool nearest)
1730 {
1731         MovieReconstructedCamera *cameras = reconstruction->cameras;
1732         int a = 0, d = 1;
1733
1734         if (!reconstruction->camnr)
1735                 return -1;
1736
1737         if (framenr < cameras[0].framenr) {
1738                 if (nearest)
1739                         return 0;
1740                 else
1741                         return -1;
1742         }
1743
1744         if (framenr > cameras[reconstruction->camnr - 1].framenr) {
1745                 if (nearest)
1746                         return reconstruction->camnr - 1;
1747                 else
1748                         return -1;
1749         }
1750
1751         if (reconstruction->last_camera < reconstruction->camnr)
1752                 a = reconstruction->last_camera;
1753
1754         if (cameras[a].framenr >= framenr)
1755                 d = -1;
1756
1757         while (a >= 0 && a < reconstruction->camnr) {
1758                 int cfra = cameras[a].framenr;
1759
1760                 /* check if needed framenr was "skipped" -- no data for requested frame */
1761
1762                 if (d > 0 && cfra > framenr) {
1763                         /* interpolate with previous position */
1764                         if (nearest)
1765                                 return a - 1;
1766                         else
1767                                 break;
1768                 }
1769
1770                 if (d < 0 && cfra < framenr) {
1771                         /* interpolate with next position */
1772                         if (nearest)
1773                                 return a;
1774                         else
1775                                 break;
1776                 }
1777
1778                 if (cfra == framenr) {
1779                         reconstruction->last_camera = a;
1780
1781                         return a;
1782                 }
1783
1784                 a += d;
1785         }
1786
1787         return -1;
1788 }
1789
1790 static void reconstructed_camera_scale_set(MovieTrackingObject *object, float mat[4][4])
1791 {
1792         if ((object->flag & TRACKING_OBJECT_CAMERA) == 0) {
1793                 float smat[4][4];
1794
1795                 scale_m4_fl(smat, 1.0f / object->scale);
1796                 mul_m4_m4m4(mat, mat, smat);
1797         }
1798 }
1799
1800
1801 /* converts principal offset from center to offset of blender's camera */
1802 void BKE_tracking_camera_shift_get(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
1803 {
1804         /* indeed in both of cases it should be winx -- it's just how camera shift works for blender's camera */
1805         *shiftx = (0.5f * winx - tracking->camera.principal[0]) / winx;
1806         *shifty = (0.5f * winy - tracking->camera.principal[1]) / winx;
1807 }
1808
1809 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
1810 {
1811         float focal = tracking->camera.focal;
1812
1813         camera->sensor_x = tracking->camera.sensor_width;
1814         camera->sensor_fit = CAMERA_SENSOR_FIT_AUTO;
1815         camera->lens = focal * camera->sensor_x / width;
1816
1817         scene->r.xsch = width * tracking->camera.pixel_aspect;
1818         scene->r.ysch = height;
1819
1820         scene->r.xasp = 1.0f;
1821         scene->r.yasp = 1.0f;
1822
1823         BKE_tracking_camera_shift_get(tracking, width, height, &camera->shiftx, &camera->shifty);
1824 }
1825
1826 MovieReconstructedCamera *BKE_tracking_camera_get_reconstructed(MovieTracking *tracking,
1827                                                                 MovieTrackingObject *object, int framenr)
1828 {
1829         MovieTrackingReconstruction *reconstruction;
1830         int a;
1831
1832         reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
1833         a = reconstructed_camera_index_get(reconstruction, framenr, false);
1834
1835         if (a == -1)
1836                 return NULL;
1837
1838         return &reconstruction->cameras[a];
1839 }
1840
1841 void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking, MovieTrackingObject *object,
1842                                                        int framenr, float mat[4][4])
1843 {
1844         MovieTrackingReconstruction *reconstruction;
1845         MovieReconstructedCamera *cameras;
1846         int a;
1847
1848         reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
1849         cameras = reconstruction->cameras;
1850         a = reconstructed_camera_index_get(reconstruction, framenr, true);
1851
1852         if (a == -1) {
1853                 unit_m4(mat);
1854
1855                 return;
1856         }
1857
1858         if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) {
1859                 float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr);
1860
1861                 blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t);
1862         }
1863         else {
1864                 copy_m4_m4(mat, cameras[a].mat);
1865         }
1866
1867         reconstructed_camera_scale_set(object, mat);
1868 }
1869
1870 /*********************** Distortion/Undistortion *************************/
1871
1872 static void cameraIntrinscisOptionsFromTracking(libmv_CameraIntrinsicsOptions *camera_intrinsics_options,
1873                                                 MovieTracking *tracking, int calibration_width, int calibration_height)
1874 {
1875         MovieTrackingCamera *camera = &tracking->camera;
1876         float aspy = 1.0f / tracking->camera.pixel_aspect;
1877
1878         camera_intrinsics_options->focal_length = camera->focal;
1879
1880         camera_intrinsics_options->principal_point_x = camera->principal[0];
1881         camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
1882
1883         camera_intrinsics_options->k1 = camera->k1;
1884         camera_intrinsics_options->k2 = camera->k2;
1885         camera_intrinsics_options->k3 = camera->k3;
1886
1887         camera_intrinsics_options->image_width = calibration_width;
1888         camera_intrinsics_options->image_height = (int) (calibration_height * aspy);
1889 }
1890
1891 MovieDistortion *BKE_tracking_distortion_new(void)
1892 {
1893         MovieDistortion *distortion;
1894
1895         distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
1896
1897         distortion->intrinsics = libmv_cameraIntrinsicsNewEmpty();
1898
1899         return distortion;
1900 }
1901
1902 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking,
1903                                     int calibration_width, int calibration_height)
1904 {
1905         libmv_CameraIntrinsicsOptions camera_intrinsics_options;
1906
1907         cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking,
1908                                             calibration_width, calibration_height);
1909
1910         libmv_cameraIntrinsicsUpdate(&camera_intrinsics_options, distortion->intrinsics);
1911 }
1912
1913 void BKE_tracking_distortion_set_threads(MovieDistortion *distortion, int threads)
1914 {
1915         libmv_cameraIntrinsicsSetThreads(distortion->intrinsics, threads);
1916 }
1917
1918 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
1919 {
1920         MovieDistortion *new_distortion;
1921
1922         new_distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
1923
1924         new_distortion->intrinsics = libmv_cameraIntrinsicsCopy(distortion->intrinsics);
1925
1926         return new_distortion;
1927 }
1928
1929 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, ImBuf *ibuf,
1930                                     int calibration_width, int calibration_height, float overscan, bool undistort)
1931 {
1932         ImBuf *resibuf;
1933
1934         BKE_tracking_distortion_update(distortion, tracking, calibration_width, calibration_height);
1935
1936         resibuf = IMB_dupImBuf(ibuf);
1937
1938         if (ibuf->rect_float) {
1939                 if (undistort) {
1940                         libmv_cameraIntrinsicsUndistortFloat(distortion->intrinsics,
1941                                                              ibuf->rect_float, resibuf->rect_float,
1942                                                              ibuf->x, ibuf->y, overscan, ibuf->channels);
1943                 }
1944                 else {
1945                         libmv_cameraIntrinsicsDistortFloat(distortion->intrinsics,
1946                                                            ibuf->rect_float, resibuf->rect_float,
1947                                                            ibuf->x, ibuf->y, overscan, ibuf->channels);
1948                 }
1949
1950                 if (ibuf->rect)
1951                         imb_freerectImBuf(ibuf);
1952         }
1953         else {
1954                 if (undistort) {
1955                         libmv_cameraIntrinsicsUndistortByte(distortion->intrinsics,
1956                                                             (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
1957                                                             ibuf->x, ibuf->y, overscan, ibuf->channels);
1958                 }
1959                 else {
1960                         libmv_cameraIntrinsicsDistortByte(distortion->intrinsics,
1961                                                           (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect,
1962                                                           ibuf->x, ibuf->y, overscan, ibuf->channels);
1963                 }
1964         }
1965
1966         return resibuf;
1967 }
1968
1969 void BKE_tracking_distortion_free(MovieDistortion *distortion)
1970 {
1971         libmv_cameraIntrinsicsDestroy(distortion->intrinsics);
1972
1973         MEM_freeN(distortion);
1974 }
1975
1976 void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r_co[2])
1977 {
1978         MovieTrackingCamera *camera = &tracking->camera;
1979
1980         libmv_CameraIntrinsicsOptions camera_intrinsics_options;
1981         double x, y;
1982         float aspy = 1.0f / tracking->camera.pixel_aspect;
1983
1984         cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
1985
1986         /* normalize coords */
1987         x = (co[0] - camera->principal[0]) / camera->focal;
1988         y = (co[1] - camera->principal[1] * aspy) / camera->focal;
1989
1990         libmv_cameraIntrinsicsApply(&camera_intrinsics_options, x, y, &x, &y);
1991
1992         /* result is in image coords already */
1993         r_co[0] = x;
1994         r_co[1] = y;
1995 }
1996
1997 void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float r_co[2])
1998 {
1999         MovieTrackingCamera *camera = &tracking->camera;
2000
2001         libmv_CameraIntrinsicsOptions camera_intrinsics_options;
2002         double x = co[0], y = co[1];
2003         float aspy = 1.0f / tracking->camera.pixel_aspect;
2004
2005         cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
2006
2007         libmv_cameraIntrinsicsInvert(&camera_intrinsics_options, x, y, &x, &y);
2008
2009         r_co[0] = (float)x * camera->focal + camera->principal[0];
2010         r_co[1] = (float)y * camera->focal + camera->principal[1] * aspy;
2011 }
2012
2013 ImBuf *BKE_tracking_undistort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width,
2014                                     int calibration_height, float overscan)
2015 {
2016         MovieTrackingCamera *camera = &tracking->camera;
2017
2018         if (camera->intrinsics == NULL)
2019                 camera->intrinsics = BKE_tracking_distortion_new();
2020
2021         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width,
2022                                             calibration_height, overscan, true);
2023 }
2024
2025 ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width,
2026                                   int calibration_height, float overscan)
2027 {
2028         MovieTrackingCamera *camera = &tracking->camera;
2029
2030         if (camera->intrinsics == NULL)
2031                 camera->intrinsics = BKE_tracking_distortion_new();
2032
2033         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width,
2034                                             calibration_height, overscan, false);
2035 }
2036
2037 void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2])
2038 {
2039         int a;
2040         float pos[2], warped_pos[2];
2041         const int coord_delta = 5;
2042
2043         delta[0] = delta[1] = -FLT_MAX;
2044
2045         for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) {
2046                 if (a > rect->xmax)
2047                         a = rect->xmax;
2048
2049                 /* bottom edge */
2050                 pos[0] = a;
2051                 pos[1] = rect->ymin;
2052
2053                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
2054
2055                 delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
2056                 delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
2057
2058                 /* top edge */
2059                 pos[0] = a;
2060                 pos[1] = rect->ymax;
2061
2062                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
2063
2064                 delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
2065                 delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
2066
2067                 if (a >= rect->xmax)
2068                         break;
2069         }
2070
2071         for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) {
2072                 if (a > rect->ymax)
2073                         a = rect->ymax;
2074
2075                 /* left edge */
2076                 pos[0] = rect->xmin;
2077                 pos[1] = a;
2078
2079                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
2080
2081                 delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
2082                 delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
2083
2084                 /* right edge */
2085                 pos[0] = rect->xmax;
2086                 pos[1] = a;
2087
2088                 BKE_tracking_undistort_v2(tracking, pos, warped_pos);
2089
2090                 delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
2091                 delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
2092
2093                 if (a >= rect->ymax)
2094                         break;
2095         }
2096 }
2097
2098 /*********************** Image sampling *************************/
2099
2100 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, bool grayscale)
2101 {
2102         BKE_tracking_disable_channels(ibuf, track->flag & TRACK_DISABLE_RED,
2103                                       track->flag & TRACK_DISABLE_GREEN,
2104                                       track->flag & TRACK_DISABLE_BLUE, grayscale);
2105 }
2106
2107 ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf,
2108                                    MovieTrackingTrack *track, MovieTrackingMarker *marker,
2109                                    bool from_anchor, bool use_mask, int num_samples_x, int num_samples_y,
2110                                    float pos[2])
2111 {
2112         ImBuf *pattern_ibuf;
2113         double src_pixel_x[5], src_pixel_y[5];
2114         double warped_position_x, warped_position_y;
2115         float *mask = NULL;
2116
2117         if (num_samples_x <= 0 || num_samples_y <= 0)
2118                 return NULL;
2119
2120         pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat);
2121
2122         if (!search_ibuf->rect_float) {
2123                 IMB_float_from_rect(search_ibuf);
2124         }
2125
2126         get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y);
2127
2128         /* from_anchor means search buffer was obtained for an anchored position,
2129          * which means applying track offset rounded to pixel space (we could not
2130          * store search buffer with sub-pixel precision)
2131          *
2132          * in this case we need to alter coordinates a bit, to compensate rounded
2133          * fractional part of offset
2134          */
2135         if (from_anchor) {
2136                 int a;
2137
2138                 for (a = 0; a < 5; a++) {
2139                         src_pixel_x[a] += (double) ((track->offset[0] * frame_width) - ((int) (track->offset[0] * frame_width)));
2140                         src_pixel_y[a] += (double) ((track->offset[1] * frame_height) - ((int) (track->offset[1] * frame_height)));
2141
2142                         /* when offset is negative, rounding happens in opposite direction */
2143                         if (track->offset[0] < 0.0f)
2144                                 src_pixel_x[a] += 1.0;
2145                         if (track->offset[1] < 0.0f)
2146                                 src_pixel_y[a] += 1.0;
2147                 }
2148         }
2149
2150         if (use_mask) {
2151                 mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
2152         }
2153
2154         libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4,
2155                                 src_pixel_x, src_pixel_y, num_samples_x,
2156                                 num_samples_y, mask, pattern_ibuf->rect_float,
2157                                 &warped_position_x, &warped_position_y);
2158
2159         if (pos) {
2160                 pos[0] = warped_position_x;
2161                 pos[1] = warped_position_y;
2162         }
2163
2164         if (mask) {
2165                 MEM_freeN(mask);
2166         }
2167
2168         return pattern_ibuf;
2169 }
2170
2171 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
2172                                       bool anchored, bool disable_channels)
2173 {
2174         ImBuf *pattern_ibuf, *search_ibuf;
2175         float pat_min[2], pat_max[2];
2176         int num_samples_x, num_samples_y;
2177
2178         BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
2179
2180         num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x;
2181         num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y;
2182
2183         search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels);
2184
2185         if (search_ibuf) {
2186                 pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker,
2187                                                            anchored, false, num_samples_x, num_samples_y, NULL);
2188
2189                 IMB_freeImBuf(search_ibuf);
2190         }
2191         else {
2192                 pattern_ibuf = NULL;
2193         }
2194
2195         return pattern_ibuf;
2196 }
2197
2198 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
2199                                      bool anchored, bool disable_channels)
2200 {
2201         ImBuf *searchibuf;
2202         int x, y, w, h;
2203         float search_origin[2];
2204
2205         get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin);
2206
2207         x = search_origin[0];
2208         y = search_origin[1];
2209
2210         if (anchored) {
2211                 x += track->offset[0] * ibuf->x;
2212                 y += track->offset[1] * ibuf->y;
2213         }
2214
2215         w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x;
2216         h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y;
2217
2218         if (w <= 0 || h <= 0)
2219                 return NULL;
2220
2221         searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
2222
2223         IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h);
2224
2225         if (disable_channels) {
2226                 if ((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
2227                     (track->flag & TRACK_DISABLE_RED)       ||
2228                     (track->flag & TRACK_DISABLE_GREEN)     ||
2229                     (track->flag & TRACK_DISABLE_BLUE))
2230                 {
2231                         disable_imbuf_channels(searchibuf, track, true);
2232                 }
2233         }
2234
2235         return searchibuf;
2236 }
2237
2238 /* zap channels from the imbuf that are disabled by the user. this can lead to
2239  * better tracks sometimes. however, instead of simply zeroing the channels
2240  * out, do a partial grayscale conversion so the display is better.
2241  */
2242 void BKE_tracking_disable_channels(ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue,
2243                                    bool grayscale)
2244 {
2245         int x, y;
2246         float scale;
2247
2248         if (!disable_red && !disable_green && !disable_blue && !grayscale)
2249                 return;
2250
2251         /* if only some components are selected, it's important to rescale the result
2252          * appropriately so that e.g. if only blue is selected, it's not zeroed out.
2253          */
2254         scale = (disable_red   ? 0.0f : 0.2126f) +
2255                 (disable_green ? 0.0f : 0.7152f) +
2256                 (disable_blue  ? 0.0f : 0.0722f);
2257
2258         for (y = 0; y < ibuf->y; y++) {
2259                 for (x = 0; x < ibuf->x; x++) {
2260                         int pixel = ibuf->x * y + x;
2261
2262                         if (ibuf->rect_float) {
2263                                 float *rrgbf = ibuf->rect_float + pixel * 4;
2264                                 float r = disable_red   ? 0.0f : rrgbf[0];
2265                                 float g = disable_green ? 0.0f : rrgbf[1];
2266                                 float b = disable_blue  ? 0.0f : rrgbf[2];
2267
2268                                 if (grayscale) {
2269                                         float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
2270
2271                                         rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
2272                                 }
2273                                 else {
2274                                         rrgbf[0] = r;
2275                                         rrgbf[1] = g;
2276                                         rrgbf[2] = b;
2277                                 }
2278                         }
2279                         else {
2280                                 char *rrgb = (char *)ibuf->rect + pixel * 4;
2281                                 char r = disable_red   ? 0 : rrgb[0];
2282                                 char g = disable_green ? 0 : rrgb[1];
2283                                 char b = disable_blue  ? 0 : rrgb[2];
2284
2285                                 if (grayscale) {
2286                                         float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
2287
2288                                         rrgb[0] = rrgb[1] = rrgb[2] = gray;
2289                                 }
2290                                 else {
2291                                         rrgb[0] = r;
2292                                         rrgb[1] = g;
2293                                         rrgb[2] = b;
2294                                 }
2295                         }
2296                 }
2297         }
2298
2299         if (ibuf->rect_float)
2300                 ibuf->userflags |= IB_RECT_INVALID;
2301 }
2302
2303 /*********************** Tracks map *************************/
2304
2305 typedef struct TracksMap {
2306         char object_name[MAX_NAME];
2307         bool is_camera;
2308
2309         int num_tracks;
2310         int customdata_size;
2311
2312         char *customdata;
2313         MovieTrackingTrack *tracks;
2314
2315         GHash *hash;
2316
2317         int ptr;
2318 } TracksMap;
2319
2320 static TracksMap *tracks_map_new(const char *object_name, bool is_camera, int num_tracks, int customdata_size)
2321 {
2322         TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap");
2323
2324         BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
2325         map->is_camera = is_camera;
2326
2327         map->num_tracks = num_tracks;
2328         map->customdata_size = customdata_size;
2329
2330         map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks");
2331
2332         if (customdata_size)
2333                 map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata");
2334
2335         map->hash = BLI_ghash_ptr_new("TracksMap hash");
2336
2337         return map;
2338 }
2339
2340 static int tracks_map_get_size(TracksMap *map)
2341 {
2342         return map->num_tracks;
2343 }
2344
2345 static void tracks_map_get_indexed_element(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
2346 {
2347         *track = &map->tracks[index];
2348
2349         if (map->customdata)
2350                 *customdata = &map->customdata[index * map->customdata_size];
2351 }
2352
2353 static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
2354 {
2355         MovieTrackingTrack new_track = *track;
2356
2357         new_track.markers = MEM_dupallocN(new_track.markers);
2358
2359         map->tracks[map->ptr] = new_track;
2360
2361         if (customdata)
2362                 memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size);
2363
2364         BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
2365
2366         map->ptr++;
2367 }
2368
2369 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
2370 {
2371         MovieTrackingTrack *track;
2372         ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL};
2373         ListBase *old_tracks;
2374         int a;
2375
2376         if (map->is_camera) {
2377                 old_tracks = &tracking->tracks;
2378         }
2379         else {
2380                 MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name);
2381
2382                 if (!object) {
2383                         /* object was deleted by user, create new one */
2384                         object = BKE_tracking_object_add(tracking, map->object_name);
2385                 }
2386
2387                 old_tracks = &object->tracks;
2388         }
2389
2390         /* duplicate currently operating tracks to temporary list.
2391          * this is needed to keep names in unique state and it's faster to change names
2392          * of currently operating tracks (if needed)
2393          */
2394         for (a = 0; a < map->num_tracks; a++) {
2395                 MovieTrackingTrack *old_track;
2396                 bool mapped_to_old = false;
2397
2398                 track = &map->tracks[a];
2399
2400                 /* find original of operating track in list of previously displayed tracks */
2401                 old_track = BLI_ghash_lookup(map->hash, track);
2402                 if (old_track) {
2403                         if (BLI_findindex(old_tracks, old_track) != -1) {
2404                                 BLI_remlink(old_tracks, old_track);
2405
2406                                 /* Copy flags like selection back to the track map. */
2407                                 track->flag = old_track->flag;
2408                                 track->pat_flag = old_track->pat_flag;
2409                                 track->search_flag = old_track->search_flag;
2410
2411                                 /* Copy all the rest settings back from the map to the actual tracks. */
2412                                 MEM_freeN(old_track->markers);
2413                                 *old_track = *track;
2414                                 old_track->markers = MEM_dupallocN(old_track->markers);
2415
2416                                 BLI_addtail(&tracks, old_track);
2417
2418                                 mapped_to_old = true;
2419                         }
2420                 }
2421
2422                 if (mapped_to_old == false) {
2423                         MovieTrackingTrack *new_track = tracking_track_duplicate(track);
2424
2425                         /* Update old-new track mapping */
2426                         BLI_ghash_remove(map->hash, track, NULL, NULL);
2427                         BLI_ghash_insert(map->hash, track, new_track);
2428
2429                         BLI_addtail(&tracks, new_track);
2430                 }
2431         }
2432
2433         /* move all tracks, which aren't operating */
2434         track = old_tracks->first;
2435         while (track) {
2436                 MovieTrackingTrack *next = track->next;
2437                 BLI_addtail(&new_tracks, track);
2438                 track = next;
2439         }
2440
2441         /* now move all tracks which are currently operating and keep their names unique */
2442         track = tracks.first;
2443         while (track) {
2444                 MovieTrackingTrack *next = track->next;
2445
2446                 BLI_remlink(&tracks, track);
2447
2448                 track->next = track->prev = NULL;
2449                 BLI_addtail(&new_tracks, track);
2450
2451                 BLI_uniquename(&new_tracks, track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.',
2452                                offsetof(MovieTrackingTrack, name), sizeof(track->name));
2453
2454                 track = next;
2455         }
2456
2457         *old_tracks = new_tracks;
2458 }
2459
2460 static void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata))
2461 {
2462         int i = 0;
2463
2464         BLI_ghash_free(map->hash, NULL, NULL);
2465
2466         for (i = 0; i < map->num_tracks; i++) {
2467                 if (map->customdata && customdata_free)
2468                         customdata_free(&map->customdata[i * map->customdata_size]);
2469
2470                 BKE_tracking_track_free(&map->tracks[i]);
2471         }
2472
2473         if (map->customdata)
2474                 MEM_freeN(map->customdata);
2475
2476         MEM_freeN(map->tracks);
2477         MEM_freeN(map);
2478 }
2479
2480 /*********************** 2D tracking *************************/
2481
2482 typedef struct TrackContext {
2483         /* the reference marker and cutout search area */
2484         MovieTrackingMarker reference_marker;
2485
2486         /* keyframed patch. This is the search area */
2487         float *search_area;
2488         int search_area_height;
2489         int search_area_width;
2490         int framenr;
2491
2492         float *mask;
2493 } TrackContext;
2494
2495 typedef struct MovieTrackingContext {
2496         MovieClipUser user;
2497         MovieClip *clip;
2498         int clip_flag;
2499
2500         int frames, first_frame;
2501         bool first_time;
2502
2503         MovieTrackingSettings settings;
2504         TracksMap *tracks_map;
2505
2506         bool backwards, sequence;
2507         int sync_frame;
2508 } MovieTrackingContext;
2509
2510 static void track_context_free(void *customdata)
2511 {
2512         TrackContext *track_context = (TrackContext *)customdata;
2513
2514         if (track_context->search_area)
2515                 MEM_freeN(track_context->search_area);
2516
2517         if (track_context->mask)
2518                 MEM_freeN(track_context->mask);
2519 }
2520
2521 /* Create context for motion 2D tracking, copies all data needed
2522  * for thread-safe tracking, allowing clip modifications during
2523  * tracking.
2524  */
2525 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence)
2526 {
2527         MovieTrackingContext *context = MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
2528         MovieTracking *tracking = &clip->tracking;
2529         MovieTrackingSettings *settings = &tracking->settings;
2530         ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
2531         MovieTrackingTrack *track;
2532         MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
2533         int num_tracks = 0;
2534
2535         context->clip = clip;
2536         context->settings = *settings;
2537         context->backwards = backwards;
2538         context->sync_frame = user->framenr;
2539         context->first_time = true;
2540         context->first_frame = user->framenr;
2541         context->sequence = sequence;
2542
2543         /* count */
2544         track = tracksbase->first;
2545         while (track) {
2546                 if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
2547                         int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
2548                         MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
2549
2550                         if ((marker->flag & MARKER_DISABLED) == 0)
2551                                 num_tracks++;
2552                 }
2553
2554                 track = track->next;
2555         }
2556
2557         /* create tracking contextx for all tracks which would be tracked */
2558         if (num_tracks) {
2559                 int width, height;
2560
2561                 context->tracks_map = tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
2562                                                      num_tracks, sizeof(TrackContext));
2563
2564                 BKE_movieclip_get_size(clip, user, &width, &height);
2565
2566                 /* create tracking data */
2567                 track = tracksbase->first;
2568                 while (track) {
2569                         if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) {
2570                                 int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
2571                                 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
2572
2573                                 if ((marker->flag & MARKER_DISABLED) == 0) {
2574                                         TrackContext track_context;
2575                                         memset(&track_context, 0, sizeof(TrackContext));
2576                                         tracks_map_insert(context->tracks_map, track, &track_context);
2577                                 }
2578                         }
2579
2580                         track = track->next;
2581                 }
2582         }
2583
2584         /* store needed clip flags passing to get_buffer functions
2585          * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip
2586          *   only in case Proxy/Timecode flag is set, so store this flag to use
2587          *   timecodes properly but reset render size to SIZE_FULL so correct resolution
2588          *   would be used for images
2589          * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might
2590          *   be stored in a different location
2591          * ignore all the rest possible flags for now
2592          */
2593         context->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
2594
2595         context->user = *user;
2596         context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
2597         context->user.render_flag = 0;
2598
2599         if (!sequence)
2600                 BLI_begin_threaded_malloc();
2601
2602         return context;
2603 }
2604
2605 /* Free context used for tracking. */
2606 void BKE_tracking_context_free(MovieTrackingContext *context)
2607 {
2608         if (!context->sequence)
2609                 BLI_end_threaded_malloc();
2610
2611         tracks_map_free(context->tracks_map, track_context_free);
2612
2613         MEM_freeN(context);
2614 }
2615
2616 /* Synchronize tracks between clip editor and tracking context,
2617  * by merging them together so all new created tracks and tracked
2618  * ones presents in the movie clip.
2619  */
2620 void BKE_tracking_context_sync(MovieTrackingContext *context)
2621 {
2622         MovieTracking *tracking = &context->clip->tracking;
2623         int newframe;
2624
2625         tracks_map_merge(context->tracks_map, tracking);
2626
2627         if (context->backwards)
2628                 newframe = context->user.framenr + 1;
2629         else
2630                 newframe = context->user.framenr - 1;
2631
2632         context->sync_frame = newframe;
2633
2634         BKE_tracking_dopesheet_tag_update(tracking);
2635 }
2636
2637 /* Synchronize clip user's frame number with a frame number from tracking context,
2638  * used to update current frame displayed in the clip editor while tracking.
2639  */
2640 void BKE_tracking_context_sync_user(const MovieTrackingContext *context, MovieClipUser *user)
2641 {
2642         user->framenr = context->sync_frame;
2643 }
2644
2645 /* **** utility functions for tracking **** */
2646
2647 /* convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */
2648 static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels,
2649                                float weight_red, float weight_green, float weight_blue)
2650 {
2651         int i;
2652
2653         for (i = 0; i < num_pixels; i++) {
2654                 const float *pixel = rgba + 4 * i;
2655
2656                 gray[i] = weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2];
2657         }
2658 }
2659
2660 static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int num_pixels,
2661                                      float weight_red, float weight_green, float weight_blue)
2662 {
2663         int i;
2664
2665         for (i = 0; i < num_pixels; i++) {
2666                 const unsigned char *pixel = rgba + i * 4;
2667
2668                 gray[i] = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f;
2669         }
2670 }
2671
2672 /* Get grayscale float search buffer for given marker and frame. */
2673 static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
2674                                         int *width_r, int *height_r)
2675 {
2676         ImBuf *searchibuf;
2677         float *gray_pixels;
2678         int width, height;
2679
2680         searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, false, true);
2681
2682         if (!searchibuf) {
2683                 *width_r = 0;
2684                 *height_r = 0;
2685                 return NULL;
2686         }
2687
2688         width = searchibuf->x;
2689         height = searchibuf->y;
2690
2691         gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf");
2692
2693         if (searchibuf->rect_float) {
2694                 float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height,
2695                                    0.2126f, 0.7152f, 0.0722f);
2696         }
2697         else {
2698                 uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height,
2699                                          0.2126f, 0.7152f, 0.0722f);
2700         }
2701
2702         IMB_freeImBuf(searchibuf);
2703
2704         *width_r = width;
2705         *height_r = height;
2706
2707         return gray_pixels;
2708 }
2709
2710 /* Get image boffer for a given frame
2711  *
2712  * Frame is in clip space.
2713  */
2714 static ImBuf *tracking_context_get_frame_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag, int framenr)
2715 {
2716         ImBuf *ibuf;
2717         MovieClipUser new_user = *user;
2718
2719         new_user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr);
2720
2721         ibuf = BKE_movieclip_get_ibuf_flag(clip, &new_user, clip_flag, MOVIECLIP_CACHE_SKIP);
2722
2723         return ibuf;
2724 }
2725
2726 /* Get previous keyframed marker. */
2727 static MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingTrack *track,
2728                                                                   int curfra, bool backwards)
2729 {
2730         MovieTrackingMarker *marker_keyed = NULL;
2731         MovieTrackingMarker *marker_keyed_fallback = NULL;
2732         int a = BKE_tracking_marker_get(track, curfra) - track->markers;
2733
2734         while (a >= 0 && a < track->markersnr) {
2735                 int next = backwards ? a + 1 : a - 1;
2736                 bool is_keyframed = false;
2737                 MovieTrackingMarker *cur_marker = &track->markers[a];
2738                 MovieTrackingMarker *next_marker = NULL;
2739
2740                 if (next >= 0 && next < track->markersnr)
2741                         next_marker = &track->markers[next];
2742
2743                 if ((cur_marker->flag & MARKER_DISABLED) == 0) {
2744                         /* If it'll happen so we didn't find a real keyframe marker,
2745                          * fallback to the first marker in current tracked segment
2746                          * as a keyframe.
2747                          */
2748                         if (next_marker && next_marker->flag & MARKER_DISABLED) {
2749                                 if (marker_keyed_fallback == NULL)
2750                                         marker_keyed_fallback = cur_marker;
2751                         }
2752
2753                         is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0;
2754                 }
2755
2756                 if (is_keyframed) {
2757                         marker_keyed = cur_marker;
2758
2759                         break;
2760                 }
2761
2762                 a = next;
2763         }
2764
2765         if (marker_keyed == NULL)
2766                 marker_keyed = marker_keyed_fallback;
2767
2768         return marker_keyed;
2769 }
2770
2771 /* Get image buffer for previous marker's keyframe. */
2772 static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag,
2773                                                   MovieTrackingTrack *track, int curfra, bool backwards,
2774                                                   MovieTrackingMarker **marker_keyed_r)
2775 {
2776         MovieTrackingMarker *marker_keyed;
2777         int keyed_framenr;
2778
2779         marker_keyed = tracking_context_get_keyframed_marker(track, curfra, backwards);
2780         if (marker_keyed == NULL) {
2781                 return NULL;
2782         }
2783
2784         keyed_framenr = marker_keyed->framenr;
2785
2786         *marker_keyed_r = marker_keyed;
2787
2788         return tracking_context_get_frame_ibuf(clip, user, clip_flag, keyed_framenr);
2789 }
2790
2791 /* Get image buffer which si used as referece for track. */
2792 static ImBuf *tracking_context_get_reference_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag,
2793                                                   MovieTrackingTrack *track, int curfra, bool backwards,
2794                                                   MovieTrackingMarker **reference_marker)
2795 {
2796         ImBuf *ibuf = NULL;
2797
2798         if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
2799                 ibuf = tracking_context_get_keyframed_ibuf(clip, user, clip_flag, track, curfra, backwards, reference_marker);
2800         }
2801         else {
2802                 ibuf = tracking_context_get_frame_ibuf(clip, user, clip_flag, curfra);
2803
2804                 /* use current marker as keyframed position */
2805                 *reference_marker = BKE_tracking_marker_get(track, curfra);
2806         }
2807
2808         return ibuf;
2809 }
2810
2811 /* Update track's reference patch (patch from which track is tracking from)
2812  *
2813  * Returns false if reference image buffer failed to load.
2814  */
2815 static bool track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context,
2816                                            MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra,
2817                                            int frame_width, int frame_height)
2818 {
2819         MovieTrackingMarker *reference_marker = NULL;
2820         ImBuf *reference_ibuf = NULL;
2821         int width, height;
2822
2823         /* calculate patch for keyframed position */
2824         reference_ibuf = tracking_context_get_reference_ibuf(context->clip, &context->user, context->clip_flag,
2825                                                              track, curfra, context->backwards, &reference_marker);
2826
2827         if (!reference_ibuf)
2828                 return false;
2829
2830         track_context->reference_marker = *reference_marker;
2831
2832         if (track_context->search_area) {
2833                 MEM_freeN(track_context->search_area);
2834         }
2835
2836         track_context->search_area = track_get_search_floatbuf(reference_ibuf, track, reference_marker, &width, &height);
2837         track_context->search_area_height = height;
2838         track_context->search_area_width = width;
2839
2840         if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) {
2841                 if (track_context->mask)
2842                         MEM_freeN(track_context->mask);
2843
2844                 track_context->mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
2845         }
2846
2847         IMB_freeImBuf(reference_ibuf);
2848
2849         return true;
2850 }
2851
2852 /* Fill in libmv tracker options structure with settings need to be used to perform track. */
2853 static void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
2854                                        libmv_TrackRegionOptions *options)
2855 {
2856         options->motion_model = track->motion_model;
2857
2858         options->use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0);
2859
2860         options->use_normalization = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0);
2861
2862         options->num_iterations = 50;
2863         options->minimum_correlation = track->minimum_correlation;
2864         options->sigma = 0.9;
2865
2866         if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0)
2867                 options->image1_mask = mask;
2868         else
2869                 options->image1_mask = NULL;
2870 }
2871
2872 /* returns false if marker crossed margin area from frame bounds */
2873 static bool tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker,
2874                                          int frame_width, int frame_height)
2875 {
2876         float pat_min[2], pat_max[2];
2877         float margin_left, margin_top, margin_right, margin_bottom;
2878         float normalized_track_margin[2];
2879
2880         /* margin from frame boundaries */
2881         BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
2882
2883         normalized_track_margin[0] = (float)track->margin / frame_width;
2884         normalized_track_margin[1] = (float)track->margin / frame_height;
2885
2886         margin_left   = max_ff(-pat_min[0], normalized_track_margin[0]);
2887         margin_top    = max_ff( pat_max[1], normalized_track_margin[1]);
2888         margin_right  = max_ff( pat_max[0], normalized_track_margin[0]);
2889         margin_bottom = max_ff(-pat_min[1], normalized_track_margin[1]);
2890
2891         /* do not track markers which are too close to boundary */
2892         if (marker->pos[0] < margin_left || marker->pos[0] > 1.0f - margin_right ||
2893             marker->pos[1] < margin_bottom || marker->pos[1] > 1.0f - margin_top)
2894         {
2895                 return false;
2896         }
2897
2898         return true;
2899 }
2900
2901 /* Scale search area of marker based on scale changes of pattern area,
2902  *
2903  * TODO(sergey): currently based on pattern bounding box scale change,
2904  *               smarter approach here is welcome.
2905  */
2906 static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker)
2907 {
2908         float old_pat_min[2], old_pat_max[2];
2909         float new_pat_min[2], new_pat_max[2];
2910         float scale_x, scale_y;
2911
2912         BKE_tracking_marker_pattern_minmax(old_marker, old_pat_min, old_pat_max);
2913         BKE_tracking_marker_pattern_minmax(new_marker, new_pat_min, new_pat_max);
2914
2915         scale_x = (new_pat_max[0] - new_pat_min[0]) / (old_pat_max[0] - old_pat_min[0]);
2916         scale_y = (new_pat_max[1] - new_pat_min[1]) / (old_pat_max[1] - old_pat_min[1]);
2917
2918         new_marker->search_min[0] *= scale_x;
2919         new_marker->search_min[1] *= scale_y;
2920
2921         new_marker->search_max[0] *= scale_x;
2922         new_marker->search_max[1] *= scale_y;
2923 }
2924
2925 /* Insert new marker which was tracked from old_marker to a new image,
2926  * will also ensure tracked segment is surrounded by disabled markers.
2927  */
2928 static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track,
2929                                        const MovieTrackingMarker *old_marker, int curfra, bool tracked,
2930                                        int frame_width, int frame_height,
2931                                        double dst_pixel_x[5], double dst_pixel_y[5])
2932 {
2933         MovieTrackingMarker new_marker;
2934         int frame_delta = context->backwards ? -1 : 1;
2935         int nextfra = curfra + frame_delta;
2936
2937         new_marker = *old_marker;
2938
2939         if (tracked) {
2940                 set_marker_coords_from_tracking(frame_width, frame_height, &new_marker, dst_pixel_x, dst_pixel_y);
2941                 new_marker.flag |= MARKER_TRACKED;
2942                 new_marker.framenr = nextfra;
2943
2944                 tracking_scale_marker_search(old_marker, &new_marker);
2945
2946                 if (context->first_time) {
2947                         /* check if there's no keyframe/tracked markers before tracking marker.
2948                          * if so -- create disabled marker before currently tracking "segment"
2949                          */
2950
2951                         tracking_marker_insert_disabled(track, old_marker, !context->backwards, false);
2952                 }
2953
2954                 /* insert currently tracked marker */
2955                 BKE_tracking_marker_insert(track, &new_marker);
2956
2957                 /* make currently tracked segment be finished with disabled marker */
2958                 tracking_marker_insert_disabled(track, &new_marker, context->backwards, false);
2959         }
2960         else {
2961                 new_marker.framenr = nextfra;
2962                 new_marker.flag |= MARKER_DISABLED;
2963
2964                 BKE_tracking_marker_insert(track, &new_marker);
2965         }
2966 }
2967
2968 /* Peform tracking from a reference_marker to destination_ibuf.
2969  * Uses marker as an initial position guess.
2970  *
2971  * Returns truth if tracker returned success, puts result
2972  * to dst_pixel_x and dst_pixel_y.
2973  */
2974 static bool configure_and_run_tracker(ImBuf *destination_ibuf, MovieTrackingTrack *track,
2975                                       MovieTrackingMarker *reference_marker, MovieTrackingMarker *marker,
2976                                       float *reference_search_area, int reference_search_area_width,
2977                                       int reference_search_area_height, float *mask,
2978                                       double dst_pixel_x[5], double dst_pixel_y[5])
2979 {
2980         /* To convert to the x/y split array format for libmv. */
2981         double src_pixel_x[5], src_pixel_y[5];
2982
2983         /* Settings for the tracker */
2984         libmv_TrackRegionOptions options = {0};
2985         libmv_TrackRegionResult result;
2986
2987         float *patch_new;
2988
2989         int new_search_area_width, new_search_area_height;
2990         int frame_width, frame_height;
2991
2992         bool tracked;
2993
2994         frame_width = destination_ibuf->x;
2995         frame_height = destination_ibuf->y;
2996
2997         /* for now track to the same search area dimension as marker has got for current frame
2998          * will make all tracked markers in currently tracked segment have the same search area
2999          * size, but it's quite close to what is actually needed
3000          */
3001         patch_new = track_get_search_floatbuf(destination_ibuf, track, marker,
3002                                               &new_search_area_width, &new_search_area_height);
3003
3004         /* configure the tracker */
3005         tracking_configure_tracker(track, mask, &options);
3006
3007         /* convert the marker corners and center into pixel coordinates in the search/destination images. */
3008         get_marker_coords_for_tracking(frame_width, frame_height, reference_marker, src_pixel_x, src_pixel_y);
3009         get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y);
3010
3011         if (patch_new == NULL || reference_search_area == NULL)
3012                 return false;
3013
3014         /* run the tracker! */
3015         tracked = libmv_trackRegion(&options,
3016                                     reference_search_area,
3017                                     reference_search_area_width,
3018                                     reference_search_area_height,
3019                                     patch_new,
3020                                     new_search_area_width,
3021                                     new_search_area_height,
3022                                     src_pixel_x, src_pixel_y,
3023                                     &result,
3024                                     dst_pixel_x, dst_pixel_y);
3025         MEM_freeN(patch_new);
3026
3027         return tracked;
3028 }
3029
3030 /* Track all the tracks from context one more frame,
3031  * returns FALSe if nothing was tracked.
3032  */
3033 bool BKE_tracking_context_step(MovieTrackingContext *context)
3034 {
3035         ImBuf *destination_ibuf;
3036         int frame_delta = context->backwards ? -1 : 1;
3037         int curfra =  BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr);
3038         int a, map_size;
3039         bool ok = false;
3040
3041         int frame_width, frame_height;
3042
3043         map_size = tracks_map_get_size(context->tracks_map);
3044
3045         /* Nothing to track, avoid unneeded frames reading to save time and memory. */
3046         if (!map_size)
3047                 return false;
3048
3049         /* Get an image buffer for frame we're tracking to. */
3050         context->user.framenr += frame_delta;
3051
3052         destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user,
3053                                                        context->clip_flag, MOVIECLIP_CACHE_SKIP);
3054         if (!destination_ibuf)
3055                 return false;
3056
3057         frame_width = destination_ibuf->x;
3058         frame_height = destination_ibuf->y;
3059
3060         #pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size > 1)
3061         for (a = 0; a < map_size; a++) {
3062                 TrackContext *track_context = NULL;
3063                 MovieTrackingTrack *track;
3064                 MovieTrackingMarker *marker;
3065
3066                 tracks_map_get_indexed_element(context->tracks_map, a, &track, (void **)&track_context);
3067
3068                 marker = BKE_tracking_marker_get_exact(track, curfra);
3069
3070                 if (marker && (marker->flag & MARKER_DISABLED) == 0) {
3071                         bool tracked = false, need_readjust;
3072                         double dst_pixel_x[5], dst_pixel_y[5];
3073
3074                         if (track->pattern_match == TRACK_MATCH_KEYFRAME)
3075                                 need_readjust = context->first_time;
3076                         else
3077                                 need_readjust = true;
3078
3079                         /* do not track markers which are too close to boundary */
3080                         if (tracking_check_marker_margin(track, marker, frame_width, frame_height)) {
3081                                 if (need_readjust) {
3082                                         if (track_context_update_reference(context, track_context, track, marker,
3083                                                                            curfra, frame_width, frame_height) == false)
3084                                         {
3085                                                 /* happens when reference frame fails to be loaded */
3086                                                 continue;
3087                                         }
3088                                 }
3089
3090                                 tracked = configure_and_run_tracker(destination_ibuf, track,
3091                                                                     &track_context->reference_marker, marker,
3092                                                                     track_context->search_area,
3093                                                                     track_context->search_area_width,
3094                                                                     track_context->search_area_height,
3095                                                                     track_context->mask,
3096                                                                     dst_pixel_x, dst_pixel_y);
3097                         }
3098
3099                         #pragma omp critical
3100                         {
3101                                 tracking_insert_new_marker(context, track, marker, curfra, tracked,
3102                                                            frame_width, frame_height, dst_pixel_x, dst_pixel_y);
3103                         }
3104
3105                         ok = true;
3106                 }
3107         }
3108
3109         IMB_freeImBuf(destination_ibuf);
3110
3111         context->first_time = false;
3112         context->frames++;
3113
3114         return ok;
3115 }
3116
3117 void BKE_tracking_context_finish(MovieTrackingContext *context)
3118 {
3119         MovieClip *clip = context->clip;
3120         ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
3121         MovieTrackingPlaneTrack *plane_track;
3122         int map_size = tracks_map_get_size(context->tracks_map);
3123
3124         for (plane_track = plane_tracks_base->first;
3125              plane_track;
3126              plane_track = plane_track->next)
3127         {
3128                 if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
3129                         int i;
3130                         for (i = 0; i < map_size; i++) {
3131                                 TrackContext *track_context = NULL;
3132                                 MovieTrackingTrack *track, *old_track;
3133                                 bool do_update = false;
3134                                 int j;
3135
3136                                 tracks_map_get_indexed_element(context->tracks_map, i, &track, (void **)&track_context);
3137
3138                                 old_track = BLI_ghash_lookup(context->tracks_map->hash, track);
3139                                 for (j = 0; j < plane_track->point_tracksnr; j++) {
3140                                         if (plane_track->point_tracks[j] == old_track) {
3141                                                 do_update = true;
3142                                                 break;
3143                                         }
3144                                 }
3145
3146                                 if (do_update) {
3147                                         BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame);
3148                                         break;
3149                                 }
3150                         }
3151                 }
3152         }
3153 }
3154
3155 /* Refine marker's position using previously known keyframe.
3156  * Direction of searching for a keyframe depends on backwards flag,
3157  * which means if backwards is false, previous keyframe will be as
3158  * reference.
3159  */
3160 void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker, bool backwards)
3161 {
3162         MovieTrackingMarker *reference_marker = NULL;
3163         ImBuf *reference_ibuf, *destination_ibuf;
3164         float *search_area, *mask = NULL;
3165         int frame_width, frame_height;
3166         int search_area_height, search_area_width;
3167         int clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS;
3168         int reference_framenr;
3169         MovieClipUser user = {0};
3170         double dst_pixel_x[5], dst_pixel_y[5];
3171         bool tracked;
3172
3173         /* Construct a temporary clip used, used to acquire image buffers. */
3174         user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
3175
3176         BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
3177
3178         /* Get an image buffer for reference frame, also gets reference marker.
3179          *
3180          * Usually tracking_context_get_reference_ibuf will return current frame
3181          * if marker is keyframed, which is correct for normal tracking. But here
3182          * we'll want to have next/previous frame in such cases. So let's use small
3183          * magic with original frame number used to get reference frame for.
3184          */
3185         reference_framenr = backwards ? marker->framenr + 1 : marker->framenr - 1;
3186         reference_ibuf = tracking_context_get_reference_ibuf(clip, &user, clip_flag, track, reference_framenr,
3187                                                              backwards, &reference_marker);
3188         if (reference_ibuf == NULL) {
3189                 return;
3190         }
3191
3192         /* Could not refine with self. */
3193         if (reference_marker == marker) {
3194                 return;
3195         }
3196
3197         /* Destination image buffer has got frame number corresponding to refining marker. */
3198         destination_ibuf = BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag, MOVIECLIP_CACHE_SKIP);
3199         if (destination_ibuf == NULL) {
3200                 IMB_freeImBuf(reference_ibuf);
3201                 return;
3202         }
3203
3204         /* Get search area from reference image. */
3205         search_area = track_get_search_floatbuf(reference_ibuf, track, reference_marker,
3206                                                 &search_area_width, &search_area_height);
3207
3208         /* If needed, compute track's mask. */
3209         if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0)
3210                 mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
3211
3212         /* Run the tracker from reference frame to current one. */
3213         tracked = configure_and_run_tracker(destination_ibuf, track, reference_marker, marker,
3214                                             search_area, search_area_width, search_area_height,
3215                                             mask, dst_pixel_x, dst_pixel_y);
3216
3217         /* Refine current marker's position if track was successful. */
3218         if (tracked) {
3219                 set_marker_coords_from_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y);
3220                 marker->flag |= MARKER_TRACKED;
3221         }
3222
3223         /* Free memory used for refining */
3224         MEM_freeN(search_area);
3225         if (mask)
3226                 MEM_freeN(mask);
3227         IMB_freeImBuf(reference_ibuf);
3228         IMB_freeImBuf(destination_ibuf);
3229 }
3230
3231 /*********************** Plane tracking *************************/
3232
3233 typedef double Vec2[2];
3234
3235 static int point_markers_correspondences_on_both_image(MovieTrackingPlaneTrack *plane_track, int frame1, int frame2,
3236                                                        Vec2 **x1_r, Vec2 **x2_r)
3237 {
3238         int i, correspondence_index;
3239         Vec2 *x1, *x2;
3240
3241         *x1_r = x1 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x1");
3242         *x2_r = x2 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x2");
3243
3244         for (i = 0, correspondence_index = 0; i < plane_track->point_tracksnr; i++) {
3245                 MovieTrackingTrack *point_track = plane_track->point_tracks[i];
3246                 MovieTrackingMarker *point_marker1, *point_marker2;
3247
3248                 point_marker1 = BKE_tracking_marker_get_exact(point_track, frame1);
3249                 point_marker2 = BKE_tracking_marker_get_exact(point_track, frame2);
3250
3251                 if (point_marker1 != NULL && point_marker2 != NULL) {
3252                         /* Here conversion from float to double happens. */
3253                         x1[correspondence_index][0] = point_marker1->pos[0];
3254                         x1[correspondence_index][1] = point_marker1->pos[1];
3255
3256                         x2[correspondence_index][0] = point_marker2->pos[0];
3257                         x2[correspondence_index][1] = point_marker2->pos[1];
3258
3259                         correspondence_index++;
3260                 }
3261         }
3262
3263         return correspondence_index;
3264 }
3265
3266 /* NOTE: frame number should be in clip space, not scene space */
3267 static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track, int start_frame,
3268                                              int direction, bool retrack)
3269 {
3270         MovieTrackingPlaneMarker *start_plane_marker = BKE_tracking_plane_marker_get(plane_track, start_frame);
3271         MovieTrackingPlaneMarker *keyframe_plane_marker = NULL;
3272         MovieTrackingPlaneMarker new_plane_marker;
3273         int current_frame, frame_delta = direction > 0 ? 1 : -1;
3274
3275         if (plane_track->flag & PLANE_TRACK_AUTOKEY) {
3276                 /* Find a keyframe in given direction. */
3277                 for (current_frame = start_frame; ; current_frame += frame_delta) {
3278                         MovieTrackingPlaneMarker *next_plane_marker =
3279                                 BKE_tracking_plane_marker_get_exact(plane_track, current_frame + frame_delta);
3280
3281                         if (next_plane_marker == NULL) {
3282           &