Various fixes for camera tracking stuff
[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  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenkernel/intern/tracking.c
28  *  \ingroup bke
29  */
30
31 #include <stddef.h>
32 #include <limits.h>
33 #include <math.h>
34 #include <memory.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_gpencil_types.h"
39 #include "DNA_camera_types.h"
40 #include "DNA_movieclip_types.h"
41 #include "DNA_object_types.h"   /* SELECT */
42 #include "DNA_scene_types.h"
43
44 #include "BLI_utildefines.h"
45 #include "BLI_math.h"
46 #include "BLI_math_base.h"
47 #include "BLI_listbase.h"
48 #include "BLI_ghash.h"
49 #include "BLI_path_util.h"
50 #include "BLI_string.h"
51 #include "BLI_threads.h"
52
53 #include "BKE_global.h"
54 #include "BKE_tracking.h"
55 #include "BKE_movieclip.h"
56 #include "BKE_object.h"
57 #include "BKE_scene.h"
58 #include "BKE_main.h"   // XXX: ...
59
60 #include "IMB_imbuf_types.h"
61 #include "IMB_imbuf.h"
62
63 #ifdef WITH_LIBMV
64 #  include "libmv-capi.h"
65 #else
66 struct libmv_Features;
67 #endif
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 void BKE_tracking_init_settings(MovieTracking *tracking)
80 {
81         tracking->camera.sensor_width= 35.0f;
82         tracking->camera.pixel_aspect= 1.0f;
83         tracking->camera.units= CAMERA_UNITS_MM;
84
85         tracking->settings.default_tracker= TRACKER_HYBRID;
86         tracking->settings.default_minimum_correlation= 0.75;
87         tracking->settings.default_pattern_size= 11;
88         tracking->settings.default_search_size= 51;
89         tracking->settings.default_pyramid_levels= 2;
90         tracking->settings.keyframe1= 1;
91         tracking->settings.keyframe2= 30;
92         tracking->settings.dist= 1;
93         tracking->settings.object_distance= 1;
94
95         tracking->stabilization.scaleinf= 1.0f;
96         tracking->stabilization.locinf= 1.0f;
97         tracking->stabilization.rotinf= 1.0f;
98         tracking->stabilization.maxscale= 2.0f;
99
100         BKE_tracking_new_object(tracking, "Camera");
101 }
102
103 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
104 {
105         int a;
106         float pat_min[2];
107         float pat_max[2];
108         float max_pyramid_level_factor = 1.0;
109
110         if (track->tracker == TRACKER_KLT) {
111                 max_pyramid_level_factor= 1 << (track->pyramid_levels - 1);
112         }
113
114         /* sort */
115         for(a= 0; a<2; a++) {
116                 if(track->pat_min[a]>track->pat_max[a])
117                         SWAP(float, track->pat_min[a], track->pat_max[a]);
118
119                 if(track->search_min[a]>track->search_max[a])
120                         SWAP(float, track->search_min[a], track->search_max[a]);
121         }
122
123         /* compute the effective pattern size, which differs from the fine resolution
124          * pattern size for the pyramid KLT tracker */
125         for(a= 0; a<2; a++) {
126                 pat_min[a] = max_pyramid_level_factor * track->pat_min[a];
127                 pat_max[a] = max_pyramid_level_factor * track->pat_max[a];
128         }
129
130         if(event==CLAMP_PAT_DIM) {
131                 for(a= 0; a<2; a++) {
132                         /* search shouldn't be resized smaller than pattern */
133                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
134                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
135                 }
136         }
137         else if(event==CLAMP_PAT_POS) {
138                 float dim[2];
139                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
140
141                 for(a= 0; a<2; a++) {
142                         /* pattern shouldn't be moved outside of search */
143                         if(pat_min[a] < track->search_min[a]) {
144                                 track->pat_min[a]= track->search_min[a] - (pat_min[a] - track->pat_min[a]);
145                                 track->pat_max[a]= track->pat_min[a] + dim[a];
146                         }
147                         if(track->pat_max[a] > track->search_max[a]) {
148                                 track->pat_max[a]= track->search_max[a] - (pat_max[a] - track->pat_max[a]);
149                                 track->pat_min[a]= track->pat_max[a] - dim[a];
150                         }
151                 }
152         }
153         else if(event==CLAMP_SEARCH_DIM) {
154                 for(a= 0; a<2; a++) {
155                         /* search shouldn't be resized smaller than pattern */
156                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
157                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
158                 }
159         }
160         else if(event==CLAMP_SEARCH_POS) {
161                 float dim[2];
162                 sub_v2_v2v2(dim, track->search_max, track->search_min);
163
164                 for(a= 0; a<2; a++) {
165                         /* search shouldn't be moved inside pattern */
166                         if(track->search_min[a] > pat_min[a]) {
167                                 track->search_min[a]= pat_min[a];
168                                 track->search_max[a]= track->search_min[a]+dim[a];
169                         }
170                         if(track->search_max[a] < pat_max[a]) {
171                                 track->search_max[a]= pat_max[a];
172                                 track->search_min[a]= track->search_max[a]-dim[a];
173                         }
174                 }
175         }
176         else if(event==CLAMP_PYRAMID_LEVELS || (event==CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT))  {
177                 float dim[2];
178                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
179                 {
180                         float search_ratio= 2.3f * max_pyramid_level_factor;
181
182                         /* resize the search area to something sensible based
183                          * on the number of pyramid levels */
184                         for(a= 0; a<2; a++) {
185                                 track->search_min[a]= search_ratio * track->pat_min[a];
186                                 track->search_max[a]= search_ratio * track->pat_max[a];
187                         }
188                 }
189         }
190
191         /* marker's center should be in center of pattern */
192         if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
193                 float dim[2];
194                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
195
196                 for(a= 0; a<2; a++) {
197                         track->pat_min[a]= -dim[a]/2.0f;
198                         track->pat_max[a]= dim[a]/2.0f;
199                 }
200         }
201 }
202
203 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
204 {
205         if(area==TRACK_AREA_NONE)
206                 return;
207
208         if(clear) {
209                 if(area&TRACK_AREA_POINT)       track->flag&= ~flag;
210                 if(area&TRACK_AREA_PAT)         track->pat_flag&= ~flag;
211                 if(area&TRACK_AREA_SEARCH)      track->search_flag&= ~flag;
212         } else {
213                 if(area&TRACK_AREA_POINT)       track->flag|= flag;
214                 if(area&TRACK_AREA_PAT)         track->pat_flag|= flag;
215                 if(area&TRACK_AREA_SEARCH)      track->search_flag|= flag;
216         }
217 }
218
219 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
220                         int framenr, int width, int height)
221 {
222         MovieTrackingTrack *track;
223         MovieTrackingMarker marker;
224         MovieTrackingSettings *settings= &tracking->settings;
225
226         float half_pattern= (float)settings->default_pattern_size/2.0f;
227         float half_search= (float)settings->default_search_size/2.0f;
228         float pat[2], search[2];
229
230         pat[0]= half_pattern/(float)width;
231         pat[1]= half_pattern/(float)height;
232
233         search[0]= half_search/(float)width;
234         search[1]= half_search/(float)height;
235
236         track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
237         strcpy(track->name, "Track");
238
239         track->tracker= settings->default_tracker;
240         track->pyramid_levels= settings->default_pyramid_levels;
241         track->minimum_correlation= settings->default_minimum_correlation;
242         track->margin= settings->default_margin;
243         track->pattern_match= settings->default_pattern_match;
244         track->frames_limit= settings->default_frames_limit;
245
246         memset(&marker, 0, sizeof(marker));
247         marker.pos[0]= x;
248         marker.pos[1]= y;
249         marker.framenr= framenr;
250
251         copy_v2_v2(track->pat_max, pat);
252         negate_v2_v2(track->pat_min, pat);
253
254         copy_v2_v2(track->search_max, search);
255         negate_v2_v2(track->search_min, search);
256
257         BKE_tracking_insert_marker(track, &marker);
258
259         if(track->tracker == TRACKER_KLT)
260                 BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS);
261
262         BLI_addtail(tracksbase, track);
263         BKE_track_unique_name(tracksbase, track);
264
265         return track;
266 }
267
268 MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
269 {
270         MovieTrackingMarker *old_marker= NULL;
271
272         if(track->markersnr)
273                 old_marker= BKE_tracking_exact_marker(track, marker->framenr);
274
275         if(old_marker) {
276                 *old_marker= *marker;
277
278                 return old_marker;
279         } else {
280                 int a= track->markersnr;
281
282                 while(a--) {
283                         if(track->markers[a].framenr<marker->framenr)
284                                 break;
285                 }
286
287                 track->markersnr++;
288
289                 if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
290                 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
291
292                 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
293                 track->markers[a+1]= *marker;
294
295                 track->last_marker= a+1;
296
297                 return &track->markers[a+1];
298         }
299 }
300
301 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
302 {
303         int a= 0;
304
305         while(a<track->markersnr) {
306                 if(track->markers[a].framenr==framenr) {
307                         if(track->markersnr>1) {
308                                 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
309                                 track->markersnr--;
310                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
311                         } else {
312                                 MEM_freeN(track->markers);
313                                 track->markers= NULL;
314                                 track->markersnr= 0;
315                         }
316
317                         break;
318                 }
319
320                 a++;
321         }
322 }
323
324 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
325 {
326         int a= track->markersnr-1;
327
328         if(!track->markersnr)
329                 return NULL;
330
331         /* approximate pre-first framenr marker with first marker */
332         if(framenr<track->markers[0].framenr)
333                 return &track->markers[0];
334
335         if(track->last_marker<track->markersnr)
336                 a= track->last_marker;
337
338         if(track->markers[a].framenr<=framenr) {
339                 while(a<track->markersnr && track->markers[a].framenr<=framenr) {
340                         if(track->markers[a].framenr==framenr) {
341                                 track->last_marker= a;
342                                 return &track->markers[a];
343                         }
344                         a++;
345                 }
346
347                 /* if there's no marker for exact position, use nearest marker from left side */
348                 return &track->markers[a-1];
349         } else {
350                 while(a>=0 && track->markers[a].framenr>=framenr) {
351                         if(track->markers[a].framenr==framenr) {
352                                 track->last_marker= a;
353                                 return &track->markers[a];
354                         }
355
356                         a--;
357                 }
358
359                 /* if there's no marker for exact position, use nearest marker from left side */
360                 return &track->markers[a];
361         }
362
363         return NULL;
364 }
365
366 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
367 {
368         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
369
370         if(marker->framenr!=framenr) {
371                 MovieTrackingMarker marker_new;
372
373                 marker_new= *marker;
374                 marker_new.framenr= framenr;
375
376                 BKE_tracking_insert_marker(track, &marker_new);
377                 marker= BKE_tracking_get_marker(track, framenr);
378         }
379
380         return marker;
381 }
382
383 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
384 {
385         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
386
387         if(marker->framenr!=framenr)
388                 return NULL;
389
390         return marker;
391 }
392
393 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
394 {
395         return BKE_tracking_exact_marker(track, framenr) != 0;
396 }
397
398 int BKE_tracking_has_enabled_marker(MovieTrackingTrack *track, int framenr)
399 {
400         MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr);
401
402         return marker && (marker->flag & MARKER_DISABLED) == 0;
403 }
404
405 void BKE_tracking_free_track(MovieTrackingTrack *track)
406 {
407         if(track->markers) MEM_freeN(track->markers);
408 }
409
410 static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite)
411 {
412         MovieTrackingMarker marker_new;
413
414         marker_new= *ref_marker;
415         marker_new.flag&= ~MARKER_TRACKED;
416         marker_new.flag|= MARKER_DISABLED;
417
418         if(before) marker_new.framenr--;
419         else marker_new.framenr++;
420
421         if(!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite)
422                 BKE_tracking_insert_marker(track, &marker_new);
423 }
424
425 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
426 {
427         int a;
428
429         if(action==TRACK_CLEAR_REMAINED) {
430                 a= 1;
431                 while(a<track->markersnr) {
432                         if(track->markers[a].framenr>ref_frame) {
433                                 track->markersnr= a;
434                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
435
436                                 break;
437                         }
438
439                         a++;
440                 }
441
442                 if(track->markersnr)
443                         put_disabled_marker(track, &track->markers[track->markersnr-1], 0, 1);
444         } else if(action==TRACK_CLEAR_UPTO) {
445                 a= track->markersnr-1;
446                 while(a>=0) {
447                         if(track->markers[a].framenr<=ref_frame) {
448                                 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
449
450                                 track->markersnr= track->markersnr-a;
451                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
452
453                                 break;
454                         }
455
456                         a--;
457                 }
458
459                 if(track->markersnr)
460                         put_disabled_marker(track, &track->markers[0], 1, 1);
461         } else if(action==TRACK_CLEAR_ALL) {
462                 MovieTrackingMarker *marker, marker_new;
463
464                 marker= BKE_tracking_get_marker(track, ref_frame);
465                 marker_new= *marker;
466
467                 MEM_freeN(track->markers);
468                 track->markers= NULL;
469                 track->markersnr= 0;
470
471                 BKE_tracking_insert_marker(track, &marker_new);
472
473                 put_disabled_marker(track, &marker_new, 1, 1);
474                 put_disabled_marker(track, &marker_new, 0, 1);
475         }
476 }
477
478 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
479 {
480         int a= 0, b= 0;
481         int count= 0;
482
483         while(a<src_track->markersnr || b<dst_track->markersnr) {
484                 if(b>=dst_track->markersnr) {
485                         a++;
486                         count++;
487                 }
488                 else if(a>=src_track->markersnr) {
489                         b++;
490                         count++;
491                 }
492                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
493                         a++;
494                         count++;
495                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
496                         b++;
497                         count++;
498                 } else {
499                         if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0)
500                                 return 0;
501
502                         a++;
503                         b++;
504                         count++;
505                 }
506         }
507
508         return count;
509 }
510
511 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
512 {
513         int i, a= 0, b= 0, tot;
514         MovieTrackingMarker *markers;
515
516         tot= BKE_tracking_test_join_tracks(dst_track, src_track);
517
518         markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks");
519
520         for(i= 0; i<tot; i++) {
521                 if(b>=dst_track->markersnr) {
522                         markers[i]= src_track->markers[a++];
523                 }
524                 else if(a>=src_track->markersnr) {
525                         markers[i]= dst_track->markers[b++];
526                 }
527                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
528                         markers[i]= src_track->markers[a++];
529                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
530                         markers[i]= dst_track->markers[b++];
531                 } else {
532                         if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b];
533                         else markers[i]= src_track->markers[a++];
534
535                         a++;
536                         b++;
537                 }
538         }
539
540         MEM_freeN(dst_track->markers);
541
542         dst_track->markers= markers;
543         dst_track->markersnr= tot;
544 }
545
546 static void tracking_tracks_free(ListBase *tracks)
547 {
548         MovieTrackingTrack *track;
549
550         for(track= tracks->first; track; track= track->next) {
551                 BKE_tracking_free_track(track);
552         }
553
554         BLI_freelistN(tracks);
555 }
556
557 static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
558 {
559         if(reconstruction->cameras)
560                 MEM_freeN(reconstruction->cameras);
561 }
562
563 static void tracking_object_free(MovieTrackingObject *object)
564 {
565         tracking_tracks_free(&object->tracks);
566         tracking_reconstruction_free(&object->reconstruction);
567 }
568
569 static void tracking_objects_free(ListBase *objects)
570 {
571         MovieTrackingObject *object;
572
573         for(object= objects->first; object; object= object->next)
574                 tracking_object_free(object);
575
576         BLI_freelistN(objects);
577 }
578
579 void BKE_tracking_free(MovieTracking *tracking)
580 {
581         tracking_tracks_free(&tracking->tracks);
582         tracking_reconstruction_free(&tracking->reconstruction);
583         tracking_objects_free(&tracking->objects);
584
585         if(tracking->stabilization.scaleibuf)
586                 IMB_freeImBuf(tracking->stabilization.scaleibuf);
587
588         if(tracking->camera.intrinsics)
589                 BKE_tracking_distortion_destroy(tracking->camera.intrinsics);
590 }
591
592 static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track)
593 {
594         MovieTrackingTrack *new_track;
595
596         new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track");
597
598         *new_track= *track;
599         new_track->next = new_track->prev = NULL;
600
601         new_track->markers = MEM_dupallocN(new_track->markers);
602
603         return new_track;
604 }
605
606 /*********************** clipboard *************************/
607
608 void BKE_tracking_free_clipboard(void)
609 {
610         MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track;
611
612         while (track) {
613                 next_track = track->next;
614
615                 BKE_tracking_free_track(track);
616                 MEM_freeN(track);
617
618                 track = next_track;
619         }
620 }
621
622 void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object)
623 {
624         ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
625         MovieTrackingTrack *track = tracksbase->first;
626
627         while (track) {
628                 if (TRACK_SELECTED(track)) {
629                         MovieTrackingTrack *new_track = duplicate_track(track);
630
631                         BLI_addtail(&tracking_clipboard.tracks, new_track);
632                 }
633
634                 track = track->next;
635         }
636 }
637
638 int BKE_tracking_clipboard_has_tracks(void)
639 {
640         return tracking_clipboard.tracks.first != NULL;
641 }
642
643 void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object)
644 {
645         ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
646         MovieTrackingTrack *track = tracking_clipboard.tracks.first;
647
648         while (track) {
649                 MovieTrackingTrack *new_track = duplicate_track(track);
650
651                 BLI_addtail(tracksbase, new_track);
652                 BKE_track_unique_name(tracksbase, new_track);
653
654                 track = track->next;
655         }
656 }
657
658 /*********************** tracks map *************************/
659
660 typedef struct TracksMap {
661         char object_name[MAX_NAME];
662         int is_camera;
663
664         int num_tracks;
665         int customdata_size;
666
667         char *customdata;
668         MovieTrackingTrack *tracks;
669
670         GHash *hash;
671
672         int ptr;
673 } TracksMap;
674
675 static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
676 {
677         TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap");
678
679         BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
680         map->is_camera= is_camera;
681
682         map->num_tracks= num_tracks;
683         map->customdata_size= customdata_size;
684
685         map->tracks= MEM_callocN(sizeof(MovieTrackingTrack)*num_tracks, "TrackingsMap tracks");
686
687         if(customdata_size)
688                 map->customdata= MEM_callocN(customdata_size*num_tracks, "TracksMap customdata");
689
690         map->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "TracksMap hash");
691
692         return map;
693 }
694
695 static int tracks_map_size(TracksMap *map)
696 {
697         return map->num_tracks;
698 }
699
700 static void tracks_map_get(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
701 {
702         *track= &map->tracks[index];
703
704         if(map->customdata)
705                 *customdata= &map->customdata[index*map->customdata_size];
706 }
707
708 static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
709 {
710         MovieTrackingTrack new_track= *track;
711
712         new_track.markers= MEM_dupallocN(new_track.markers);
713
714         map->tracks[map->ptr]= new_track;
715
716         if(customdata)
717                 memcpy(&map->customdata[map->ptr*map->customdata_size], customdata, map->customdata_size);
718
719         BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
720
721         map->ptr++;
722 }
723
724 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
725 {
726         MovieTrackingTrack *track;
727         MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
728         ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
729         ListBase *old_tracks;
730         int a;
731
732         if(map->is_camera) {
733                 old_tracks= &tracking->tracks;
734         } else {
735                 MovieTrackingObject *object= BKE_tracking_named_object(tracking, map->object_name);
736
737                 if(!object) {
738                         /* object was deleted by user, create new one */
739                         object= BKE_tracking_new_object(tracking, map->object_name);
740                 }
741
742                 old_tracks= &object->tracks;
743         }
744
745         /* duplicate currently operating tracks to temporary list.
746            this is needed to keep names in unique state and it's faster to change names
747            of currently operating tracks (if needed) */
748         for(a= 0; a<map->num_tracks; a++) {
749                 int replace_sel= 0;
750                 MovieTrackingTrack *new_track, *old;
751
752                 track= &map->tracks[a];
753
754                 /* find original of operating track in list of previously displayed tracks */
755                 old= BLI_ghash_lookup(map->hash, track);
756                 if(old) {
757                         MovieTrackingTrack *cur= old_tracks->first;
758
759                         while(cur) {
760                                 if(cur==old)
761                                         break;
762
763                                 cur= cur->next;
764                         }
765
766                         /* original track was found, re-use flags and remove this track */
767                         if(cur) {
768                                 if(act_track)
769                                         replace_sel= 1;
770
771                                 track->flag= cur->flag;
772                                 track->pat_flag= cur->pat_flag;
773                                 track->search_flag= cur->search_flag;
774
775                                 BKE_tracking_free_track(cur);
776                                 BLI_freelinkN(old_tracks, cur);
777                         }
778                 }
779
780                 new_track= duplicate_track(track);
781
782                 BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */
783                 BLI_ghash_insert(map->hash, track, new_track);
784
785                 if(replace_sel)         /* update current selection in clip */
786                         tracking->act_track= new_track;
787
788                 BLI_addtail(&tracks, new_track);
789         }
790
791         /* move all tracks, which aren't operating */
792         track= old_tracks->first;
793         while(track) {
794                 MovieTrackingTrack *next= track->next;
795
796                 track->next= track->prev= NULL;
797                 BLI_addtail(&new_tracks, track);
798
799                 track= next;
800         }
801
802         /* now move all tracks which are currently operating and keep their names unique */
803         track= tracks.first;
804         while(track) {
805                 MovieTrackingTrack *next= track->next;
806
807                 BLI_remlink(&tracks, track);
808
809                 track->next= track->prev= NULL;
810                 BLI_addtail(&new_tracks, track);
811
812                 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
813
814                 track= next;
815         }
816
817         *old_tracks= new_tracks;
818 }
819
820 static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata))
821 {
822         int i= 0;
823
824         BLI_ghash_free(map->hash, NULL, NULL);
825
826         for(i= 0; i<map->num_tracks; i++) {
827                 if(map->customdata && customdata_free)
828                         customdata_free(&map->customdata[i*map->customdata_size]);
829
830                 BKE_tracking_free_track(&map->tracks[i]);
831         }
832
833         if(map->customdata)
834                 MEM_freeN(map->customdata);
835
836         MEM_freeN(map->tracks);
837         MEM_freeN(map);
838 }
839
840 /*********************** tracking *************************/
841
842 typedef struct TrackContext {
843 #ifdef WITH_LIBMV
844         float keyframed_pos[2];
845
846         /* ** KLT tracker ** */
847         struct libmv_RegionTracker *region_tracker;
848         float *patch;                   /* keyframed patch */
849
850         /* ** SAD tracker ** */
851         int pattern_size;               /* size of pattern */
852         unsigned char *pattern; /* keyframed pattern */
853         unsigned char *warped;  /* warped version of reference */
854 #else
855         int pad;
856 #endif
857 } TrackContext;
858
859 typedef struct MovieTrackingContext {
860         MovieClipUser user;
861         MovieClip *clip;
862         int clip_flag;
863
864         int first_time, frames;
865
866         MovieTrackingSettings settings;
867         TracksMap *tracks_map;
868
869         short backwards, sequence;
870         int sync_frame;
871 } MovieTrackingContext;
872
873 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence)
874 {
875         MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
876         MovieTracking *tracking= &clip->tracking;
877         MovieTrackingSettings *settings= &tracking->settings;
878         ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
879         MovieTrackingTrack *track;
880         MovieTrackingObject *object= BKE_tracking_active_object(tracking);
881         int num_tracks= 0;
882
883         context->settings= *settings;
884         context->backwards= backwards;
885         context->sync_frame= user->framenr;
886         context->first_time= 1;
887         context->sequence= sequence;
888
889         /* count */
890         track= tracksbase->first;
891         while(track) {
892                 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
893                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
894
895                         if((marker->flag&MARKER_DISABLED)==0)
896                                 num_tracks++;
897                 }
898
899                 track= track->next;
900         }
901
902         if(num_tracks) {
903                 int width, height;
904
905                 context->tracks_map= tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
906                                         num_tracks, sizeof(TrackContext));
907
908                 BKE_movieclip_get_size(clip, user, &width, &height);
909
910                 /* create tracking data */
911                 track= tracksbase->first;
912                 while(track) {
913                         if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
914                                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
915
916                                 if((marker->flag&MARKER_DISABLED)==0) {
917                                         TrackContext track_context;
918
919                                         memset(&track_context, 0, sizeof(TrackContext));
920
921 #ifdef WITH_LIBMV
922                                         {
923                                                 float patx, paty;
924                                                 patx= (int)((track->pat_max[0]-track->pat_min[0])*width);
925                                                 paty= (int)((track->pat_max[1]-track->pat_min[1])*height);
926
927                                                 if(ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) {
928                                                         float search_size_x= (track->search_max[0]-track->search_min[0])*width;
929                                                         float search_size_y= (track->search_max[1]-track->search_min[1])*height;
930                                                         float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
931                                                         float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
932                                                         int wndx= (int)patx/2, wndy= (int)paty/2;
933
934                                                         /* compute the maximum pyramid size */
935                                                         float search_to_pattern_ratio= MIN2(search_size_x,  search_size_y)
936                                                                 / MAX2(pattern_size_x, pattern_size_y);
937                                                         float log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2;
938                                                         int max_pyramid_levels= floor(log2_search_to_pattern_ratio + 1);
939
940                                                         /* try to accomodate the user's choice of pyramid level in a way
941                                                          * that doesn't cause the coarsest pyramid pattern to be larger
942                                                          * than the search size */
943                                                         int level= MIN2(track->pyramid_levels, max_pyramid_levels);
944
945                                                         if(track->tracker==TRACKER_KLT)
946                                                                 track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy), track->minimum_correlation);
947                                                         else
948                                                                 track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy), track->minimum_correlation);
949                                                 }
950                                                 else if(track->tracker==TRACKER_SAD) {
951                                                         track_context.pattern_size= MAX2(patx, paty);
952                                                 }
953                                         }
954 #endif
955
956                                         tracks_map_insert(context->tracks_map, track, &track_context);
957                                 }
958                         }
959
960                         track= track->next;
961                 }
962         }
963
964         context->clip= clip;
965
966         /* store needed clip flags passing to get_buffer functions
967          * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip
968          *   only in case Proxy/Timecode flag is set, so store this flag to use
969          *   timecodes properly but reset render size to SIZE_FULL so correct resolution
970          *   would be used for images
971          * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might
972          *   be stored in a different location
973          * ignore all the rest pssible flags for now */
974         context->clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS;
975
976         context->user= *user;
977         context->user.render_size= 0;
978         context->user.render_flag= MCLIP_PROXY_RENDER_SIZE_FULL;
979
980         if(!sequence)
981                 BLI_begin_threaded_malloc();
982
983         return context;
984 }
985
986 static void track_context_free(void *customdata)
987 {
988         TrackContext *track_context= (TrackContext *)customdata;
989
990 #if WITH_LIBMV
991         if(track_context->region_tracker)
992                 libmv_regionTrackerDestroy(track_context->region_tracker);
993
994         if(track_context->patch)
995                 MEM_freeN(track_context->patch);
996
997         if(track_context->pattern)
998                 MEM_freeN(track_context->pattern);
999
1000         if(track_context->warped)
1001                 MEM_freeN(track_context->warped);
1002 #else
1003                 (void) track_context;
1004 #endif
1005 }
1006
1007 void BKE_tracking_context_free(MovieTrackingContext *context)
1008 {
1009         if(!context->sequence)
1010                 BLI_end_threaded_malloc();
1011
1012         tracks_map_free(context->tracks_map, track_context_free);
1013
1014         MEM_freeN(context);
1015 }
1016
1017 /* zap channels from the imbuf that are disabled by the user. this can lead to
1018  * better tracks sometimes. however, instead of simply zeroing the channels
1019  * out, do a partial grayscale conversion so the display is better. */
1020 void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale)
1021 {
1022         int x, y;
1023         float scale;
1024
1025         if(!disable_red && !disable_green && !disable_blue && !grayscale)
1026                 return;
1027
1028         /* If only some components are selected, it's important to rescale the result
1029          * appropriately so that e.g. if only blue is selected, it's not zeroed out. */
1030         scale = (disable_red   ? 0.0f : 0.2126f) +
1031                 (disable_green ? 0.0f : 0.7152f) +
1032                 (disable_blue  ? 0.0f : 0.0722f);
1033
1034         for(y= 0; y<ibuf->y; y++) {
1035                 for (x= 0; x<ibuf->x; x++) {
1036                         int pixel= ibuf->x*y + x;
1037
1038                         if(ibuf->rect_float) {
1039                                 float *rrgbf= ibuf->rect_float + pixel*4;
1040                                 float r = disable_red   ? 0.0f : rrgbf[0];
1041                                 float g = disable_green ? 0.0f : rrgbf[1];
1042                                 float b = disable_blue  ? 0.0f : rrgbf[2];
1043                                 if (grayscale) {
1044                                         float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
1045                                         rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
1046                                 } else {
1047                                         rrgbf[0] = r;
1048                                         rrgbf[1] = g;
1049                                         rrgbf[2] = b;
1050                                 }
1051                         } else {
1052                                 char *rrgb= (char*)ibuf->rect + pixel*4;
1053                                 char r = disable_red   ? 0 : rrgb[0];
1054                                 char g = disable_green ? 0 : rrgb[1];
1055                                 char b = disable_blue  ? 0 : rrgb[2];
1056                                 if (grayscale) {
1057                                         float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
1058                                         rrgb[0] = rrgb[1] = rrgb[2] = gray;
1059                                 } else {
1060                                         rrgb[0] = r;
1061                                         rrgb[1] = g;
1062                                         rrgb[2] = b;
1063                                 }
1064                         }
1065                 }
1066         }
1067 }
1068
1069 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
1070 {
1071         BKE_tracking_disable_imbuf_channels(ibuf, track->flag&TRACK_DISABLE_RED,
1072                         track->flag&TRACK_DISABLE_GREEN, track->flag&TRACK_DISABLE_BLUE, grayscale);
1073 }
1074
1075 static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1076                         float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2])
1077 {
1078         ImBuf *tmpibuf;
1079         int x, y;
1080         int x1, y1, w, h;
1081         float mpos[2];
1082
1083         copy_v2_v2(mpos, marker->pos);
1084         if(anchored)
1085                 add_v2_v2(mpos, track->offset);
1086
1087         if(pos)
1088                 zero_v2(pos);
1089
1090         x= mpos[0]*ibuf->x;
1091         y= mpos[1]*ibuf->y;
1092
1093         w= (max[0]-min[0])*ibuf->x;
1094         h= (max[1]-min[1])*ibuf->y;
1095
1096         w= w|1;
1097         h= h|1;
1098
1099         x1= x-(int)(w/2.0f);
1100         y1= y-(int)(h/2.0f);
1101
1102         /* dimensions should be odd */
1103         tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
1104         IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
1105
1106         if(pos != NULL) {
1107                 pos[0]= mpos[0]*ibuf->x-x1+margin;
1108                 pos[1]= mpos[1]*ibuf->y-y1+margin;
1109         }
1110
1111         if(origin != NULL) {
1112                 origin[0]= x1-margin;
1113                 origin[1]= y1-margin;
1114         }
1115
1116         if((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
1117            (track->flag & TRACK_DISABLE_RED)       ||
1118            (track->flag & TRACK_DISABLE_GREEN)     ||
1119            (track->flag & TRACK_DISABLE_BLUE))
1120         {
1121                 disable_imbuf_channels(tmpibuf, track, 1 /* grayscale */);
1122         }
1123
1124         return tmpibuf;
1125 }
1126
1127 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1128                         int margin, int anchored, float pos[2], int origin[2])
1129 {
1130         return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin);
1131 }
1132
1133 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1134                         int margin, int anchored, float pos[2], int origin[2])
1135 {
1136         return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin);
1137 }
1138
1139 #ifdef WITH_LIBMV
1140 static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1141                         int *width_r, int *height_r, float pos[2], int origin[2])
1142 {
1143         ImBuf *tmpibuf;
1144         float *pixels, *fp;
1145         int x, y, width, height;
1146
1147         width= (track->search_max[0]-track->search_min[0])*ibuf->x;
1148         height= (track->search_max[1]-track->search_min[1])*ibuf->y;
1149
1150         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
1151         disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
1152
1153         *width_r= width;
1154         *height_r= height;
1155
1156         fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
1157         for(y= 0; y<(int)height; y++) {
1158                 for (x= 0; x<(int)width; x++) {
1159                         int pixel= tmpibuf->x*y + x;
1160
1161                         if(tmpibuf->rect_float) {
1162                                 float *rrgbf= tmpibuf->rect_float + pixel*4;
1163                                 *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2];
1164                         } else {
1165                                 unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4;
1166                                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f;
1167                         }
1168                         fp++;
1169                 }
1170         }
1171
1172         IMB_freeImBuf(tmpibuf);
1173
1174         return pixels;
1175 }
1176
1177 static unsigned char *get_ucharbuf(ImBuf *ibuf)
1178 {
1179         int x, y;
1180         unsigned char *pixels, *cp;
1181
1182         cp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
1183         for(y= 0; y<ibuf->y; y++) {
1184                 for (x= 0; x<ibuf->x; x++) {
1185                         int pixel= ibuf->x*y + x;
1186
1187                         if(ibuf->rect_float) {
1188                                 const float *rrgbf= ibuf->rect_float + pixel*4;
1189                                 const float grey_f= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2];
1190                                 *cp= FTOCHAR(grey_f);
1191                         } else {
1192                                 const unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4;
1193                                 *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
1194                         }
1195                         cp++;
1196                 }
1197         }
1198
1199         return pixels;
1200 }
1201
1202 static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1203                         int *width_r, int *height_r, float pos[2], int origin[2])
1204 {
1205         ImBuf *tmpibuf;
1206         unsigned char *pixels;
1207
1208         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
1209         disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
1210
1211         *width_r= tmpibuf->x;
1212         *height_r= tmpibuf->y;
1213
1214         pixels= get_ucharbuf(tmpibuf);
1215
1216         IMB_freeImBuf(tmpibuf);
1217
1218         return pixels;
1219 }
1220
1221 static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr)
1222 {
1223         ImBuf *ibuf;
1224         MovieClipUser user= context->user;
1225
1226         user.framenr= framenr;
1227
1228         ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag);
1229
1230         return ibuf;
1231 }
1232
1233 static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
1234                         MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
1235 {
1236         int framenr= marker->framenr;
1237         int a= marker-track->markers;
1238
1239         *marker_keyed= marker;
1240
1241         while(a>=0 && a<track->markersnr) {
1242                 int next= (context->backwards) ? a+1 : a-1;
1243                 int is_keyframed= 0;
1244                 MovieTrackingMarker *cur_marker= &track->markers[a];
1245                 MovieTrackingMarker *next_marker= NULL;
1246
1247                 if(next>=0 && next<track->markersnr)
1248                         next_marker= &track->markers[next];
1249
1250                 /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */
1251                 if(next_marker && next_marker->flag&MARKER_DISABLED)
1252                         is_keyframed= 1;
1253
1254                 is_keyframed|= (cur_marker->flag&MARKER_TRACKED)==0;
1255
1256                 if(is_keyframed) {
1257                         framenr= cur_marker->framenr;
1258                         *marker_keyed= cur_marker;
1259                         break;
1260                 }
1261
1262                 a= next;
1263         }
1264
1265         return get_frame_ibuf(context, framenr);
1266 }
1267
1268 static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
1269                         int curfra, MovieTrackingMarker **marker_keyed)
1270 {
1271         ImBuf *ibuf= NULL;
1272
1273         if(track->pattern_match == TRACK_MATCH_KEYFRAME) {
1274                 ibuf= get_keyframed_ibuf(context, track, marker, marker_keyed);
1275         } else {
1276                 ibuf= get_frame_ibuf(context, curfra);
1277
1278                 /* use current marker as keyframed position */
1279                 *marker_keyed= marker;
1280         }
1281
1282         return ibuf;
1283 }
1284
1285 static void get_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image)
1286 {
1287         int i, j;
1288
1289         for(i=0; i<track_context->pattern_size; i++) {
1290                 for(j=0; j<track_context->pattern_size; j++) {
1291                         track_context->warped[i*track_context->pattern_size+j]=
1292                                         image[(y+i-track_context->pattern_size/2)*width+x+j-track_context->pattern_size/2];
1293                 }
1294         }
1295 }
1296
1297 #endif
1298
1299 void BKE_tracking_sync(MovieTrackingContext *context)
1300 {
1301         MovieTracking *tracking= &context->clip->tracking;
1302         int newframe;
1303
1304         tracks_map_merge(context->tracks_map, tracking);
1305
1306         if(context->backwards) newframe= context->user.framenr+1;
1307         else newframe= context->user.framenr-1;
1308
1309         context->sync_frame= newframe;
1310 }
1311
1312 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
1313 {
1314         user->framenr= context->sync_frame;
1315 }
1316
1317 int BKE_tracking_next(MovieTrackingContext *context)
1318 {
1319         ImBuf *ibuf_new;
1320         int curfra= context->user.framenr;
1321         int a, ok= 0, map_size;
1322
1323         map_size= tracks_map_size(context->tracks_map);
1324
1325         /* nothing to track, avoid unneeded frames reading to save time and memory */
1326         if(!map_size)
1327                 return 0;
1328
1329         if(context->backwards) context->user.framenr--;
1330         else context->user.framenr++;
1331
1332         ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag);
1333         if(!ibuf_new)
1334                 return 0;
1335
1336         #pragma omp parallel for private(a) shared(ibuf_new, ok) if(map_size>1)
1337         for(a= 0; a<map_size; a++) {
1338                 TrackContext *track_context = NULL;
1339                 MovieTrackingTrack *track;
1340                 MovieTrackingMarker *marker;
1341
1342                 tracks_map_get(context->tracks_map, a, &track, (void**)&track_context);
1343
1344                 marker= BKE_tracking_exact_marker(track, curfra);
1345
1346                 if(marker && (marker->flag&MARKER_DISABLED)==0) {
1347 #ifdef WITH_LIBMV
1348                         int width, height, origin[2], tracked= 0, need_readjust= 0;
1349                         float pos[2], margin[2], dim[2];
1350                         double x1, y1, x2, y2;
1351                         ImBuf *ibuf= NULL;
1352                         MovieTrackingMarker marker_new, *marker_keyed;
1353                         int onbound= 0, nextfra;
1354
1355                         if(track->pattern_match==TRACK_MATCH_KEYFRAME)
1356                                 need_readjust= context->first_time;
1357                         else
1358                                 need_readjust= 1;
1359
1360                         if(context->backwards) nextfra= curfra-1;
1361                         else nextfra= curfra+1;
1362
1363                         /* margin from frame boundaries */
1364                         sub_v2_v2v2(dim, track->pat_max, track->pat_min);
1365                         margin[0]= margin[1]= MAX2(dim[0], dim[1]) / 2.0f;
1366
1367                         margin[0]= MAX2(margin[0], (float)track->margin / ibuf_new->x);
1368                         margin[1]= MAX2(margin[1], (float)track->margin / ibuf_new->y);
1369
1370                         /* do not track markers which are too close to boundary */
1371                         if(marker->pos[0]<margin[0] || marker->pos[0]>1.0f-margin[0] ||
1372                            marker->pos[1]<margin[1] || marker->pos[1]>1.0f-margin[1]) {
1373                                 onbound= 1;
1374                         }
1375                         else if(ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) {
1376                                 float *patch_new;
1377
1378                                 if(need_readjust) {
1379                                         /* calculate patch for keyframed position */
1380                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1381
1382                                         if(track_context->patch)
1383                                                 MEM_freeN(track_context->patch);
1384
1385                                         track_context->patch= get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, track_context->keyframed_pos, origin);
1386
1387                                         IMB_freeImBuf(ibuf);
1388                                 }
1389
1390                                 patch_new= get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
1391
1392                                 x1= track_context->keyframed_pos[0];
1393                                 y1= track_context->keyframed_pos[1];
1394
1395                                 x2= pos[0];
1396                                 y2= pos[1];
1397
1398                                 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
1399                                                         width, height, x1, y1, &x2, &y2);
1400
1401                                 MEM_freeN(patch_new);
1402                         }
1403                         else if(track->tracker==TRACKER_SAD) {
1404                                 unsigned char *image_new;
1405                                 float correlation;
1406                                 float warp[3][2]={{0}};
1407
1408                                 if(need_readjust) {
1409                                         unsigned char *image;
1410
1411                                         /* calculate pattern for keyframed position */
1412                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1413
1414                                         image= get_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1415
1416                                         memset(warp, 0, sizeof(warp));
1417                                         warp[0][0]= 1;
1418                                         warp[1][1]= 1;
1419                                         warp[2][0]= pos[0];
1420                                         warp[2][1]= pos[1];
1421
1422                                         if(!track_context->pattern) {
1423                                                 int square= track_context->pattern_size*track_context->pattern_size;
1424                                                 track_context->pattern= MEM_callocN(sizeof(unsigned char)*square, "trackking pattern");
1425                                         }
1426
1427                                         libmv_SADSamplePattern(image, width, warp, track_context->pattern, track_context->pattern_size);
1428
1429                                         MEM_freeN(image);
1430                                         IMB_freeImBuf(ibuf);
1431                                 }
1432
1433                                 image_new= get_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
1434
1435                                 if(track_context->warped==NULL) {
1436                                         unsigned char *image_old;
1437
1438                                         ibuf= get_frame_ibuf(context, curfra);
1439
1440                                         if(track_context->warped==NULL) {
1441                                                 int square= track_context->pattern_size*track_context->pattern_size;
1442                                                 track_context->warped= MEM_callocN(sizeof(unsigned char)*square, "trackking warped");
1443                                         }
1444
1445                                         image_old= get_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
1446                                         get_warped(track_context, pos[0], pos[1], width, image_old);
1447                                         IMB_freeImBuf(ibuf);
1448                                         MEM_freeN(image_old);
1449                                 }
1450
1451                                 memset(warp, 0, sizeof(warp));
1452                                 warp[0][0]= 1;
1453                                 warp[1][1]= 1;
1454                                 warp[2][0]= pos[0];
1455                                 warp[2][1]= pos[1];
1456
1457                                 correlation= libmv_SADTrackerTrack(track_context->pattern, track_context->warped,
1458                                                         track_context->pattern_size, image_new, width, width, height, warp);
1459
1460                                 x2= warp[2][0];
1461                                 y2= warp[2][1];
1462
1463                                 tracked= track->minimum_correlation < correlation;
1464
1465                                 if(tracked)
1466                                         get_warped(track_context, x2, y2, width, image_new);
1467
1468                                 MEM_freeN(image_new);
1469                         }
1470
1471                         if(tracked && !onbound && finite(x2) && finite(y2)) {
1472                                 if(context->first_time) {
1473                                         #pragma omp critical
1474                                         {
1475                                                 /* check if there's no keyframe/tracked markers before tracking marker.
1476                                                    if so -- create disabled marker before currently tracking "segment" */
1477                                                 put_disabled_marker(track, marker, !context->backwards, 0);
1478                                         }
1479                                 }
1480
1481                                 memset(&marker_new, 0, sizeof(marker_new));
1482
1483                                 if(!onbound) {
1484                                         marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
1485                                         marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
1486                                 } else {
1487                                         copy_v2_v2(marker_new.pos, marker->pos);
1488                                 }
1489
1490                                 marker_new.flag|= MARKER_TRACKED;
1491                                 marker_new.framenr= nextfra;
1492
1493                                 #pragma omp critical
1494                                 {
1495                                         BKE_tracking_insert_marker(track, &marker_new);
1496                                 }
1497
1498                                 /* make currently tracked segment be finished with disabled marker */
1499                                 #pragma omp critical
1500                                 {
1501                                         put_disabled_marker(track, &marker_new, context->backwards, 0);
1502                                 }
1503                         } else {
1504                                 marker_new= *marker;
1505
1506                                 marker_new.framenr= nextfra;
1507                                 marker_new.flag|= MARKER_DISABLED;
1508
1509                                 #pragma omp critical
1510                                 {
1511                                         BKE_tracking_insert_marker(track, &marker_new);
1512                                 }
1513                         }
1514
1515                         ok= 1;
1516 #endif
1517                 }
1518         }
1519
1520         IMB_freeImBuf(ibuf_new);
1521
1522         context->first_time= 0;
1523         context->frames++;
1524
1525         return ok;
1526 }
1527
1528 /*********************** camera solving *************************/
1529
1530 typedef struct MovieReconstructContext {
1531 #ifdef WITH_LIBMV
1532         struct libmv_Tracks *tracks;
1533         int keyframe1, keyframe2;
1534         short refine_flags;
1535
1536         struct libmv_Reconstruction *reconstruction;
1537 #endif
1538         char object_name[MAX_NAME];
1539         int is_camera;
1540
1541         float focal_length;
1542         float principal_point[2];
1543         float k1, k2, k3;
1544
1545         float reprojection_error;
1546
1547         TracksMap *tracks_map;
1548
1549         int sfra, efra;
1550 } MovieReconstructContext;
1551
1552 typedef struct ReconstructProgressData {
1553         short *stop;
1554         short *do_update;
1555         float *progress;
1556         char *stats_message;
1557         int message_size;
1558 } ReconstructProgressData;
1559
1560 #if WITH_LIBMV
1561 static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height)
1562 {
1563         int tracknr= 0;
1564         MovieTrackingTrack *track;
1565         struct libmv_Tracks *tracks= libmv_tracksNew();
1566
1567         track= tracksbase->first;
1568         while(track) {
1569                 int a= 0;
1570
1571                 for(a= 0; a<track->markersnr; a++) {
1572                         MovieTrackingMarker *marker= &track->markers[a];
1573
1574                         if((marker->flag&MARKER_DISABLED)==0)
1575                                 libmv_tracksInsert(tracks, marker->framenr, tracknr,
1576                                                         marker->pos[0]*width, marker->pos[1]*height);
1577                 }
1578
1579                 track= track->next;
1580                 tracknr++;
1581         }
1582
1583         return tracks;
1584 }
1585
1586 static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *context, MovieTracking *tracking)
1587 {
1588         struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
1589         struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction);
1590
1591         float aspy= 1.0f/tracking->camera.pixel_aspect;
1592
1593         double focal_length, principal_x, principal_y, k1, k2, k3;
1594         int width, height;
1595
1596         libmv_CameraIntrinsicsExtract(libmv_intrinsics, &focal_length, &principal_x, &principal_y,
1597                         &k1, &k2, &k3, &width, &height);
1598
1599         tracking->camera.focal= focal_length;
1600         tracking->camera.principal[0]= principal_x;
1601
1602         /* todo: verify divide by aspy is correct */
1603         tracking->camera.principal[1]= principal_y / aspy;
1604         tracking->camera.k1= k1;
1605         tracking->camera.k2= k2;
1606 }
1607
1608 static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking)
1609 {
1610         struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
1611         MovieTrackingReconstruction *reconstruction= NULL;
1612         MovieReconstructedCamera *reconstructed;
1613         MovieTrackingTrack *track;
1614         ListBase *tracksbase=  NULL;
1615         int ok= 1, tracknr= 0, a, origin_set= 0;
1616         int sfra= context->sfra, efra= context->efra;
1617         float imat[4][4];
1618
1619         if(context->is_camera) {
1620                 tracksbase= &tracking->tracks;
1621                 reconstruction= &tracking->reconstruction;
1622         }
1623         else {
1624                 MovieTrackingObject *object= BKE_tracking_named_object(tracking, context->object_name);
1625
1626                 tracksbase= &object->tracks;
1627                 reconstruction= &object->reconstruction;
1628         }
1629
1630         unit_m4(imat);
1631
1632         track= tracksbase->first;
1633         while(track) {
1634                 double pos[3];
1635
1636                 if(libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
1637                         track->bundle_pos[0]= pos[0];
1638                         track->bundle_pos[1]= pos[1];
1639                         track->bundle_pos[2]= pos[2];
1640
1641                         track->flag|= TRACK_HAS_BUNDLE;
1642                         track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
1643                 } else {
1644                         track->flag&= ~TRACK_HAS_BUNDLE;
1645                         ok= 0;
1646
1647                         printf("No bundle for track #%d '%s'\n", tracknr, track->name);
1648                 }
1649
1650                 track= track->next;
1651                 tracknr++;
1652         }
1653
1654         if(reconstruction->cameras)
1655                 MEM_freeN(reconstruction->cameras);
1656
1657         reconstruction->camnr= 0;
1658         reconstruction->cameras= NULL;
1659         reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
1660
1661         for(a= sfra; a<=efra; a++) {
1662                 double matd[4][4];
1663
1664                 if(libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
1665                         int i, j;
1666                         float mat[4][4];
1667                         float error= libmv_reporojectionErrorForImage(libmv_reconstruction, a);
1668
1669                         for(i=0; i<4; i++)
1670                                 for(j= 0; j<4; j++)
1671                                         mat[i][j]= matd[i][j];
1672
1673                         if(!origin_set) {
1674                                 copy_m4_m4(imat, mat);
1675                                 invert_m4(imat);
1676                                 origin_set= 1;
1677                         }
1678
1679                         if(origin_set)
1680                                 mult_m4_m4m4(mat, imat, mat);
1681
1682                         copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
1683                         reconstructed[reconstruction->camnr].framenr= a;
1684                         reconstructed[reconstruction->camnr].error= error;
1685                         reconstruction->camnr++;
1686                 } else {
1687                         ok= 0;
1688                         printf("No camera for frame %d\n", a);
1689                 }
1690         }
1691
1692         if(reconstruction->camnr) {
1693                 reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
1694                 memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera));
1695         }
1696
1697         if(origin_set) {
1698                 track= tracksbase->first;
1699                 while(track) {
1700                         if(track->flag&TRACK_HAS_BUNDLE)
1701                                 mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos);
1702
1703                         track= track->next;
1704                 }
1705         }
1706
1707         MEM_freeN(reconstructed);
1708
1709         return ok;
1710 }
1711
1712 static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking)
1713 {
1714         /* take the intrinscis back from libmv */
1715         retrieve_libmv_reconstruct_intrinscis(context, tracking);
1716
1717         return retrieve_libmv_reconstruct_tracks(context, tracking);
1718 }
1719
1720 static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object)
1721 {
1722         int refine= tracking->settings.refine_camera_intrinsics;
1723         int flags= 0;
1724
1725         if((object->flag&TRACKING_OBJECT_CAMERA)==0)
1726                 return 0;
1727
1728         if(refine&REFINE_FOCAL_LENGTH)
1729                 flags|= LIBMV_REFINE_FOCAL_LENGTH;
1730
1731         if(refine&REFINE_PRINCIPAL_POINT)
1732                 flags|= LIBMV_REFINE_PRINCIPAL_POINT;
1733
1734         if(refine&REFINE_RADIAL_DISTORTION_K1)
1735                 flags|= REFINE_RADIAL_DISTORTION_K1;
1736
1737         if(refine&REFINE_RADIAL_DISTORTION_K2)
1738                 flags|= REFINE_RADIAL_DISTORTION_K2;
1739
1740         return flags;
1741 }
1742
1743 static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase)
1744 {
1745         int tot= 0;
1746         int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2;
1747         MovieTrackingTrack *track;
1748
1749         track= tracksbase->first;
1750         while(track) {
1751                 if(BKE_tracking_has_enabled_marker(track, frame1))
1752                         if(BKE_tracking_has_enabled_marker(track, frame2))
1753                                 tot++;
1754
1755                 track= track->next;
1756         }
1757
1758         return tot;
1759 }
1760 #endif
1761
1762 int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
1763 {
1764 #if WITH_LIBMV
1765         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
1766
1767         if(count_tracks_on_both_keyframes(tracking, tracksbase)<8) {
1768                 BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction", error_size);
1769                 return 0;
1770         }
1771
1772         return 1;
1773 #else
1774         BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size);
1775         (void)tracking;
1776         (void)object;
1777
1778         return 0;
1779 #endif
1780 }
1781
1782 MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking,
1783                         MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height)
1784 {
1785         MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
1786         MovieTrackingCamera *camera= &tracking->camera;
1787         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
1788         float aspy= 1.0f/tracking->camera.pixel_aspect;
1789         int num_tracks= BLI_countlist(tracksbase);
1790         int sfra= INT_MAX, efra= INT_MIN;
1791         MovieTrackingTrack *track;
1792
1793         BLI_strncpy(context->object_name, object->name, sizeof(context->object_name));
1794         context->is_camera = object->flag&TRACKING_OBJECT_CAMERA;
1795
1796         context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
1797
1798         track= tracksbase->first;
1799         while(track) {
1800                 int first= 0, last= track->markersnr-1;
1801                 MovieTrackingMarker *first_marker= &track->markers[0];
1802                 MovieTrackingMarker *last_marker= &track->markers[track->markersnr-1];
1803
1804                 /* find first not-disabled marker */
1805                 while(first<=track->markersnr-1 && first_marker->flag&MARKER_DISABLED) {
1806                         first++;
1807                         first_marker++;
1808                 }
1809
1810                 /* find last not-disabled marker */
1811                 while(last>=0 && last_marker->flag&MARKER_DISABLED) {
1812                         last--;
1813                         last_marker--;
1814                 }
1815
1816                 if(first<track->markersnr-1)
1817                         sfra= MIN2(sfra, first_marker->framenr);
1818
1819                 if(last>=0)
1820                         efra= MAX2(efra, last_marker->framenr);
1821
1822                 tracks_map_insert(context->tracks_map, track, NULL);
1823
1824                 track= track->next;
1825         }
1826
1827         context->sfra= sfra;
1828         context->efra= efra;
1829
1830 #ifdef WITH_LIBMV
1831         context->tracks= create_libmv_tracks(tracksbase, width, height*aspy);
1832         context->keyframe1= keyframe1;
1833         context->keyframe2= keyframe2;
1834         context->refine_flags= get_refine_intrinsics_flags(tracking, object);
1835 #else
1836         (void) width;
1837         (void) height;
1838         (void) keyframe1;
1839         (void) keyframe2;
1840 #endif
1841
1842         context->focal_length= camera->focal;
1843         context->principal_point[0]= camera->principal[0];
1844         context->principal_point[1]= camera->principal[1]*aspy;
1845
1846         context->k1= camera->k1;
1847         context->k2= camera->k2;
1848         context->k3= camera->k3;
1849
1850         return context;
1851 }
1852
1853 void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context)
1854 {
1855 #ifdef WITH_LIBMV
1856         if(context->reconstruction)
1857                         libmv_destroyReconstruction(context->reconstruction);
1858
1859         libmv_tracksDestroy(context->tracks);
1860 #endif
1861
1862         tracks_map_free(context->tracks_map, NULL);
1863
1864         MEM_freeN(context);
1865 }
1866
1867 #ifdef WITH_LIBMV
1868 static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message)
1869 {
1870         ReconstructProgressData *progressdata= customdata;
1871
1872         if(progressdata->progress) {
1873                 *progressdata->progress= progress;
1874                 *progressdata->do_update= 1;
1875         }
1876
1877         BLI_snprintf(progressdata->stats_message, progressdata->message_size,
1878                         "Solving camera | %s", message);
1879 }
1880 #endif
1881
1882 #if 0
1883 static int solve_reconstruction_testbreak_cb(void *customdata)
1884 {
1885         ReconstructProgressData *progressdata= customdata;
1886
1887         if(progressdata->stop && *progressdata->stop)
1888                 return 1;
1889
1890         return G.afbreek;
1891 }
1892 #endif
1893
1894 void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop,
1895                         short *do_update, float *progress, char *stats_message, int message_size)
1896 {
1897 #ifdef WITH_LIBMV
1898         float error;
1899
1900         ReconstructProgressData progressdata;
1901
1902         progressdata.stop= stop;
1903         progressdata.do_update= do_update;
1904         progressdata.progress= progress;
1905         progressdata.stats_message= stats_message;
1906         progressdata.message_size= message_size;
1907
1908         context->reconstruction = libmv_solveReconstruction(context->tracks,
1909                 context->keyframe1, context->keyframe2,
1910                 context->refine_flags,
1911                 context->focal_length,
1912                 context->principal_point[0], context->principal_point[1],
1913                 context->k1, context->k2, context->k3,
1914                 solve_reconstruction_update_cb, &progressdata);
1915
1916         error= libmv_reprojectionError(context->reconstruction);
1917
1918         context->reprojection_error= error;
1919 #else
1920         (void) context;
1921         (void) stop;
1922         (void) do_update;
1923         (void) progress;
1924         (void) stats_message;
1925         (void) message_size;
1926 #endif
1927 }
1928
1929 int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking)
1930 {
1931         MovieTrackingReconstruction *reconstruction;
1932
1933         tracks_map_merge(context->tracks_map, tracking);
1934
1935         if(context->is_camera) {
1936                 reconstruction= &tracking->reconstruction;
1937         }
1938         else {
1939                 MovieTrackingObject *object;
1940
1941                 object= BKE_tracking_named_object(tracking, context->object_name);
1942                 reconstruction= &object->reconstruction;
1943         }
1944
1945         reconstruction->error= context->reprojection_error;
1946         reconstruction->flag|= TRACKING_RECONSTRUCTED;
1947
1948 #ifdef WITH_LIBMV
1949         if(!retrieve_libmv_reconstruct(context, tracking))
1950                 return 0;
1951 #endif
1952
1953         return 1;
1954 }
1955
1956 void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
1957 {
1958         BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1959 }
1960
1961 MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
1962 {
1963         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
1964         MovieTrackingTrack *track= tracksbase->first;
1965
1966         while(track) {
1967                 if(!strcmp(track->name, name))
1968                         return track;
1969
1970                 track= track->next;
1971         }
1972
1973         return NULL;
1974 }
1975
1976 static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest)
1977 {
1978         MovieReconstructedCamera *cameras= reconstruction->cameras;
1979         int a= 0, d= 1;
1980
1981         if(!reconstruction->camnr)
1982                 return -1;
1983
1984         if(framenr<cameras[0].framenr) {
1985                 if(nearest) return 0;
1986                 else return -1;
1987         }
1988
1989         if(framenr>cameras[reconstruction->camnr-1].framenr) {
1990                 if(nearest) return reconstruction->camnr-1;
1991                 else return -1;
1992         }
1993
1994         if(reconstruction->last_camera<reconstruction->camnr)
1995                 a= reconstruction->last_camera;
1996
1997         if(cameras[a].framenr>=framenr)
1998                 d= -1;
1999
2000         while(a>=0 && a<reconstruction->camnr) {
2001                 int cfra= cameras[a].framenr;
2002
2003                 /* check if needed framenr was "skipped" -- no data for requested frame */
2004
2005                 if(d>0 && cfra>framenr) {
2006                         /* interpolate with previous position */
2007                         if(nearest) return a-1;
2008                         else break;
2009                 }
2010
2011                 if(d<0 && cfra<framenr) {
2012                         /* interpolate with next position */
2013                         if(nearest) return a;
2014                         else break;
2015                 }
2016
2017                 if(cfra==framenr) {
2018                         reconstruction->last_camera= a;
2019
2020                         return a;
2021                 }
2022
2023                 a+= d;
2024         }
2025
2026         return -1;
2027 }
2028
2029 static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4])
2030 {
2031         if((object->flag&TRACKING_OBJECT_CAMERA)==0) {
2032                 float smat[4][4];
2033
2034                 scale_m4_fl(smat, 1.0f/object->scale);
2035                 mult_m4_m4m4(mat, mat, smat);
2036         }
2037 }
2038
2039 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking,
2040                         MovieTrackingObject *object, int framenr)
2041 {
2042         MovieTrackingReconstruction *reconstruction;
2043         int a;
2044
2045         reconstruction= BKE_tracking_object_reconstruction(tracking, object);
2046         a= reconstruction_camera_index(reconstruction, framenr, 0);
2047
2048         if(a==-1)
2049                 return NULL;
2050
2051         return &reconstruction->cameras[a];
2052 }
2053
2054 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object,
2055                         int framenr, float mat[4][4])
2056 {
2057         MovieTrackingReconstruction *reconstruction;
2058         MovieReconstructedCamera *cameras;
2059         int a;
2060
2061         reconstruction= BKE_tracking_object_reconstruction(tracking, object);
2062         cameras= reconstruction->cameras;
2063         a= reconstruction_camera_index(reconstruction, framenr, 1);
2064
2065         if(a==-1) {
2066                 unit_m4(mat);
2067                 return;
2068         }
2069
2070         if(cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) {
2071                 float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr);
2072
2073                 blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t);
2074         } else {
2075                 copy_m4_m4(mat, cameras[a].mat);
2076         }
2077
2078         scale_reconstructed_camera(object, mat);
2079 }
2080
2081 void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4])
2082 {
2083         if(!ob) {
2084                 if(scene->camera) ob= scene->camera;
2085                 else ob= scene_find_camera(scene);
2086         }
2087
2088         if(ob)
2089                 where_is_object_mat(scene, ob, mat);
2090         else
2091                 unit_m4(mat);
2092 }
2093
2094 void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
2095 {
2096         *shiftx= (0.5f*winx-tracking->camera.principal[0]) / winx;
2097         *shifty= (0.5f*winy-tracking->camera.principal[1]) / winx;
2098 }
2099
2100 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
2101 {
2102         float focal= tracking->camera.focal;
2103
2104         camera->sensor_x= tracking->camera.sensor_width;
2105         camera->sensor_fit= CAMERA_SENSOR_FIT_AUTO;
2106         camera->lens= focal*camera->sensor_x/width;
2107
2108         scene->r.xsch= width*tracking->camera.pixel_aspect;
2109         scene->r.ysch= height;
2110
2111         scene->r.xasp= 1.0f;
2112         scene->r.yasp= 1.0f;
2113
2114         BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
2115 }
2116
2117 void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
2118                         int framenr, int winx, int winy, float mat[4][4])
2119 {
2120         MovieReconstructedCamera *camera;
2121         float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
2122         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
2123         float winmat[4][4];
2124         float ycor= 1.0f/tracking->camera.pixel_aspect;
2125         float shiftx, shifty, winside= MAX2(winx, winy);
2126
2127         BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty);
2128
2129         clipsta= 0.1f;
2130         clipend= 1000.0f;
2131
2132         if(winx >= winy)
2133                 viewfac= (lens*winx)/tracking->camera.sensor_width;
2134         else
2135                 viewfac= (ycor*lens*winy)/tracking->camera.sensor_width;
2136
2137         pixsize= clipsta/viewfac;
2138
2139         left= -0.5f*(float)winx + shiftx*winside;
2140         bottom= -0.5f*(ycor)*(float)winy + shifty*winside;
2141         right=  0.5f*(float)winx + shiftx*winside;
2142         top=  0.5f*(ycor)*(float)winy + shifty*winside;
2143
2144         left *= pixsize;
2145         right *= pixsize;
2146         bottom *= pixsize;
2147         top *= pixsize;
2148
2149         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
2150
2151         camera= BKE_tracking_get_reconstructed_camera(tracking, object, framenr);
2152
2153         if(camera) {
2154                 float imat[4][4];
2155
2156                 invert_m4_m4(imat, camera->mat);
2157                 mult_m4_m4m4(mat, winmat, imat);
2158         } else copy_m4_m4(mat, winmat);
2159 }
2160
2161 ListBase *BKE_tracking_get_tracks(MovieTracking *tracking)
2162 {
2163         MovieTrackingObject *object= BKE_tracking_active_object(tracking);
2164
2165         if(object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
2166                 return &object->tracks;
2167         }
2168
2169         return &tracking->tracks;
2170 }
2171
2172 MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking)
2173 {
2174         ListBase *tracksbase;
2175
2176         if(!tracking->act_track)
2177                 return NULL;
2178
2179         tracksbase= BKE_tracking_get_tracks(tracking);
2180
2181         /* check that active track is in current tracks list */
2182         if(BLI_findindex(tracksbase, tracking->act_track) >= 0)
2183                 return tracking->act_track;
2184
2185         return NULL;
2186 }
2187
2188 MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking)
2189 {
2190         return BLI_findlink(&tracking->objects, tracking->objectnr);
2191 }
2192
2193 MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking)
2194 {
2195         MovieTrackingObject *object= tracking->objects.first;
2196
2197         while(object) {
2198                 if(object->flag & TRACKING_OBJECT_CAMERA)
2199                         return object;
2200
2201                 object= object->next;
2202         }
2203
2204         return NULL;
2205 }
2206
2207 ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object)
2208 {
2209         if(object->flag & TRACKING_OBJECT_CAMERA) {
2210                 return &tracking->tracks;
2211         }
2212
2213         return &object->tracks;
2214 }
2215
2216 MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object)
2217 {
2218         if(object->flag & TRACKING_OBJECT_CAMERA) {
2219                 return &tracking->reconstruction;
2220         }
2221
2222         return &object->reconstruction;
2223 }
2224
2225 MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking)
2226 {
2227         MovieTrackingObject *object= BKE_tracking_active_object(tracking);
2228
2229         return BKE_tracking_object_reconstruction(tracking, object);
2230 }
2231
2232 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
2233 {
2234         MovieTrackingCamera *camera= &tracking->camera;
2235
2236 #ifdef WITH_LIBMV
2237         double x, y;
2238         float aspy= 1.0f/tracking->camera.pixel_aspect;
2239
2240         /* normalize coords */
2241         x= (co[0]-camera->principal[0]) / camera->focal;
2242         y= (co[1]-camera->principal[1] * aspy) / camera->focal;
2243
2244         libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
2245                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
2246
2247         /* result is in image coords already */
2248         nco[0]= x;
2249         nco[1]= y;
2250 #else
2251         (void)camera;
2252         (void)co;
2253         (void)nco;
2254 #endif
2255 }
2256
2257 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
2258 {
2259         MovieTrackingCamera *camera= &tracking->camera;
2260
2261 #ifdef WITH_LIBMV
2262         double x= co[0], y= co[1];
2263         float aspy= 1.0f/tracking->camera.pixel_aspect;
2264
2265         libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
2266                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
2267
2268         nco[0]= x * camera->focal + camera->principal[0];
2269         nco[1]= y * camera->focal + camera->principal[1] * aspy;
2270 #else
2271         (void)camera;
2272         (void)co;
2273         (void)nco;
2274 #endif
2275 }
2276
2277 #ifdef WITH_LIBMV
2278 static int point_in_stroke(bGPDstroke *stroke, float x, float y)
2279 {
2280         int i, prev;
2281         int count= 0;
2282         bGPDspoint *points= stroke->points;
2283
2284         prev= stroke->totpoints-1;
2285
2286         for(i= 0; i<stroke->totpoints; i++) {
2287                 if((points[i].y<y && points[prev].y>=y) || (points[prev].y<y && points[i].y>=y)) {
2288                         float fac= (y-points[i].y)/(points[prev].y-points[i].y);
2289
2290                         if (points[i].x+fac*(points[prev].x-points[i].x)<x)
2291                                 count++;
2292                 }
2293
2294                 prev= i;
2295         }
2296
2297         return count%2;
2298 }
2299
2300 static int point_in_layer(bGPDlayer *layer, float x, float y)
2301 {
2302         bGPDframe *frame= layer->frames.first;
2303
2304         while(frame) {
2305                 bGPDstroke *stroke= frame->strokes.first;
2306                 while(stroke) {
2307                         if(point_in_stroke(stroke, x, y))
2308                                 return 1;
2309
2310                         stroke= stroke->next;
2311                 }
2312                 frame= frame->next;
2313         }
2314
2315         return 0;
2316 }
2317
2318 static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
2319                         struct libmv_Features *features, int framenr, int width, int height,
2320                         bGPDlayer *layer, int place_outside_layer)
2321 {
2322         int a;
2323
2324         a= libmv_countFeatures(features);
2325         while(a--) {
2326                 MovieTrackingTrack *track;
2327                 double x, y, size, score;
2328                 int ok= 1;
2329                 float xu, yu;
2330
2331                 libmv_getFeature(features, a, &x, &y, &score, &size);
2332
2333                 xu= x/width;
2334                 yu= y/height;
2335
2336                 if(layer)
2337                         ok= point_in_layer(layer, xu, yu)!=place_outside_layer;
2338
2339                 if(ok) {
2340                         track= BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height);
2341                         track->flag|= SELECT;
2342                         track->pat_flag|= SELECT;
2343                         track->search_flag|= SELECT;
2344                 }
2345         }
2346 }
2347 #endif
2348
2349 void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
2350                         int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
2351                         int place_outside_layer)
2352 {
2353 #ifdef WITH_LIBMV
2354         struct libmv_Features *features;
2355         unsigned char *pixels= get_ucharbuf(ibuf);
2356
2357         features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
2358                         margin, min_trackness, min_distance);
2359
2360         MEM_freeN(pixels);
2361
2362         retrieve_libmv_features(tracking, tracksbase, features, framenr,
2363                         ibuf->x, ibuf->y, layer, place_outside_layer);
2364
2365         libmv_destroyFeatures(features);
2366 #else
2367         (void)tracking;
2368         (void)tracksbase;
2369         (void)ibuf;
2370         (void)framenr;
2371         (void)margin;
2372         (void)min_trackness;
2373         (void)min_distance;
2374         (void)layer;
2375         (void)place_outside_layer;
2376 #endif
2377 }
2378
2379 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
2380 {
2381         MovieTrackingObject *object;
2382         int cur= 1;
2383
2384         object= tracking->objects.first;
2385         while(object) {
2386                 ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
2387                 MovieTrackingTrack *track= tracksbase->first;
2388
2389                 while(track) {
2390                         if(track->flag&TRACK_HAS_BUNDLE) {
2391                                 if(cur==tracknr) {
2392                                         *tracksbase_r= tracksbase;
2393                                         return track;
2394                                 }
2395
2396                                 cur++;
2397                         }
2398
2399                         track= track->next;
2400                 }
2401
2402                 object= object->next;
2403         }
2404
2405         *tracksbase_r= NULL;
2406
2407         return NULL;
2408 }
2409
2410 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
2411 {
2412         int ok= 0;
2413         float min[2], max[2];
2414         MovieTrackingTrack *track;
2415
2416         INIT_MINMAX2(min, max);
2417
2418         (void) tracking;
2419
2420         track= tracking->tracks.first;
2421         while(track) {
2422                 if(track->flag&TRACK_USE_2D_STAB) {
2423                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
2424
2425                         DO_MINMAX2(marker->pos, min, max);
2426
2427                         ok= 1;
2428                 }
2429
2430                 track= track->next;
2431         }
2432
2433         median[0]= (max[0]+min[0])/2.0f;
2434         median[1]= (max[1]+min[1])/2.0f;
2435
2436         return ok;
2437 }
2438
2439 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
2440                         float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
2441 {
2442         MovieTrackingStabilization *stab= &tracking->stabilization;
2443
2444         *scale= (stab->scale-1.0f)*stab->scaleinf+1.0f;
2445         *angle= 0.0f;
2446
2447         loc[0]= (firstmedian[0]-median[0])*width*(*scale);
2448         loc[1]= (firstmedian[1]-median[1])*height*(*scale);
2449
2450         mul_v2_fl(loc, stab->locinf);
2451
2452         if((stab->flag&TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) {
2453                 MovieTrackingMarker *marker;
2454                 float a[2], b[2];
2455                 float x0= (float)width/2.0f, y0= (float)height/2.0f;
2456                 float x= median[0]*width, y= median[1]*height;
2457
2458                 marker= BKE_tracking_get_marker(stab->rot_track, 1);
2459                 sub_v2_v2v2(a, marker->pos, firstmedian);
2460                 a[0]*= width;
2461                 a[1]*= height;
2462
2463                 marker= BKE_tracking_get_marker(stab->rot_track, framenr);
2464                 sub_v2_v2v2(b, marker->pos, median);
2465                 b[0]*= width;
2466                 b[1]*= height;
2467
2468                 *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]);
2469                 *angle*= stab->rotinf;
2470
2471                 /* convert to rotation around image center */
2472                 loc[0]-= (x0 + (x-x0)*cosf(*angle)-(y-y0)*sinf(*angle) - x)*(*scale);
2473                 loc[1]-= (y0 + (x-x0)*sinf(*angle)+(y-y0)*cosf(*angle) - y)*(*scale);
2474         }
2475 }
2476
2477 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
2478 {
2479         float firstmedian[2];
2480         MovieTrackingStabilization *stab= &tracking->stabilization;
2481
2482         if(stab->ok)
2483                 return stab->scale;
2484
2485         if(stabilization_median_point(tracking, 1, firstmedian)) {
2486                 int sfra= INT_MAX, efra= INT_MIN, cfra;
2487                 float delta[2]= {0.0f, 0.0f}, scalex= 1.0f, scaley= 1.0f;
2488                 MovieTrackingTrack *track;
2489
2490                 stab->scale= 1.0f;
2491
2492                 track= tracking->tracks.first;
2493                 while(track) {
2494                         if(track->flag&TRACK_USE_2D_STAB ||
2495                            ((stab->flag&TRACKING_STABILIZE_ROTATION) && track==stab->rot_track)) {
2496                                 sfra= MIN2(sfra, track->markers[0].framenr);
2497                                 efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
2498                         }
2499
2500                         track= track->next;
2501                 }
2502
2503                 for(cfra=sfra; cfra<=efra; cfra++) {
2504                         float median[2], near[2];
2505                         float loc[2], scale, angle;
2506
2507                         stabilization_median_point(tracking, cfra, median);
2508
2509                         calculate_stabdata(tracking, cfra, width, height, firstmedian, median,
2510                                                 loc, &scale, &angle);
2511
2512                         if(angle==0.0f) {
2513                                 loc[0]= fabsf(loc[0]);
2514                                 loc[1]= fabsf(loc[1]);
2515
2516                                 delta[0]= MAX2(delta[0], loc[0]);
2517                                 delta[1]= MAX2(delta[1], loc[1]);
2518
2519                                 near[0]= MIN2(median[0], 1.0f-median[0]);
2520                                 near[1]= MIN2(median[1], 1.0f-median[1]);
2521                                 near[0]= MAX2(near[0], 0.05f);
2522                                 near[1]= MAX2(near[1], 0.05f);
2523
2524                                 scalex= 1.0f+delta[0]/(near[0]*width);
2525                                 scaley= 1.0f+delta[1]/(near[1]*height);
2526                         } else {
2527                                 int i;
2528                                 float mat[4][4];
2529                                 float points[4][2]={{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}};
2530
2531                                 BKE_tracking_stabdata_to_mat4(width, height, loc, scale, angle, mat);
2532
2533                                 for(i= 0; i<4; i++) {
2534                                         int j;
2535                                         float a[3]= {0.0f, 0.0f, 0.0f}, b[3]= {0.0f, 0.0f, 0.0f};
2536
2537                                         copy_v3_v3(a, points[i]);
2538                                         copy_v3_v3(b, points[(i+1)%4]);
2539
2540                                         mul_m4_v3(mat, a);
2541                                         mul_m4_v3(mat, b);
2542
2543                                         for(j= 0; j<4; j++) {
2544                                                 float point[3]= {points[j][0], points[j][1], 0.0f};
2545                                                 float v1[3], v2[3];
2546
2547                                                 sub_v3_v3v3(v1, b, a);
2548                                                 sub_v3_v3v3(v2, point, a);
2549
2550                                                 if(cross_v2v2(v1, v2) >= 0.0f) {
2551                                                         float dist= dist_to_line_v2(point, a, b);
2552                                                         if(i%2==0) {
2553                                                                 scalex= MAX2(scalex, (width+2*dist)/width);
2554                                                         } else {
2555                                                                 scaley= MAX2(scaley, (height+2*dist)/height);
2556                                                         }
2557                                                 }
2558                                         }
2559                                 }
2560                         }
2561                 }
2562
2563                 stab->scale= MAX2(scalex, scaley);
2564
2565                 if(stab->maxscale>0.0f)
2566                         stab->scale= MIN2(stab->scale, stab->maxscale);
2567         } else {
2568                 stab->scale= 1.0f;
2569         }
2570
2571         stab->ok= 1;
2572
2573         return stab->scale;
2574 }
2575
2576 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
2577 {
2578         int flags;
2579
2580         if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
2581                 IMB_freeImBuf(cacheibuf);
2582                 cacheibuf= NULL;
2583         }
2584
2585         flags= IB_rect;
2586
2587         if(srcibuf->rect_float)
2588                 flags|= IB_rectfloat;
2589
2590         if(cacheibuf) {
2591                 if(fill) {
2592                         float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
2593                         IMB_rectfill(cacheibuf, col);
2594                 }
2595         }
2596         else {
2597                 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags);
2598                 cacheibuf->profile= srcibuf->profile;
2599         }
2600
2601         return cacheibuf;
2602 }
2603
2604 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle)
2605 {
2606         float firstmedian[2], median[2];
2607         MovieTrackingStabilization *stab= &tracking->stabilization;
2608
2609         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
2610                 zero_v2(loc);
2611                 *scale= 1.0f;
2612                 *angle= 0.0f;
2613
2614                 return;
2615         }
2616
2617         if(stabilization_median_point(tracking, 1, firstmedian)) {
2618                 stabilization_median_point(tracking, framenr, median);
2619
2620                 if((stab->flag&TRACKING_AUTOSCALE)==0)
2621                         stab->scale= 1.0f;
2622
2623                 if(!stab->ok) {
2624                         if(stab->flag&TRACKING_AUTOSCALE)
2625                                 stabilization_auto_scale_factor(tracking, width, height);
2626
2627                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
2628
2629                         stab->ok= 1;
2630                 } else {
2631                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
2632                 }
2633         } else {
2634                 zero_v2(loc);
2635                 *scale= 1.0f;
2636                 *angle= 0.0f;
2637         }
2638 }
2639
2640 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle)
2641 {
2642         float tloc[2], tscale, tangle;
2643         MovieTrackingStabilization *stab= &tracking->stabilization;
2644         ImBuf *tmpibuf;
2645         float width= ibuf->x, height= ibuf->y;
2646
2647         if(loc)         copy_v2_v2(tloc, loc);
2648         if(scale)       tscale= *scale;
2649
2650         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
2651                 if(loc)         zero_v2(loc);
2652                 if(scale)       *scale= 1.0f;
2653
2654                 return ibuf;
2655         }
2656
2657         BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
2658
2659         tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1);
2660
2661         /* scale would be handled by matrix transformation when angle is non-zero */
2662         if(tscale!=1.0f && tangle==0.0f) {
2663                 ImBuf *scaleibuf;
2664
2665                 stabilization_auto_scale_factor(tracking, width, height);
2666
2667                 scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
2668                 stab->scaleibuf= scaleibuf;
2669
2670                 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
2671                 IMB_scalefastImBuf(scaleibuf, ibuf->x*tscale, ibuf->y*tscale);
2672
2673                 ibuf= scaleibuf;
2674         }
2675
2676         if(tangle==0.0f) {
2677                 /* if angle is zero, then it's much faster to use rect copy
2678                    but could be issues with subpixel precisions */
2679                 IMB_rectcpy(tmpibuf, ibuf, tloc[0]-(tscale-1.0f)*width/2.0f, tloc[1]-(tscale-1.0f)*height/2.0f, 0, 0, ibuf->x, ibuf->y);
2680         } else {
2681                 float mat[4][4];
2682                 int i, j;
2683
2684                 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, tloc, tscale, tangle, mat);
2685                 invert_m4(mat);
2686
2687                 for(j=0; j<tmpibuf->y; j++) {
2688                         for(i=0; i<tmpibuf->x;i++) {
2689                                 float vec[3]= {i, j, 0};
2690
2691                                 mul_v3_m4v3(vec, mat, vec);
2692
2693                                 /* TODO: add selector for interpolation method */
2694                                 neareast_interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
2695                         }
2696                 }
2697         }
2698
2699         tmpibuf->userflags|= IB_MIPMAP_INVALID;
2700
2701         if(tmpibuf->rect_float)
2702                 tmpibuf->userflags|= IB_RECT_INVALID;
2703
2704         if(loc)         copy_v2_v2(loc, tloc);
2705         if(scale)       *scale= tscale;
2706         if(angle)       *angle= tangle;
2707
2708         return tmpibuf;
2709 }
2710
2711 void BKE_tracking_stabdata_to_mat4(int width, int height, float loc[2], float scale, float angle, float mat[4][4])
2712 {
2713         float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
2714         float svec[3]= {scale, scale, scale};
2715
2716         unit_m4(rmat);
2717         unit_m4(lmat);
2718         unit_m4(smat);
2719         unit_m4(cmat);
2720
2721         /* image center as rotation center */
2722         cmat[3][0]= (float)width/2.0f;
2723         cmat[3][1]= (float)height/2.0f;
2724         invert_m4_m4(icmat, cmat);
2725
2726         size_to_mat4(smat, svec);               /* scale matrix */
2727         add_v2_v2(lmat[3], loc);                /* tranlation matrix */
2728         rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
2729
2730         /* compose transformation matrix */
2731         mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);
2732 }
2733
2734 MovieDistortion *BKE_tracking_distortion_create(void)
2735 {
2736         MovieDistortion *distortion;
2737
2738         distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2739
2740         return distortion;
2741 }
2742
2743 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
2744 {
2745         MovieDistortion *new_distortion;
2746
2747         new_distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2748
2749 #ifdef WITH_LIBMV
2750         new_distortion->intrinsics= libmv_CameraIntrinsicsCopy(distortion->intrinsics);
2751 #else
2752         (void)distortion;
2753 #endif
2754
2755         return new_distortion;
2756 }
2757
2758 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height)
2759 {
2760         MovieTrackingCamera *camera= &tracking->camera;
2761         float aspy= 1.0f/tracking->camera.pixel_aspect;
2762
2763 #ifdef WITH_LIBMV
2764         if(!distortion->intrinsics) {
2765                 distortion->intrinsics= libmv_CameraIntrinsicsNew(camera->focal,
2766                                 camera->principal[0], camera->principal[1] * aspy,
2767                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2768         } else {
2769                 libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
2770                                 camera->principal[0], camera->principal[1] * aspy,
2771                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2772         }
2773 #else
2774         (void)distortion;
2775         (void)width;
2776         (void)height;
2777         (void)camera;
2778         (void)aspy;
2779 #endif
2780 }
2781
2782 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking,
2783                         ImBuf *ibuf, int width, int height, float overscan, int undistort)
2784 {
2785         ImBuf *resibuf;
2786
2787         BKE_tracking_distortion_update(distortion, tracking, width, height);
2788
2789         resibuf= IMB_dupImBuf(ibuf);
2790
2791         if(ibuf->rect_float) {
2792 #ifdef WITH_LIBMV
2793                 if(undistort) {
2794                         libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics,
2795                                                 ibuf->rect_float, resibuf->rect_float,
2796                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2797                 } else {
2798                         libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics,
2799                                                 ibuf->rect_float, resibuf->rect_float,
2800                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2801                 }
2802 #endif
2803
2804                 ibuf->userflags|= IB_RECT_INVALID;
2805         } else {
2806 #ifdef WITH_LIBMV
2807                 if(undistort) {
2808                                 libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics,
2809                                                         (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2810                                                         ibuf->x, ibuf->y, overscan, ibuf->channels);
2811                 } else {
2812                         libmv_CameraIntrinsicsDistortByte(distortion->intrinsics,
2813                                                 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2814                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2815                 }
2816 #endif
2817         }
2818
2819 #ifndef WITH_LIBMV
2820         (void)overscan;
2821         (void)undistort;
2822 #endif
2823
2824         return resibuf;
2825 }
2826
2827 void BKE_tracking_distortion_destroy(MovieDistortion *distortion)
2828 {
2829 #ifdef WITH_LIBMV
2830         libmv_CameraIntrinsicsDestroy(distortion->intrinsics);
2831 #endif
2832
2833         MEM_freeN(distortion);
2834 }
2835
2836 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2837 {
2838         MovieTrackingCamera *camera= &tracking->camera;
2839
2840         if(camera->intrinsics == NULL)
2841                 camera->intrinsics= BKE_tracking_distortion_create();
2842
2843         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1);
2844 }
2845
2846 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2847 {
2848         MovieTrackingCamera *camera= &tracking->camera;
2849
2850         if(camera->intrinsics == NULL)
2851                 camera->intrinsics= BKE_tracking_distortion_create();
2852
2853         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0);
2854 }
2855
2856 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
2857 void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend)
2858 {
2859         if(extend) {
2860                 BKE_tracking_track_flag(track, area, SELECT, 0);
2861         } else {
2862                 MovieTrackingTrack *cur= tracksbase->first;
2863
2864                 while(cur) {
2865                         if(cur==track) {
2866                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2867                                 BKE_tracking_track_flag(cur, area, SELECT, 0);
2868                         }
2869                         else {
2870                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2871                         }
2872
2873                         cur= cur->next;
2874                 }
2875         }
2876 }
2877
2878 void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area)
2879 {
2880         BKE_tracking_track_flag(track, area, SELECT, 1);
2881 }
2882
2883 MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name)
2884 {
2885         MovieTrackingObject *object= MEM_callocN(sizeof(MovieTrackingObject), "tracking object");
2886
2887         if(tracking->tot_object==0) {
2888                 /* first object is always camera */
2889                 BLI_strncpy(object->name, "Camera", sizeof(object->name));
2890
2891                 object->flag|= TRACKING_OBJECT_CAMERA;
2892         }
2893         else {
2894                 BLI_strncpy(object->name, name, sizeof(object->name));
2895         }
2896
2897         BLI_addtail(&tracking->objects, object);
2898
2899         tracking->tot_object++;
2900         tracking->objectnr= BLI_countlist(&tracking->objects) - 1;
2901
2902         BKE_tracking_object_unique_name(tracking, object);
2903
2904         return object;
2905 }
2906
2907 void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object)
2908 {
2909         MovieTrackingTrack *track;
2910         int index= BLI_findindex(&tracking->objects, object);
2911
2912         if(index<0)
2913                 return;
2914
2915         if(object->flag & TRACKING_OBJECT_CAMERA) {
2916                 /* object used for camera solving can't be deleted */
2917                 return;
2918         }
2919
2920         track= object->tracks.first;
2921         while(track) {
2922                 if(track==tracking->act_track)
2923                         tracking->act_track= NULL;
2924
2925                 track= track->next;
2926         }
2927
2928         tracking_object_free(object);
2929         BLI_freelinkN(&tracking->objects, object);
2930
2931         tracking->tot_object--;
2932
2933         if(index>0)
2934                 tracking->objectnr= index-1;
2935         else
2936                 tracking->objectnr= 0;
2937 }
2938
2939 void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
2940 {
2941         BLI_uniquename(&tracking->objects, object, "Object", '.', offsetof(MovieTrackingObject, name), sizeof(object->name));
2942 }
2943
2944 MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name)
2945 {
2946         MovieTrackingObject *object= tracking->objects.first;
2947
2948         while(object) {
2949                 if(!strcmp(object->name, name))
2950                         return object;
2951
2952                 object= object->next;
2953         }
2954
2955         return NULL;
2956 }