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