Camera tracking integration
[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
51 #include "BKE_global.h"
52 #include "BKE_tracking.h"
53 #include "BKE_movieclip.h"
54 #include "BKE_object.h"
55 #include "BKE_scene.h"
56
57 #include "IMB_imbuf_types.h"
58 #include "IMB_imbuf.h"
59
60 #ifdef WITH_LIBMV
61 #include "libmv-capi.h"
62 #endif
63
64 typedef struct MovieDistortion {
65         struct libmv_CameraIntrinsics *intrinsics;
66 } MovieDistortion;
67
68 /*********************** common functions *************************/
69
70 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
71 {
72         int a;
73         float pat_min[2];
74         float pat_max[2];
75         float max_pyramid_level_factor = 1.0;
76         if (track->tracker == TRACKER_KLT) {
77                 max_pyramid_level_factor = 1 << (track->pyramid_levels - 1);
78         }
79
80         /* sort */
81         for(a= 0; a<2; a++) {
82                 if(track->pat_min[a]>track->pat_max[a])
83                         SWAP(float, track->pat_min[a], track->pat_max[a]);
84
85                 if(track->search_min[a]>track->search_max[a])
86                         SWAP(float, track->search_min[a], track->search_max[a]);
87         }
88
89         /* compute the effective pattern size, which differs from the fine resolution
90          * pattern size for the pyramid KLT tracker */
91         for(a= 0; a<2; a++) {
92                 pat_min[a] = max_pyramid_level_factor * track->pat_min[a];
93                 pat_max[a] = max_pyramid_level_factor * track->pat_max[a];
94         }
95
96         if(event==CLAMP_PAT_DIM) {
97                 for(a= 0; a<2; a++) {
98                         /* search shouldn't be resized smaller than pattern */
99                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
100                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
101                 }
102         }
103         else if(event==CLAMP_PAT_POS) {
104                 float dim[2];
105                 sub_v2_v2v2(dim, track->pat_max, pat_min);
106
107                 for(a= 0; a<2; a++) {
108                         /* pattern shouldn't be moved outside of search */
109                         if(pat_min[a] < track->search_min[a]) {
110                                 track->pat_min[a]= track->search_min[a] - (pat_min[a] - track->pat_min[a]);
111                                 track->pat_max[a]=  (pat_min[a] - track->pat_min[a])+dim[a];
112                         }
113                         if(track->pat_max[a] > track->search_max[a]) {
114                                 track->pat_max[a]= track->search_max[a] - (pat_max[a] - track->pat_max[a]);
115                                 track->pat_min[a]= track->pat_max[a]-dim[a] - (pat_min[a] - track->pat_min[a]);
116                         }
117                 }
118         }
119         else if(event==CLAMP_SEARCH_DIM) {
120                 float max_pyramid_level_factor = 1.0;
121                 if (track->tracker == TRACKER_KLT) {
122                         max_pyramid_level_factor = 1 << (track->pyramid_levels - 1);
123                 }
124                 for(a= 0; a<2; a++) {
125                         /* search shouldn't be resized smaller than pattern */
126                         track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
127                         track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
128                 }
129         }
130         else if(event==CLAMP_SEARCH_POS) {
131                 float dim[2];
132                 sub_v2_v2v2(dim, track->search_max, track->search_min);
133
134                 for(a= 0; a<2; a++) {
135                         /* search shouldn't be moved inside pattern */
136                         if(track->search_min[a] > pat_min[a]) {
137                                 track->search_min[a]= pat_min[a];
138                                 track->search_max[a]= track->search_min[a]+dim[a];
139                         }
140                         if(track->search_max[a] < pat_max[a]) {
141                                 track->search_max[a]= pat_max[a];
142                                 track->search_min[a]= track->search_max[a]-dim[a];
143                         }
144                 }
145         }
146
147         else if(event==CLAMP_PYRAMID_LEVELS || (event==CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT))  {
148                 float dim[2];
149                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
150                 {
151                         float search_ratio = 2.3f * max_pyramid_level_factor;
152
153                         /* resize the search area to something sensible based
154                          * on the number of pyramid levels */
155                         for(a= 0; a<2; a++) {
156                                 track->search_min[a]= search_ratio * track->pat_min[a];
157                                 track->search_max[a]= search_ratio * track->pat_max[a];
158                         }
159                 }
160         }
161
162         /* marker's center should be in center of pattern */
163         if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
164                 float dim[2];
165                 sub_v2_v2v2(dim, track->pat_max, track->pat_min);
166
167                 for(a= 0; a<2; a++) {
168                         track->pat_min[a]= -dim[a]/2.0f;
169                         track->pat_max[a]= dim[a]/2.0f;
170                 }
171         }
172 }
173
174 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
175 {
176         if(area==TRACK_AREA_NONE)
177                 return;
178
179         if(clear) {
180                 if(area&TRACK_AREA_POINT)       track->flag&= ~flag;
181                 if(area&TRACK_AREA_PAT)         track->pat_flag&= ~flag;
182                 if(area&TRACK_AREA_SEARCH)      track->search_flag&= ~flag;
183         } else {
184                 if(area&TRACK_AREA_POINT)       track->flag|= flag;
185                 if(area&TRACK_AREA_PAT)         track->pat_flag|= flag;
186                 if(area&TRACK_AREA_SEARCH)      track->search_flag|= flag;
187         }
188 }
189
190 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, float y,
191                         int framenr, int width, int height)
192 {
193         MovieTrackingTrack *track;
194         MovieTrackingMarker marker;
195
196         /* pick reasonable defaults */
197         float pat[2]= {5.5f, 5.5f}, search[2]= {25.5f, 25.5f}; /* TODO: move to default setting? */
198
199         pat[0] /= (float)width;
200         pat[1] /= (float)height;
201
202         search[0] /= (float)width;
203         search[1] /= (float)height;
204
205         track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
206         strcpy(track->name, "Track");
207
208         /* default to KLT tracker */
209         track->tracker = TRACKER_KLT;
210         track->pyramid_levels = 2;
211
212         /* set SAD defaults even though it's not selected by default */
213         track->minimum_correlation= 0.75f;
214
215         memset(&marker, 0, sizeof(marker));
216         marker.pos[0]= x;
217         marker.pos[1]= y;
218         marker.framenr= framenr;
219
220         copy_v2_v2(track->pat_max, pat);
221         negate_v2_v2(track->pat_min, pat);
222
223         copy_v2_v2(track->search_max, search);
224         negate_v2_v2(track->search_min, search);
225
226         BKE_tracking_insert_marker(track, &marker);
227
228         BLI_addtail(&tracking->tracks, track);
229         BKE_track_unique_name(tracking, track);
230
231         return track;
232 }
233
234 void BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
235 {
236         MovieTrackingMarker *old_marker= BKE_tracking_get_marker(track, marker->framenr);
237
238         if(old_marker && old_marker->framenr==marker->framenr) {
239                 *old_marker= *marker;
240         } else {
241                 int a= track->markersnr;
242
243                 while(a--) {
244                         if(track->markers[a].framenr<marker->framenr)
245                                 break;
246                 }
247
248                 track->markersnr++;
249
250                 if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
251                 else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
252
253                 memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
254                 track->markers[a+1]= *marker;
255
256                 track->last_marker= a+1;
257         }
258 }
259
260 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
261 {
262         int a= 0;
263
264         while(a<track->markersnr) {
265                 if(track->markers[a].framenr==framenr) {
266                         if(track->markersnr>1) {
267                                 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
268                                 track->markersnr--;
269                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
270                         } else {
271                                 MEM_freeN(track->markers);
272                                 track->markers= NULL;
273                                 track->markersnr= 0;
274                         }
275
276                         break;
277                 }
278
279                 a++;
280         }
281 }
282
283 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
284 {
285         int a= track->markersnr-1;
286
287         if(!track->markersnr)
288                 return NULL;
289
290         /* approximate pre-first framenr marker with first marker */
291         if(framenr<track->markers[0].framenr)
292                 return &track->markers[0];
293
294         if(track->last_marker<track->markersnr)
295                 a= track->last_marker;
296
297         if(track->markers[a].framenr<=framenr) {
298                 while(a<track->markersnr && track->markers[a].framenr<=framenr) {
299                         if(track->markers[a].framenr==framenr) {
300                                 track->last_marker= a;
301                                 return &track->markers[a];
302                         }
303                         a++;
304                 }
305
306                 /* if there's no marker for exact position, use nearest marker from left side */
307                 return &track->markers[a-1];
308         } else {
309                 while(a>=0 && track->markers[a].framenr>=framenr) {
310                         if(track->markers[a].framenr==framenr) {
311                                 track->last_marker= a;
312                                 return &track->markers[a];
313                         }
314
315                         a--;
316                 }
317
318                 /* if there's no marker for exact position, use nearest marker from left side */
319                 return &track->markers[a];
320         }
321
322         return NULL;
323 }
324
325 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
326 {
327         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
328
329         if(marker && marker->framenr!=framenr) {
330                 MovieTrackingMarker marker_new;
331
332                 marker_new= *marker;
333                 marker_new.framenr= framenr;
334
335                 BKE_tracking_insert_marker(track, &marker_new);
336                 marker= BKE_tracking_get_marker(track, framenr);
337         }
338
339         return marker;
340 }
341
342 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
343 {
344         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
345
346         if(marker && marker->framenr!=framenr)
347                 return NULL;
348
349         return marker;
350 }
351
352 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
353 {
354         return BKE_tracking_exact_marker(track, framenr) != 0;
355 }
356
357 void BKE_tracking_free_track(MovieTrackingTrack *track)
358 {
359         if(track->markers) MEM_freeN(track->markers);
360 }
361
362 MovieTrackingTrack *BKE_tracking_copy_track(MovieTrackingTrack *track)
363 {
364         MovieTrackingTrack *new_track= MEM_dupallocN(track);
365
366         new_track->next= new_track->prev= NULL;
367
368         if(new_track->markers)
369                 new_track->markers= MEM_dupallocN(new_track->markers);
370
371         return new_track;
372 }
373
374 static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite)
375 {
376         MovieTrackingMarker marker_new;
377
378         marker_new= *ref_marker;
379         marker_new.flag&= ~MARKER_TRACKED;
380         marker_new.flag|= MARKER_DISABLED;
381
382         if(before) marker_new.framenr--;
383         else marker_new.framenr++;
384
385         if(!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite)
386                 BKE_tracking_insert_marker(track, &marker_new);
387 }
388
389 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
390 {
391         int a;
392
393         if(action==TRACK_CLEAR_REMAINED) {
394                 a= 1;
395                 while(a<track->markersnr) {
396                         if(track->markers[a].framenr>ref_frame) {
397                                 track->markersnr= a;
398                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
399
400                                 break;
401                         }
402
403                         a++;
404                 }
405
406                 if(track->markersnr)
407                         put_disabled_marker(track, &track->markers[track->markersnr-1], 0, 1);
408         } else if(action==TRACK_CLEAR_UPTO) {
409                 a= track->markersnr-1;
410                 while(a>=0) {
411                         if(track->markers[a].framenr<=ref_frame) {
412                                 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
413
414                                 track->markersnr= track->markersnr-a;
415                                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
416
417                                 break;
418                         }
419
420                         a--;
421                 }
422
423                 if(track->markersnr)
424                         put_disabled_marker(track, &track->markers[0], 1, 1);
425         } else if(action==TRACK_CLEAR_ALL) {
426                 MovieTrackingMarker *marker, marker_new;
427
428                 marker= BKE_tracking_get_marker(track, ref_frame);
429                 marker_new= *marker;
430
431                 MEM_freeN(track->markers);
432                 track->markers= NULL;
433                 track->markersnr= 0;
434
435                 BKE_tracking_insert_marker(track, &marker_new);
436
437                 put_disabled_marker(track, &marker_new, 1, 1);
438                 put_disabled_marker(track, &marker_new, 0, 1);
439         }
440 }
441
442 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
443 {
444         int i, a= 0, b= 0, tot= dst_track->markersnr+src_track->markersnr;
445         int count= 0;
446
447         for(i= 0; i<tot; i++) {
448                 if(a>=src_track->markersnr) {
449                         b++;
450                         count++;
451                 }
452                 else if(b>=dst_track->markersnr) {
453                         a++;
454                         count++;
455                 }
456                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
457                         a++;
458                         count++;
459                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
460                         b++;
461                         count++;
462                 } else {
463                         if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0)
464                                 return 0;
465
466                         a++;
467                         b++;
468                         count++;
469                 }
470         }
471
472         return count;
473 }
474
475 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
476 {
477         int i, a= 0, b= 0, tot;
478         MovieTrackingMarker *markers;
479
480         tot= BKE_tracking_test_join_tracks(dst_track, src_track);
481
482         markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks");
483
484         for(i= 0; i<tot; i++) {
485                 if(b>=dst_track->markersnr) {
486                         markers[i]= src_track->markers[a++];
487                 }
488                 else if(a>=src_track->markersnr) {
489                         markers[i]= dst_track->markers[b++];
490                 }
491                 else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
492                         markers[i]= src_track->markers[a++];
493                 } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
494                         markers[i]= dst_track->markers[b++];
495                 } else {
496                         if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b];
497                         else markers[i]= src_track->markers[a++];
498
499                         a++;
500                         b++;
501                 }
502         }
503
504         MEM_freeN(dst_track->markers);
505
506         dst_track->markers= markers;
507         dst_track->markersnr= tot;
508 }
509
510 void BKE_tracking_free(MovieTracking *tracking)
511 {
512         MovieTrackingTrack *track;
513
514         for(track= tracking->tracks.first; track; track= track->next) {
515                 BKE_tracking_free_track(track);
516         }
517
518         BLI_freelistN(&tracking->tracks);
519
520         if(tracking->reconstruction.cameras)
521                 MEM_freeN(tracking->reconstruction.cameras);
522
523         if(tracking->stabilization.scaleibuf)
524                 IMB_freeImBuf(tracking->stabilization.scaleibuf);
525
526         if(tracking->camera.intrinsics)
527                 BKE_tracking_distortion_destroy(tracking->camera.intrinsics);
528 }
529
530 /*********************** tracking *************************/
531
532 typedef struct TrackContext {
533         MovieTrackingTrack *track;
534
535 #ifdef WITH_LIBMV
536         float keyframed_pos[2];
537
538         /* ** KLT tracker ** */
539         struct libmv_RegionTracker *region_tracker;
540         float *patch;                   /* keyframed patch */
541
542         /* ** SAD tracker ** */
543         int patsize;                    /* size of pattern (currently only 16x16 due to libmv side) */
544         unsigned char *pattern; /* keyframed pattern */
545         unsigned char *warped;  /* warped version of reference */
546 #endif
547 } TrackContext;
548
549 typedef struct MovieTrackingContext {
550         MovieClipUser user;
551         MovieClip *clip;
552
553         int first_time, frames;
554
555         TrackContext *track_context;
556         int num_tracks;
557
558         GHash *hash;
559         MovieTrackingSettings settings;
560
561         short backwards, disable_failed;
562         int sync_frame;
563 } MovieTrackingContext;
564
565 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short disable_failed)
566 {
567         MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
568         MovieTracking *tracking= &clip->tracking;
569         MovieTrackingSettings *settings= &tracking->settings;
570         MovieTrackingTrack *track;
571         TrackContext *track_context;
572
573         context->settings= *settings;
574         context->backwards= backwards;
575         context->disable_failed= disable_failed;
576         context->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "tracking trackHash");
577         context->sync_frame= user->framenr;
578         context->first_time= 1;
579
580         /* count */
581         track= tracking->tracks.first;
582         while(track) {
583                 if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
584                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
585
586                         if((marker->flag&MARKER_DISABLED)==0)
587                                 context->num_tracks++;
588                 }
589
590                 track= track->next;
591         }
592
593         if(context->num_tracks) {
594                 int width, height;
595
596                 BKE_movieclip_get_size(clip, user, &width, &height);
597
598                 /* create tracking data */
599                 context->track_context= MEM_callocN(sizeof(TrackContext)*context->num_tracks, "tracking track_context");
600
601                 track_context= context->track_context;
602                 track= tracking->tracks.first;
603                 while(track) {
604                         if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
605                                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
606
607                                 if((marker->flag&MARKER_DISABLED)==0) {
608                                         MovieTrackingTrack *new_track= BKE_tracking_copy_track(track);
609
610                                         track_context->track= new_track;
611 #ifdef WITH_LIBMV
612                                         {
613                                                 if(track_context->track->tracker==TRACKER_KLT) {
614                                                         float search_size_x= (track->search_max[0]-track->search_min[0])*width;
615                                                         float search_size_y= (track->search_max[1]-track->search_min[1])*height;
616                                                         float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
617                                                         float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
618
619                                                         /* compute the maximum pyramid size */
620                                                         double search_to_pattern_ratio= MIN2(search_size_x,  search_size_y)
621                                                                 / MAX2(pattern_size_x, pattern_size_y);
622                                                         double log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2;
623                                                         int max_pyramid_levels= floor(log2_search_to_pattern_ratio + 1);
624
625                                                         /* try to accomodate the user's choice of pyramid level in a way
626                                                          * that doesn't cause the coarsest pyramid pattern to be larger
627                                                          * than the search size */
628                                                         int level= MIN2(track_context->track->pyramid_levels, max_pyramid_levels);
629                                                         track_context->region_tracker= libmv_regionTrackerNew(100, level);
630                                                 }
631                                                 else if(track_context->track->tracker==TRACKER_SAD) {
632                                                         /* nothing to initialize */
633                                                 }
634                                         }
635 #endif
636
637                                         BLI_ghash_insert(context->hash, new_track, track);
638
639                                         track_context++;
640                                 }
641                         }
642
643                         track= track->next;
644                 }
645         }
646
647         context->clip= clip;
648         context->user= *user;
649
650         return context;
651 }
652
653 void BKE_tracking_context_free(MovieTrackingContext *context)
654 {
655         int a;
656         TrackContext *track_context;
657
658         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
659                 BKE_tracking_free_track(context->track_context[a].track);
660
661 #if WITH_LIBMV
662                 if(track_context->region_tracker)
663                         libmv_regionTrackerDestroy(track_context->region_tracker);
664
665                 if(track_context->patch)
666                         MEM_freeN(track_context->patch);
667
668                 if(track_context->pattern)
669                         MEM_freeN(track_context->pattern);
670
671                 if(track_context->warped)
672                         MEM_freeN(track_context->warped);
673 #endif
674
675                 MEM_freeN(track_context->track);
676         }
677
678         if(context->track_context)
679                 MEM_freeN(context->track_context);
680
681         BLI_ghash_free(context->hash, NULL, NULL);
682
683         MEM_freeN(context);
684 }
685
686 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track)
687 {
688         int x, y;
689
690         if((track->flag&(TRACK_DISABLE_RED|TRACK_DISABLE_GREEN|TRACK_DISABLE_BLUE))==0)
691                 return;
692
693         for(y= 0; y<ibuf->y; y++) {
694                 for (x= 0; x<ibuf->x; x++) {
695                         int pixel= ibuf->x*y + x;
696
697                         if(ibuf->rect_float) {
698                                 float *rrgbf= ibuf->rect_float + pixel*4;
699
700                                 if(track->flag&TRACK_DISABLE_RED)       rrgbf[0]= 0;
701                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgbf[1]= 0;
702                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgbf[2]= 0;
703                         } else {
704                                 char *rrgb= (char*)ibuf->rect + pixel*4;
705
706                                 if(track->flag&TRACK_DISABLE_RED)       rrgb[0]= 0;
707                                 if(track->flag&TRACK_DISABLE_GREEN)     rrgb[1]= 0;
708                                 if(track->flag&TRACK_DISABLE_BLUE)      rrgb[2]= 0;
709                         }
710                 }
711         }
712 }
713
714 static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
715                         float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2])
716 {
717         ImBuf *tmpibuf;
718         int x, y;
719         int x1, y1, x2, y2, w, h;
720         float mpos[2];
721
722         copy_v2_v2(mpos, marker->pos);
723         if(anchored)
724                 add_v2_v2(mpos, track->offset);
725
726         x= mpos[0]*ibuf->x;
727         y= mpos[1]*ibuf->y;
728         x1= x-(int)(-min[0]*ibuf->x);
729         y1= y-(int)(-min[1]*ibuf->y);
730         x2= x+(int)(max[0]*ibuf->x);
731         y2= y+(int)(max[1]*ibuf->y);
732
733         /* dimensions should be odd */
734         w= (x2-x1)|1;
735         h= (y2-y1)|1;
736
737         tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
738         IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
739
740         if(pos != NULL) {
741                 pos[0]= mpos[0]*ibuf->x-x1+margin;
742                 pos[1]= mpos[1]*ibuf->y-y1+margin;
743         }
744
745         if(origin != NULL) {
746                 origin[0]= x1-margin;
747                 origin[1]= y1-margin;
748         }
749
750         disable_imbuf_channels(tmpibuf, track);
751
752         return tmpibuf;
753 }
754
755 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
756                         int margin, int anchored, float pos[2], int origin[2])
757 {
758         return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin);
759 }
760
761 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
762                         int margin, int anchored, float pos[2], int origin[2])
763 {
764         return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin);
765 }
766
767 #ifdef WITH_LIBMV
768 static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
769                         int *width_r, int *height_r, float pos[2], int origin[2])
770 {
771         ImBuf *tmpibuf;
772         float *pixels, *fp;
773         int x, y, width, height;
774
775         width= (track->search_max[0]-track->search_min[0])*ibuf->x;
776         height= (track->search_max[1]-track->search_min[1])*ibuf->y;
777
778         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
779         disable_imbuf_channels(tmpibuf, track);
780
781         *width_r= width;
782         *height_r= height;
783
784         fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
785         for(y= 0; y<(int)height; y++) {
786                 for (x= 0; x<(int)width; x++) {
787                         int pixel= tmpibuf->x*y + x;
788
789                         if(tmpibuf->rect_float) {
790                                 float *rrgbf= tmpibuf->rect_float + pixel*4;
791
792                                 *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2];
793                         } else {
794                                 unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4;
795
796                                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f;
797                         }
798
799                         fp++;
800                 }
801         }
802
803         IMB_freeImBuf(tmpibuf);
804
805         return pixels;
806 }
807
808 static unsigned char *get_ucharbuf(ImBuf *ibuf)
809 {
810         int x, y;
811         unsigned char *pixels, *cp;
812
813         cp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
814         for(y= 0; y<ibuf->y; y++) {
815                 for (x= 0; x<ibuf->x; x++) {
816                         int pixel= ibuf->x*y + x;
817
818                         if(ibuf->rect_float) {
819                                 float *rrgbf= ibuf->rect_float + pixel*4;
820
821                                 *cp= FTOCHAR(0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2]);
822                         } else {
823                                 unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4;
824
825                                 *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
826                         }
827
828                         cp++;
829                 }
830         }
831
832         return pixels;
833 }
834
835 static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
836                         int *width_r, int *height_r, float pos[2], int origin[2])
837 {
838         ImBuf *tmpibuf;
839         unsigned char *pixels;
840
841         tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
842         disable_imbuf_channels(tmpibuf, track);
843
844         *width_r= tmpibuf->x;
845         *height_r= tmpibuf->y;
846
847         pixels= get_ucharbuf(tmpibuf);
848
849         IMB_freeImBuf(tmpibuf);
850
851         return pixels;
852 }
853
854 static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr)
855 {
856         ImBuf *ibuf;
857         int framenr_old= context->user.framenr;
858
859         context->user.framenr= framenr;
860
861         ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, 0);
862
863         context->user.framenr= framenr_old;
864
865         return ibuf;
866 }
867
868 static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
869                         MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
870 {
871         int framenr= marker->framenr;
872         int a= marker-track->markers;
873
874         *marker_keyed= marker;
875
876         while(a>=0 && a<track->markersnr) {
877                 int next= (context->backwards) ? a+1 : a-1;
878                 int is_keyframed= 0;
879                 MovieTrackingMarker *marker= &track->markers[a];
880                 MovieTrackingMarker *next_marker= NULL;
881
882                 if(next>=0 && next<track->markersnr)
883                         next_marker= &track->markers[next];
884
885                 /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */
886                 if(next_marker && next_marker->flag&MARKER_DISABLED)
887                         is_keyframed= 1;
888
889                 is_keyframed|= (marker->flag&MARKER_TRACKED)==0;
890
891                 if(is_keyframed) {
892                         framenr= marker->framenr;
893                         *marker_keyed= marker;
894                         break;
895                 }
896
897                 a= next;
898         }
899
900         return get_frame_ibuf(context, framenr);
901 }
902
903 static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
904                         int curfra, MovieTrackingMarker **marker_keyed)
905 {
906         ImBuf *ibuf= NULL;
907
908         if(context->settings.adjframes == 0) {
909                 ibuf= get_keyframed_ibuf(context, track, marker, marker_keyed);
910         } else {
911                 ibuf= get_frame_ibuf(context, curfra);
912
913                 /* use current marker as keyframed position */
914                 *marker_keyed= marker;
915         }
916
917         return ibuf;
918 }
919
920 static void get_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image)
921 {
922         int i, j;
923
924         for(i=0; i<track_context->patsize; i++) {
925                 for(j=0; j<track_context->patsize; j++) {
926                         track_context->warped[i*track_context->patsize+j]=
927                                         image[(y+i-track_context->patsize/2)*width+x+j-track_context->patsize/2];
928                 }
929         }
930 }
931
932 #endif
933
934 void BKE_tracking_sync(MovieTrackingContext *context)
935 {
936         TrackContext *track_context;
937         MovieTracking *tracking= &context->clip->tracking;
938         MovieTrackingTrack *track;
939         ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
940         ListBase *old_tracks= &context->clip->tracking.tracks;
941         int a, newframe;
942
943         /* duplicate currently tracking tracks to temporary list.
944            this is needed to keep names in unique state and it's faster to change names
945            of currently tracking tracks (if needed) */
946         for(a= 0, track_context= context->track_context; a<context->num_tracks; a++, track_context++) {
947                 int replace_sel= 0;
948                 MovieTrackingTrack *new_track, *old;
949
950                 track= track_context->track;
951
952                 /* find original of tracking track in list of previously displayed tracks */
953                 old= BLI_ghash_lookup(context->hash, track);
954                 if(old) {
955                         MovieTrackingTrack *cur= old_tracks->first;
956
957                         while(cur) {
958                                 if(cur==old)
959                                         break;
960
961                                 cur= cur->next;
962                         }
963
964                         /* original track was found, re-use flags and remove this track */
965                         if(cur) {
966                                 if(cur==tracking->act_track)
967                                         replace_sel= 1;
968
969                                 track->flag= cur->flag;
970                                 track->pat_flag= cur->pat_flag;
971                                 track->search_flag= cur->search_flag;
972
973                                 BKE_tracking_free_track(cur);
974                                 BLI_freelinkN(old_tracks, cur);
975                         }
976                 }
977
978                 new_track= BKE_tracking_copy_track(track);
979
980                 BLI_ghash_remove(context->hash, track, NULL, NULL); /* XXX: are we actually need this */
981                 BLI_ghash_insert(context->hash, track, new_track);
982
983                 if(replace_sel)         /* update current selection in clip */
984                         tracking->act_track= new_track;
985
986                 BLI_addtail(&tracks, new_track);
987         }
988
989         /* move all tracks, which aren't tracking */
990         track= old_tracks->first;
991         while(track) {
992                 MovieTrackingTrack *next= track->next;
993
994                 track->next= track->prev= NULL;
995                 BLI_addtail(&new_tracks, track);
996
997                 track= next;
998         }
999
1000         /* now move all tracks which are currently tracking and keep their names unique */
1001         track= tracks.first;
1002         while(track) {
1003                 MovieTrackingTrack *next= track->next;
1004
1005                 BLI_remlink(&tracks, track);
1006
1007                 track->next= track->prev= NULL;
1008                 BLI_addtail(&new_tracks, track);
1009
1010                 BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1011
1012                 track= next;
1013         }
1014
1015         context->clip->tracking.tracks= new_tracks;
1016
1017         if(context->backwards) newframe= context->user.framenr+1;
1018         else newframe= context->user.framenr-1;
1019
1020         context->sync_frame= newframe;
1021 }
1022
1023 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
1024 {
1025         user->framenr= context->sync_frame;
1026 }
1027
1028 int BKE_tracking_next(MovieTrackingContext *context)
1029 {
1030         ImBuf *ibuf_new;
1031         int curfra= context->user.framenr;
1032         int a, ok= 0;
1033
1034         /* nothing to track, avoid unneeded frames reading to save time and memory */
1035         if(!context->num_tracks)
1036                 return 0;
1037
1038         if(context->backwards) context->user.framenr--;
1039         else context->user.framenr++;
1040
1041         ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, 0);
1042         if(!ibuf_new)
1043                 return 0;
1044
1045         #pragma omp parallel for private(a) shared(ibuf_new, ok) if(context->num_tracks>1)
1046         for(a= 0; a<context->num_tracks; a++) {
1047                 TrackContext *track_context= &context->track_context[a];
1048                 MovieTrackingTrack *track= track_context->track;
1049                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, curfra);
1050
1051                 if(marker && (marker->flag&MARKER_DISABLED)==0 && marker->framenr==curfra) {
1052 #ifdef WITH_LIBMV
1053                         int width, height, origin[2], tracked= 0, need_readjust= 0;
1054                         float pos[2], margin[2];
1055                         double x1, y1, x2, y2;
1056                         ImBuf *ibuf= NULL;
1057                         MovieTrackingMarker marker_new, *marker_keyed;
1058                         int onbound= 0, coords_correct= 0;
1059                         int nextfra;
1060
1061                         if(!context->settings.adjframes) need_readjust= context->first_time;
1062                         else need_readjust= context->frames%context->settings.adjframes == 0;
1063
1064                         if(context->backwards) nextfra= curfra-1;
1065                         else nextfra= curfra+1;
1066
1067                         /* margin from frame boundaries */
1068                         sub_v2_v2v2(margin, track->pat_max, track->pat_min);
1069
1070                         margin[0]= MAX2(margin[0], (float)context->settings.margin / ibuf_new->x);
1071                         margin[1]= MAX2(margin[1], (float)context->settings.margin / ibuf_new->y);
1072
1073                         /* do not track markers which are too close to boundary */
1074                         if(marker->pos[0]<margin[0] || marker->pos[0]>1.0f-margin[0] ||
1075                            marker->pos[1]<margin[1] || marker->pos[1]>1.0f-margin[1]) {
1076                                 onbound= 1;
1077                         }
1078                         else if(track_context->track->tracker==TRACKER_KLT) {
1079                                 int wndx, wndy;
1080                                 float *patch_new;
1081
1082                                 if(need_readjust) {
1083                                         /* calculate patch for keyframed position */
1084                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1085
1086                                         if(track_context->patch)
1087                                                 MEM_freeN(track_context->patch);
1088
1089                                         track_context->patch= get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, track_context->keyframed_pos, origin);
1090
1091                                         IMB_freeImBuf(ibuf);
1092                                 }
1093
1094                                 patch_new= get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
1095
1096                                 x1= track_context->keyframed_pos[0];
1097                                 y1= track_context->keyframed_pos[1];
1098
1099                                 x2= pos[0];
1100                                 y2= pos[1];
1101
1102                                 wndx= (int)((track->pat_max[0]-track->pat_min[0])*ibuf_new->x)/2;
1103                                 wndy= (int)((track->pat_max[1]-track->pat_min[1])*ibuf_new->y)/2;
1104
1105                                 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
1106                                                         width, height, MAX2(wndx, wndy), x1, y1, &x2, &y2);
1107
1108                                 MEM_freeN(patch_new);
1109                         }
1110                         else if(track_context->track->tracker==TRACKER_SAD) {
1111                                 unsigned char *image_new;
1112                                 float correlation;
1113                                 float warp[3][2]={{0}};
1114
1115                                 if(need_readjust) {
1116                                         unsigned char *image;
1117
1118                                         /* calculate pattern for keyframed position */
1119                                         ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
1120
1121                                         image= get_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
1122
1123                                         memset(warp, 0, sizeof(warp));
1124                                         warp[0][0]= 1;
1125                                         warp[1][1]= 1;
1126                                         warp[2][0]= pos[0];
1127                                         warp[2][1]= pos[1];
1128
1129                                         /* pattern size is hardcoded to 16x16px in libmv */
1130                                         track_context->patsize= 16;
1131
1132                                         if(!track_context->pattern)
1133                                                 track_context->pattern= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking pattern");
1134
1135                                         libmv_SADSamplePattern(image, width, warp, track_context->pattern);
1136
1137                                         MEM_freeN(image);
1138                                         IMB_freeImBuf(ibuf);
1139                                 }
1140
1141                                 image_new= get_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
1142
1143                                 if(track_context->warped==NULL) {
1144                                         unsigned char *image_old;
1145
1146                                         ibuf= get_frame_ibuf(context, curfra);
1147
1148                                         if(track_context->warped==NULL)
1149                                                 track_context->warped= MEM_callocN(sizeof(unsigned char)*track_context->patsize*track_context->patsize, "trackking warped");
1150
1151                                         image_old= get_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
1152                                         get_warped(track_context, pos[0], pos[1], width, image_old);
1153                                         IMB_freeImBuf(ibuf);
1154                                         MEM_freeN(image_old);
1155                                 }
1156
1157                                 memset(warp, 0, sizeof(warp));
1158                                 warp[0][0]= 1;
1159                                 warp[1][1]= 1;
1160                                 warp[2][0]= pos[0];
1161                                 warp[2][1]= pos[1];
1162
1163                                 correlation= libmv_SADTrackerTrack(track_context->pattern, track_context->warped, image_new, width, width, height, warp);
1164
1165                                 x2= warp[2][0];
1166                                 y2= warp[2][1];
1167
1168                                 tracked= track_context->track->minimum_correlation < correlation;
1169
1170                                 if(tracked)
1171                                         get_warped(track_context, x2, y2, width, image_new);
1172
1173                                 MEM_freeN(image_new);
1174                         }
1175
1176                         coords_correct= !isnan(x2) && !isnan(y2) && finite(x2) && finite(y2);
1177                         if(coords_correct && (tracked || !context->disable_failed)) {
1178                                 if(context->first_time) {
1179                                         #pragma omp critical
1180                                         {
1181                                                 /* check if there's no keyframe/tracked markers before tracking marker.
1182                                                     if so -- create disabled marker before currently tracking "segment" */
1183                                                 put_disabled_marker(track, marker, 1, 0);
1184                                         }
1185                                 }
1186
1187                                 memset(&marker_new, 0, sizeof(marker_new));
1188
1189                                 if(!onbound) {
1190                                         marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
1191                                         marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
1192                                 } else {
1193                                         copy_v2_v2(marker_new.pos, marker->pos);
1194                                 }
1195
1196                                 marker_new.flag|= MARKER_TRACKED;
1197                                 marker_new.framenr= nextfra;
1198
1199                                 #pragma omp critical
1200                                 {
1201                                         BKE_tracking_insert_marker(track, &marker_new);
1202                                 }
1203
1204                                 /* make currently tracked segment be finished with disabled marker */
1205                                 #pragma omp critical
1206                                 {
1207                                         put_disabled_marker(track, &marker_new, 0, 0);
1208                                 }
1209                         } else {
1210                                 marker_new= *marker;
1211
1212                                 marker_new.framenr= nextfra;
1213                                 marker_new.flag|= MARKER_DISABLED;
1214
1215                                 #pragma omp critical
1216                                 {
1217                                         BKE_tracking_insert_marker(track, &marker_new);
1218                                 }
1219                         }
1220
1221                         ok= 1;
1222 #endif
1223                 }
1224         }
1225
1226         IMB_freeImBuf(ibuf_new);
1227
1228         context->first_time= 0;
1229         context->frames++;
1230
1231         return ok;
1232 }
1233
1234 #if WITH_LIBMV
1235 static struct libmv_Tracks *create_libmv_tracks(MovieTracking *tracking, int width, int height)
1236 {
1237         int tracknr= 0;
1238         MovieTrackingTrack *track;
1239         struct libmv_Tracks *tracks= libmv_tracksNew();
1240
1241         track= tracking->tracks.first;
1242         while(track) {
1243                 int a= 0;
1244
1245                 for(a= 0; a<track->markersnr; a++) {
1246                         MovieTrackingMarker *marker= &track->markers[a];
1247
1248                         if((marker->flag&MARKER_DISABLED)==0)
1249                                 libmv_tracksInsert(tracks, marker->framenr, tracknr,
1250                                                         marker->pos[0]*width, marker->pos[1]*height);
1251                 }
1252
1253                 track= track->next;
1254                 tracknr++;
1255         }
1256
1257         return tracks;
1258 }
1259
1260 static int retrieve_libmv_reconstruct(MovieTracking *tracking, struct libmv_Reconstruction *libmv_reconstruction)
1261 {
1262         int tracknr= 0;
1263         int sfra= INT_MAX, efra= INT_MIN, a, origin_set= 0;
1264         MovieTrackingTrack *track;
1265         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1266         MovieReconstructedCamera *reconstructed;
1267         float origin[3]= {0.0f, 0.0f, 0.0f};
1268         int ok= 1;
1269
1270         track= tracking->tracks.first;
1271         while(track) {
1272                 double pos[3];
1273
1274                 if(libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
1275                         track->bundle_pos[0]= pos[0];
1276                         track->bundle_pos[1]= pos[1];
1277                         track->bundle_pos[2]= pos[2];
1278
1279                         track->flag|= TRACK_HAS_BUNDLE;
1280                         track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
1281                 } else {
1282                         track->flag&= ~TRACK_HAS_BUNDLE;
1283                         ok= 0;
1284
1285                         printf("No bundle for track #%d '%s'\n", tracknr, track->name);
1286                 }
1287
1288                 if(track->markersnr) {
1289                         if(track->markers[0].framenr<sfra) sfra= track->markers[0].framenr;
1290                         if(track->markers[track->markersnr-1].framenr>efra) efra= track->markers[track->markersnr-1].framenr;
1291                 }
1292
1293                 track= track->next;
1294                 tracknr++;
1295         }
1296
1297         if(reconstruction->cameras)
1298                 MEM_freeN(reconstruction->cameras);
1299
1300         reconstruction->camnr= 0;
1301         reconstruction->cameras= NULL;
1302         reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
1303
1304         for(a= sfra; a<=efra; a++) {
1305                 double matd[4][4];
1306
1307                 if(libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
1308                         int i, j;
1309                         float mat[4][4];
1310                         float error= libmv_reporojectionErrorForImage(libmv_reconstruction, a);
1311
1312                         for(i=0; i<4; i++)
1313                                 for(j= 0; j<4; j++)
1314                                         mat[i][j]= matd[i][j];
1315
1316                         if(!origin_set) {
1317                                 copy_v3_v3(origin, mat[3]);
1318                                 origin_set= 1;
1319                         }
1320
1321                         if(origin_set)
1322                                 sub_v3_v3(mat[3], origin);
1323
1324                         copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
1325                         reconstructed[reconstruction->camnr].framenr= a;
1326                         reconstructed[reconstruction->camnr].error= error;
1327                         reconstruction->camnr++;
1328                 } else {
1329                         ok= 0;
1330                         printf("No camera for frame %d\n", a);
1331                 }
1332         }
1333
1334         if(reconstruction->camnr) {
1335                 reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
1336                 memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera));
1337         }
1338
1339         if(origin_set) {
1340                 track= tracking->tracks.first;
1341                 while(track) {
1342                         if(track->flag&TRACK_HAS_BUNDLE)
1343                                 sub_v3_v3(track->bundle_pos, origin);
1344
1345                         track= track->next;
1346                 }
1347         }
1348
1349         MEM_freeN(reconstructed);
1350
1351         return ok;
1352 }
1353
1354 #endif
1355
1356 float BKE_tracking_solve_reconstruction(MovieTracking *tracking, int width, int height)
1357 {
1358 #if WITH_LIBMV
1359         {
1360                 MovieTrackingCamera *camera= &tracking->camera;
1361                 float aspy= 1.0f/tracking->camera.pixel_aspect;
1362                 struct libmv_Tracks *tracks= create_libmv_tracks(tracking, width, height*aspy);
1363                 struct libmv_Reconstruction *reconstruction = libmv_solveReconstruction(tracks,
1364                         tracking->settings.keyframe1, tracking->settings.keyframe2,
1365                         camera->focal,
1366                         camera->principal[0], camera->principal[1]*aspy,
1367                         camera->k1, camera->k2, camera->k3);
1368                 float error= libmv_reprojectionError(reconstruction);
1369
1370                 tracking->reconstruction.error= error;
1371
1372                 if(!retrieve_libmv_reconstruct(tracking, reconstruction))
1373                         error= -1.0f;
1374
1375                 libmv_destroyReconstruction(reconstruction);
1376                 libmv_tracksDestroy(tracks);
1377
1378                 tracking->reconstruction.flag|= TRACKING_RECONSTRUCTED;
1379
1380                 return error;
1381         }
1382 #endif
1383 }
1384
1385 void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track)
1386 {
1387         BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
1388 }
1389
1390 MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char *name)
1391 {
1392         MovieTrackingTrack *track= tracking->tracks.first;
1393
1394         while(track) {
1395                 if(!strcmp(track->name, name))
1396                         return track;
1397
1398                 track= track->next;
1399         }
1400
1401         return NULL;
1402 }
1403
1404 static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int nearest)
1405 {
1406         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1407         MovieReconstructedCamera *cameras= reconstruction->cameras;
1408         int a= 0, d= 1;
1409
1410         if(!reconstruction->camnr)
1411                 return -1;
1412
1413         if(framenr<cameras[0].framenr) {
1414                 if(nearest) return 0;
1415                 else return -1;
1416         }
1417
1418         if(framenr>cameras[reconstruction->camnr-1].framenr) {
1419                 if(nearest) return reconstruction->camnr-1;
1420                 else return -1;
1421         }
1422
1423         if(reconstruction->last_camera<reconstruction->camnr)
1424                 a= reconstruction->last_camera;
1425
1426         if(cameras[a].framenr>=framenr)
1427                 d= -1;
1428
1429         while(a>=0 && a<reconstruction->camnr) {
1430                 int cfra= cameras[a].framenr;
1431
1432                 /* check if needed framenr was "skipped" -- no data for requested frame */
1433
1434                 if(d>0 && cfra>framenr) {
1435                         /* interpolate with previous position */
1436                         if(nearest) return a-1;
1437                         else break;
1438                 }
1439
1440                 if(d<0 && cfra<framenr) {
1441                         /* interpolate with next position */
1442                         if(nearest) return a;
1443                         else break;
1444                 }
1445
1446                 if(cfra==framenr) {
1447                         reconstruction->last_camera= a;
1448
1449                         return a;
1450                 }
1451
1452                 a+= d;
1453         }
1454
1455         return -1;
1456 }
1457
1458 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr)
1459 {
1460         int a= reconstruction_camera_index(tracking, framenr, 0);
1461
1462         if(a==-1)
1463                 return NULL;
1464
1465         return &tracking->reconstruction.cameras[a];
1466 }
1467
1468 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, float mat[4][4])
1469 {
1470         MovieTrackingReconstruction *reconstruction= &tracking->reconstruction;
1471         MovieReconstructedCamera *cameras= reconstruction->cameras;
1472         int a= reconstruction_camera_index(tracking, framenr, 1);
1473
1474         if(a==-1) {
1475                 unit_m4(mat);
1476                 return;
1477         }
1478
1479         if(cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) {
1480                 float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr);
1481
1482                 blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t);
1483         } else {
1484                 copy_m4_m4(mat, cameras[a].mat);
1485         }
1486 }
1487
1488 void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4])
1489 {
1490         if(!ob) {
1491                 if(scene->camera) ob= scene->camera;
1492                 else ob= scene_find_camera(scene);
1493         }
1494
1495         if(ob)
1496                 where_is_object_mat(scene, ob, mat);
1497         else
1498                 unit_m4(mat);
1499 }
1500
1501 void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
1502 {
1503         *shiftx= (0.5f*winx-tracking->camera.principal[0]) / winx;
1504         *shifty= (0.5f*winy-tracking->camera.principal[1]) / winx;
1505 }
1506
1507 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
1508 {
1509         float focal= tracking->camera.focal;
1510
1511         camera->sensor_x= tracking->camera.sensor_width;
1512         camera->sensor_fit= CAMERA_SENSOR_FIT_AUTO;
1513         camera->lens= focal*camera->sensor_x/width;
1514
1515         scene->r.xsch= width*tracking->camera.pixel_aspect;
1516         scene->r.ysch= height;
1517
1518         scene->r.xasp= 1.0f;
1519         scene->r.yasp= 1.0f;
1520
1521         BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
1522 }
1523
1524 void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4])
1525 {
1526         MovieReconstructedCamera *camera;
1527         float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
1528         float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
1529         float winmat[4][4];
1530         float ycor= 1.0f/tracking->camera.pixel_aspect;
1531         float shiftx, shifty, winside= MAX2(winx, winy);
1532
1533         BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty);
1534
1535         clipsta= 0.1f;
1536         clipend= 1000.0f;
1537
1538         if(winx >= winy)
1539                 viewfac= (lens*winx)/tracking->camera.sensor_width;
1540         else
1541                 viewfac= (ycor*lens*winy)/tracking->camera.sensor_width;
1542
1543         pixsize= clipsta/viewfac;
1544
1545         left= -0.5f*(float)winx + shiftx*winside;
1546         bottom= -0.5f*(ycor)*(float)winy + shifty*winside;
1547         right=  0.5f*(float)winx + shiftx*winside;
1548         top=  0.5f*(ycor)*(float)winy + shifty*winside;
1549
1550         left *= pixsize;
1551         right *= pixsize;
1552         bottom *= pixsize;
1553         top *= pixsize;
1554
1555         perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
1556
1557         camera= BKE_tracking_get_reconstructed_camera(tracking, framenr);
1558         if(camera) {
1559                 float imat[4][4];
1560
1561                 invert_m4_m4(imat, camera->mat);
1562                 mul_m4_m4m4(mat, imat, winmat);
1563         } else copy_m4_m4(mat, winmat);
1564 }
1565
1566 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1567 {
1568         MovieTrackingCamera *camera= &tracking->camera;
1569
1570 #ifdef WITH_LIBMV
1571         double x, y;
1572         float aspy= 1.0f/tracking->camera.pixel_aspect;
1573
1574         /* normalize coords */
1575         x= (co[0]-camera->principal[0]) / camera->focal;
1576         y= (co[1]-camera->principal[1] * aspy) / camera->focal;
1577
1578         libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1579                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1580
1581         /* result is in image coords already */
1582         nco[0]= x;
1583         nco[1]= y;
1584 #endif
1585 }
1586
1587 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
1588 {
1589         MovieTrackingCamera *camera= &tracking->camera;
1590
1591 #ifdef WITH_LIBMV
1592         double x= co[0], y= co[1];
1593         float aspy= 1.0f/tracking->camera.pixel_aspect;
1594
1595         libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
1596                                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
1597
1598         nco[0]= x * camera->focal + camera->principal[0];
1599         nco[1]= y * camera->focal + camera->principal[1] * aspy;
1600 #endif
1601 }
1602
1603 static int point_in_stroke(bGPDstroke *stroke, float x, float y)
1604 {
1605         int i, prev;
1606         int count= 0;
1607         bGPDspoint *points= stroke->points;
1608
1609         prev= stroke->totpoints-1;
1610
1611         for(i= 0; i<stroke->totpoints; i++) {
1612                 if((points[i].y<y && points[prev].y>=y) || (points[prev].y<y && points[i].y>=y)) {
1613                         float fac= (y-points[i].y)/(points[prev].y-points[i].y);
1614
1615                         if (points[i].x+fac*(points[prev].x-points[i].x)<x)
1616                                 count++;
1617                 }
1618
1619                 prev= i;
1620         }
1621
1622         return count%2;
1623 }
1624
1625 static int point_in_layer(bGPDlayer *layer, float x, float y)
1626 {
1627         bGPDframe *frame= layer->frames.first;
1628
1629         while(frame) {
1630                 bGPDstroke *stroke= frame->strokes.first;
1631                 while(stroke) {
1632                         if(point_in_stroke(stroke, x, y))
1633                                 return 1;
1634
1635                         stroke= stroke->next;
1636                 }
1637                 frame= frame->next;
1638         }
1639
1640         return 0;
1641 }
1642
1643 static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Features *features,
1644                         int framenr, int width, int height, bGPDlayer *layer, int place_outside_layer)
1645 {
1646 #ifdef WITH_LIBMV
1647         int a;
1648
1649         a= libmv_countFeatures(features);
1650         while(a--) {
1651                 MovieTrackingTrack *track;
1652                 double x, y, size, score;
1653                 int ok= 1;
1654                 float xu, yu;
1655
1656                 libmv_getFeature(features, a, &x, &y, &score, &size);
1657
1658                 xu= x/width;
1659                 yu= y/height;
1660
1661                 if(layer)
1662                         ok= point_in_layer(layer, xu, yu)!=place_outside_layer;
1663
1664                 if(ok) {
1665                         track= BKE_tracking_add_track(tracking, xu, yu, framenr, width, height);
1666                         track->flag|= SELECT;
1667                         track->pat_flag|= SELECT;
1668                         track->search_flag|= SELECT;
1669                 }
1670         }
1671 #endif
1672 }
1673
1674 void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf,
1675                         int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
1676                         int place_outside_layer)
1677 {
1678 #ifdef WITH_LIBMV
1679         struct libmv_Features *features;
1680         unsigned char *pixels= get_ucharbuf(ibuf);
1681
1682         features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, margin, min_trackness, min_distance);
1683
1684         MEM_freeN(pixels);
1685
1686         retrieve_libmv_features(tracking, features, framenr, ibuf->x, ibuf->y, layer, place_outside_layer);
1687
1688         libmv_destroyFeatures(features);
1689 #endif
1690 }
1691
1692 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr)
1693 {
1694         MovieTrackingTrack *track= tracking->tracks.first;
1695         int cur= 1;
1696
1697         while(track) {
1698                 if(track->flag&TRACK_HAS_BUNDLE) {
1699                         if(cur==tracknr)
1700                                 return track;
1701
1702                         cur++;
1703                 }
1704
1705                 track= track->next;
1706         }
1707
1708         return NULL;
1709 }
1710
1711 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
1712 {
1713         int ok= 0;
1714         float min[2], max[2];
1715         MovieTrackingTrack *track;
1716
1717         INIT_MINMAX2(min, max);
1718
1719         track= tracking->tracks.first;
1720         while(track) {
1721                 if(track->flag&TRACK_USE_2D_STAB) {
1722                         MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
1723
1724                         DO_MINMAX2(marker->pos, min, max);
1725
1726                         ok= 1;
1727                 }
1728
1729                 track= track->next;
1730         }
1731
1732         median[0]= (max[0]+min[0])/2.0f;
1733         median[1]= (max[1]+min[1])/2.0f;
1734
1735         return ok;
1736 }
1737
1738 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
1739                         float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
1740 {
1741         MovieTrackingStabilization *stab= &tracking->stabilization;
1742
1743         *scale= (stab->scale-1.0f)*stab->scaleinf+1.0f;
1744         *angle= 0.0f;
1745
1746         loc[0]= (firstmedian[0]-median[0])*width*(*scale);
1747         loc[1]= (firstmedian[1]-median[1])*height*(*scale);
1748
1749         mul_v2_fl(loc, stab->locinf);
1750
1751         if(stab->rot_track && stab->rotinf) {
1752                 MovieTrackingMarker *marker;
1753                 float a[2], b[2];
1754                 float x0= (float)width/2.0f, y0= (float)height/2.0f;
1755                 float x= median[0]*width, y= median[1]*height;
1756
1757                 marker= BKE_tracking_get_marker(stab->rot_track, 1);
1758                 sub_v2_v2v2(a, marker->pos, firstmedian);
1759                 a[0]*= width;
1760                 a[1]*= height;
1761
1762                 marker= BKE_tracking_get_marker(stab->rot_track, framenr);
1763                 sub_v2_v2v2(b, marker->pos, median);
1764                 b[0]*= width;
1765                 b[1]*= height;
1766
1767                 *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]);
1768                 *angle*= stab->rotinf;
1769
1770                 /* convert to rotation around image center */
1771                 loc[0]-= (x0 + (x-x0)*cos(*angle)-(y-y0)*sin(*angle) - x)*(*scale);
1772                 loc[1]-= (y0 + (x-x0)*sin(*angle)+(y-y0)*cos(*angle) - y)*(*scale);
1773         }
1774 }
1775
1776 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
1777 {
1778         float firstmedian[2];
1779         MovieTrackingStabilization *stab= &tracking->stabilization;
1780
1781         if(stab->ok)
1782                 return stab->scale;
1783
1784         if(stabilization_median_point(tracking, 1, firstmedian)) {
1785                 int sfra= INT_MAX, efra= INT_MIN, cfra;
1786                 float delta[2]= {0.0f, 0.0f}, scalex= 1.0f, scaley= 1.0f;
1787                 MovieTrackingTrack *track;
1788
1789                 stab->scale= 1.0f;
1790
1791                 track= tracking->tracks.first;
1792                 while(track) {
1793                         if(track->flag&TRACK_USE_2D_STAB || track==stab->rot_track) {
1794                                 if(track->markersnr) {
1795                                         sfra= MIN2(sfra, track->markers[0].framenr);
1796                                         efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
1797                                 }
1798                         }
1799
1800                         track= track->next;
1801                 }
1802
1803                 for(cfra=sfra; cfra<=efra; cfra++) {
1804                         float median[2], near[2];
1805                         float loc[2], scale, angle;
1806
1807                         stabilization_median_point(tracking, cfra, median);
1808
1809                         calculate_stabdata(tracking, cfra, width, height, firstmedian, median,
1810                                                 loc, &scale, &angle);
1811
1812                         if(angle==0.0f) {
1813                                 loc[0]= fabsf(loc[0]);
1814                                 loc[1]= fabsf(loc[1]);
1815
1816                                 delta[0]= MAX2(delta[0], loc[0]);
1817                                 delta[1]= MAX2(delta[1], loc[1]);
1818
1819                                 near[0]= MIN2(median[0], 1.0f-median[0]);
1820                                 near[1]= MIN2(median[1], 1.0f-median[1]);
1821                                 near[0]= MAX2(near[0], 0.05f);
1822                                 near[1]= MAX2(near[1], 0.05f);
1823
1824                                 scalex= 1.0f+delta[0]/(near[0]*width);
1825                                 scaley= 1.0f+delta[1]/(near[1]*height);
1826                         } else {
1827                                 int i;
1828                                 float mat[4][4];
1829                                 float points[4][2]={{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}};
1830
1831                                 BKE_tracking_stabdata_to_mat4(width, height, loc, scale, angle, mat);
1832
1833                                 for(i= 0; i<4; i++) {
1834                                         int j;
1835                                         float a[3]= {0.0f, 0.0f, 0.0f}, b[3]= {0.0f, 0.0f, 0.0f};
1836
1837                                         copy_v3_v3(a, points[i]);
1838                                         copy_v3_v3(b, points[(i+1)%4]);
1839
1840                                         mul_m4_v3(mat, a);
1841                                         mul_m4_v3(mat, b);
1842
1843                                         for(j= 0; j<4; j++) {
1844                                                 float point[3]= {points[j][0], points[j][1], 0.0f};
1845                                                 float v1[3], v2[3];
1846
1847                                                 sub_v3_v3v3(v1, b, a);
1848                                                 sub_v3_v3v3(v2, point, a);
1849
1850                                                 if(cross_v2v2(v1, v2) >= 0.0f) {
1851                                                         float dist= dist_to_line_v2(point, a, b);
1852                                                         if(i%2==0) {
1853                                                                 scalex= MAX2(scalex, (width+2*dist)/width);
1854                                                         } else {
1855                                                                 scaley= MAX2(scaley, (height+2*dist)/height);
1856                                                         }
1857                                                 }
1858                                         }
1859                                 }
1860                         }
1861                 }
1862
1863                 stab->scale= MAX2(scalex, scaley);
1864
1865                 if(stab->maxscale>0.0f)
1866                         stab->scale= MIN2(stab->scale, stab->maxscale);
1867         } else {
1868                 stab->scale= 1.0f;
1869         }
1870
1871         stab->ok= 1;
1872
1873         return stab->scale;
1874 }
1875
1876 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
1877 {
1878         int flags;
1879
1880         if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
1881                 IMB_freeImBuf(cacheibuf);
1882                 cacheibuf= NULL;
1883         }
1884
1885         flags= IB_rect;
1886
1887         if(srcibuf->rect_float)
1888                 flags|= IB_rectfloat;
1889
1890         if(cacheibuf) {
1891                 if(fill) {
1892                         float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
1893                         IMB_rectfill(cacheibuf, col);
1894                 }
1895         }
1896         else {
1897                 cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->depth, flags);
1898                 cacheibuf->profile= srcibuf->profile;
1899         }
1900
1901         return cacheibuf;
1902 }
1903
1904 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle)
1905 {
1906         float firstmedian[2], median[2];
1907         MovieTrackingStabilization *stab= &tracking->stabilization;
1908
1909         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1910                 zero_v2(loc);
1911                 *scale= 1.0f;
1912                 *angle= 0.0f;
1913
1914                 return;
1915         }
1916
1917         if(stabilization_median_point(tracking, 1, firstmedian)) {
1918                 stabilization_median_point(tracking, framenr, median);
1919
1920                 if((stab->flag&TRACKING_AUTOSCALE)==0)
1921                         stab->scale= 1.0f;
1922
1923                 if(!stab->ok) {
1924                         if(stab->flag&TRACKING_AUTOSCALE)
1925                                 stabilization_auto_scale_factor(tracking, width, height);
1926
1927                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1928
1929                         stab->ok= 1;
1930                 } else {
1931                         calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
1932                 }
1933         } else {
1934                 zero_v2(loc);
1935                 *scale= 1.0f;
1936                 *angle= 0.0f;
1937         }
1938 }
1939
1940 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle)
1941 {
1942         float tloc[2], tscale, tangle;
1943         MovieTrackingStabilization *stab= &tracking->stabilization;
1944         ImBuf *tmpibuf;
1945         float width= ibuf->x, height= ibuf->y;
1946
1947         if(loc)         copy_v2_v2(tloc, loc);
1948         if(scale)       tscale= *scale;
1949
1950         if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
1951                 if(loc)         zero_v2(loc);
1952                 if(scale)       *scale= 1.0f;
1953
1954                 return ibuf;
1955         }
1956
1957         BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
1958
1959         tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1);
1960
1961         /* scale would be handled by matrix transformation when angle is non-zero */
1962         if(tscale!=1.0f && tangle==0.0f) {
1963                 ImBuf *scaleibuf;
1964
1965                 stabilization_auto_scale_factor(tracking, width, height);
1966
1967                 scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
1968                 stab->scaleibuf= scaleibuf;
1969
1970                 IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
1971                 IMB_scalefastImBuf(scaleibuf, ibuf->x*tscale, ibuf->y*tscale);
1972
1973                 ibuf= scaleibuf;
1974         }
1975
1976         if(tangle==0.0f) {
1977                 /* if angle is zero, then it's much faster to use rect copy
1978                    but could be issues with subpixel precisions */
1979                 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);
1980         } else {
1981                 float mat[4][4];
1982                 int i, j;
1983
1984                 BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, tloc, tscale, tangle, mat);
1985                 invert_m4(mat);
1986
1987                 for(j=0; j<tmpibuf->y; j++) {
1988                         for(i=0; i<tmpibuf->x;i++) {
1989                                 float vec[3]= {i, j, 0};
1990
1991                                 mul_v3_m4v3(vec, mat, vec);
1992
1993                                 /* TODO: add selector for interpolation method */
1994                                 neareast_interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
1995                         }
1996                 }
1997         }
1998
1999         tmpibuf->userflags|= IB_MIPMAP_INVALID;
2000
2001         if(tmpibuf->rect_float)
2002                 tmpibuf->userflags|= IB_RECT_INVALID;
2003
2004         if(loc)         copy_v2_v2(loc, tloc);
2005         if(scale)       *scale= tscale;
2006         if(angle)       *angle= tangle;
2007
2008         return tmpibuf;
2009 }
2010
2011 void BKE_tracking_stabdata_to_mat4(int width, int height, float loc[2], float scale, float angle, float mat[4][4])
2012 {
2013         float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
2014         float svec[3]= {scale, scale, scale};
2015
2016         unit_m4(rmat);
2017         unit_m4(lmat);
2018         unit_m4(smat);
2019         unit_m4(cmat);
2020
2021         /* image center as rotation center */
2022         cmat[3][0]= (float)width/2.0f;
2023         cmat[3][1]= (float)height/2.0f;
2024         invert_m4_m4(icmat, cmat);
2025
2026         size_to_mat4(smat, svec);               /* scale matrix */
2027         add_v2_v2(lmat[3], loc);                /* tranlation matrix */
2028         rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
2029
2030         /* compose transformation matrix */
2031         mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);
2032 }
2033
2034 MovieDistortion *BKE_tracking_distortion_create(void)
2035 {
2036         MovieDistortion *distortion;
2037
2038         distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2039
2040         return distortion;
2041 }
2042
2043 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
2044 {
2045         MovieDistortion *new_distortion;
2046
2047         new_distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
2048
2049 #ifdef WITH_LIBMV
2050         new_distortion->intrinsics= libmv_CameraIntrinsicsCopy(distortion->intrinsics);
2051 #endif
2052
2053         return new_distortion;
2054 }
2055
2056 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height)
2057 {
2058         MovieTrackingCamera *camera= &tracking->camera;
2059         float aspy= 1.0f/tracking->camera.pixel_aspect;
2060
2061 #ifdef WITH_LIBMV
2062         if(!distortion->intrinsics) {
2063                 distortion->intrinsics= libmv_CameraIntrinsicsNew(camera->focal,
2064                                 camera->principal[0], camera->principal[1] * aspy,
2065                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2066         } else {
2067                 libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
2068                                 camera->principal[0], camera->principal[1] * aspy,
2069                                 camera->k1, camera->k2, camera->k3, width, height * aspy);
2070         }
2071 #endif
2072 }
2073
2074 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking,
2075                         ImBuf *ibuf, int width, int height, float overscan, int undistort)
2076 {
2077         ImBuf *resibuf;
2078
2079         BKE_tracking_distortion_update(distortion, tracking, width, height);
2080
2081         resibuf= IMB_dupImBuf(ibuf);
2082
2083         if(ibuf->rect_float) {
2084 #ifdef WITH_LIBMV
2085                 if(undistort) {
2086                         libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics,
2087                                                 ibuf->rect_float, resibuf->rect_float,
2088                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2089                 } else {
2090                         libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics,
2091                                                 ibuf->rect_float, resibuf->rect_float,
2092                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2093                 }
2094 #endif
2095
2096                 ibuf->userflags|= IB_RECT_INVALID;
2097         } else {
2098 #ifdef WITH_LIBMV
2099                 if(undistort) {
2100                                 libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics,
2101                                                         (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2102                                                         ibuf->x, ibuf->y, overscan, ibuf->channels);
2103                 } else {
2104                         libmv_CameraIntrinsicsDistortByte(distortion->intrinsics,
2105                                                 (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
2106                                                 ibuf->x, ibuf->y, overscan, ibuf->channels);
2107                 }
2108 #endif
2109         }
2110
2111         return resibuf;
2112 }
2113
2114 void BKE_tracking_distortion_destroy(MovieDistortion *distortion)
2115 {
2116 #ifdef WITH_LIBMV
2117         libmv_CameraIntrinsicsDestroy(distortion->intrinsics);
2118 #endif
2119
2120         MEM_freeN(distortion);
2121 }
2122
2123 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2124 {
2125         MovieTrackingCamera *camera= &tracking->camera;
2126
2127         if(camera->intrinsics == NULL)
2128                 camera->intrinsics= BKE_tracking_distortion_create();
2129
2130         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1);
2131 }
2132
2133 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
2134 {
2135         MovieTrackingCamera *camera= &tracking->camera;
2136
2137         if(camera->intrinsics == NULL)
2138                 camera->intrinsics= BKE_tracking_distortion_create();
2139
2140         return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0);
2141 }
2142
2143 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
2144 void BKE_tracking_select_track(MovieTracking *tracking, MovieTrackingTrack *track, int area, int extend)
2145 {
2146         if(extend) {
2147                 BKE_tracking_track_flag(track, area, SELECT, 0);
2148         } else {
2149                 MovieTrackingTrack *cur= tracking->tracks.first;
2150
2151                 while(cur) {
2152                         if(cur==track) {
2153                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2154                                 BKE_tracking_track_flag(cur, area, SELECT, 0);
2155                         }
2156                         else {
2157                                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
2158                         }
2159
2160                         cur= cur->next;
2161                 }
2162         }
2163 }
2164
2165 void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area)
2166 {
2167         BKE_tracking_track_flag(track, area, SELECT, 1);
2168 }