Blender V2.61 - r43446

tracking.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2011 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation,
00022  *                 Sergey Sharybin
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00031 #include <stddef.h>
00032 #include <limits.h>
00033 #include <math.h>
00034 #include <memory.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "DNA_gpencil_types.h"
00039 #include "DNA_camera_types.h"
00040 #include "DNA_movieclip_types.h"
00041 #include "DNA_object_types.h"   /* SELECT */
00042 #include "DNA_scene_types.h"
00043 
00044 #include "BLI_utildefines.h"
00045 #include "BLI_math.h"
00046 #include "BLI_math_base.h"
00047 #include "BLI_listbase.h"
00048 #include "BLI_ghash.h"
00049 #include "BLI_path_util.h"
00050 #include "BLI_string.h"
00051 #include "BLI_threads.h"
00052 
00053 #include "BKE_global.h"
00054 #include "BKE_tracking.h"
00055 #include "BKE_movieclip.h"
00056 #include "BKE_object.h"
00057 #include "BKE_scene.h"
00058 #include "BKE_main.h"   // XXX: ...
00059 
00060 #include "IMB_imbuf_types.h"
00061 #include "IMB_imbuf.h"
00062 
00063 #ifdef WITH_LIBMV
00064 #  include "libmv-capi.h"
00065 #else
00066 struct libmv_Features;
00067 #endif
00068 
00069 typedef struct MovieDistortion {
00070     struct libmv_CameraIntrinsics *intrinsics;
00071 } MovieDistortion;
00072 
00073 static struct {
00074     ListBase tracks;
00075 } tracking_clipboard;
00076 
00077 /*********************** common functions *************************/
00078 
00079 void BKE_tracking_init_settings(MovieTracking *tracking)
00080 {
00081     tracking->camera.sensor_width= 35.0f;
00082     tracking->camera.pixel_aspect= 1.0f;
00083     tracking->camera.units= CAMERA_UNITS_MM;
00084 
00085     tracking->settings.default_tracker= TRACKER_HYBRID;
00086     tracking->settings.default_minimum_correlation= 0.75;
00087     tracking->settings.default_pattern_size= 11;
00088     tracking->settings.default_search_size= 51;
00089     tracking->settings.default_pyramid_levels= 2;
00090     tracking->settings.keyframe1= 1;
00091     tracking->settings.keyframe2= 30;
00092     tracking->settings.dist= 1;
00093     tracking->settings.object_distance= 1;
00094 
00095     tracking->stabilization.scaleinf= 1.0f;
00096     tracking->stabilization.locinf= 1.0f;
00097     tracking->stabilization.rotinf= 1.0f;
00098     tracking->stabilization.maxscale= 2.0f;
00099 
00100     BKE_tracking_new_object(tracking, "Camera");
00101 }
00102 
00103 void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event)
00104 {
00105     int a;
00106     float pat_min[2];
00107     float pat_max[2];
00108     float max_pyramid_level_factor = 1.0;
00109 
00110     if (track->tracker == TRACKER_KLT) {
00111         max_pyramid_level_factor= 1 << (track->pyramid_levels - 1);
00112     }
00113 
00114     /* sort */
00115     for(a= 0; a<2; a++) {
00116         if(track->pat_min[a]>track->pat_max[a])
00117             SWAP(float, track->pat_min[a], track->pat_max[a]);
00118 
00119         if(track->search_min[a]>track->search_max[a])
00120             SWAP(float, track->search_min[a], track->search_max[a]);
00121     }
00122 
00123     /* compute the effective pattern size, which differs from the fine resolution
00124      * pattern size for the pyramid KLT tracker */
00125     for(a= 0; a<2; a++) {
00126         pat_min[a] = max_pyramid_level_factor * track->pat_min[a];
00127         pat_max[a] = max_pyramid_level_factor * track->pat_max[a];
00128     }
00129 
00130     if(event==CLAMP_PAT_DIM) {
00131         for(a= 0; a<2; a++) {
00132             /* search shouldn't be resized smaller than pattern */
00133             track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
00134             track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
00135         }
00136     }
00137     else if(event==CLAMP_PAT_POS) {
00138         float dim[2];
00139         sub_v2_v2v2(dim, track->pat_max, track->pat_min);
00140 
00141         for(a= 0; a<2; a++) {
00142             /* pattern shouldn't be moved outside of search */
00143             if(pat_min[a] < track->search_min[a]) {
00144                 track->pat_min[a]= track->search_min[a] - (pat_min[a] - track->pat_min[a]);
00145                 track->pat_max[a]= track->pat_min[a] + dim[a];
00146             }
00147             if(track->pat_max[a] > track->search_max[a]) {
00148                 track->pat_max[a]= track->search_max[a] - (pat_max[a] - track->pat_max[a]);
00149                 track->pat_min[a]= track->pat_max[a] - dim[a];
00150             }
00151         }
00152     }
00153     else if(event==CLAMP_SEARCH_DIM) {
00154         for(a= 0; a<2; a++) {
00155             /* search shouldn't be resized smaller than pattern */
00156             track->search_min[a]= MIN2(pat_min[a], track->search_min[a]);
00157             track->search_max[a]= MAX2(pat_max[a], track->search_max[a]);
00158         }
00159     }
00160     else if(event==CLAMP_SEARCH_POS) {
00161         float dim[2];
00162         sub_v2_v2v2(dim, track->search_max, track->search_min);
00163 
00164         for(a= 0; a<2; a++) {
00165             /* search shouldn't be moved inside pattern */
00166             if(track->search_min[a] > pat_min[a]) {
00167                 track->search_min[a]= pat_min[a];
00168                 track->search_max[a]= track->search_min[a]+dim[a];
00169             }
00170             if(track->search_max[a] < pat_max[a]) {
00171                 track->search_max[a]= pat_max[a];
00172                 track->search_min[a]= track->search_max[a]-dim[a];
00173             }
00174         }
00175     }
00176     else if(event==CLAMP_PYRAMID_LEVELS || (event==CLAMP_SEARCH_DIM && track->tracker == TRACKER_KLT))  {
00177         float dim[2];
00178         sub_v2_v2v2(dim, track->pat_max, track->pat_min);
00179         {
00180             float search_ratio= 2.3f * max_pyramid_level_factor;
00181 
00182             /* resize the search area to something sensible based
00183              * on the number of pyramid levels */
00184             for(a= 0; a<2; a++) {
00185                 track->search_min[a]= search_ratio * track->pat_min[a];
00186                 track->search_max[a]= search_ratio * track->pat_max[a];
00187             }
00188         }
00189     }
00190 
00191     /* marker's center should be in center of pattern */
00192     if(event==CLAMP_PAT_DIM || event==CLAMP_PAT_POS) {
00193         float dim[2];
00194         sub_v2_v2v2(dim, track->pat_max, track->pat_min);
00195 
00196         for(a= 0; a<2; a++) {
00197             track->pat_min[a]= -dim[a]/2.0f;
00198             track->pat_max[a]= dim[a]/2.0f;
00199         }
00200     }
00201 }
00202 
00203 void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear)
00204 {
00205     if(area==TRACK_AREA_NONE)
00206         return;
00207 
00208     if(clear) {
00209         if(area&TRACK_AREA_POINT)   track->flag&= ~flag;
00210         if(area&TRACK_AREA_PAT)     track->pat_flag&= ~flag;
00211         if(area&TRACK_AREA_SEARCH)  track->search_flag&= ~flag;
00212     } else {
00213         if(area&TRACK_AREA_POINT)   track->flag|= flag;
00214         if(area&TRACK_AREA_PAT)     track->pat_flag|= flag;
00215         if(area&TRACK_AREA_SEARCH)  track->search_flag|= flag;
00216     }
00217 }
00218 
00219 MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y,
00220             int framenr, int width, int height)
00221 {
00222     MovieTrackingTrack *track;
00223     MovieTrackingMarker marker;
00224     MovieTrackingSettings *settings= &tracking->settings;
00225 
00226     float half_pattern= (float)settings->default_pattern_size/2.0f;
00227     float half_search= (float)settings->default_search_size/2.0f;
00228     float pat[2], search[2];
00229 
00230     pat[0]= half_pattern/(float)width;
00231     pat[1]= half_pattern/(float)height;
00232 
00233     search[0]= half_search/(float)width;
00234     search[1]= half_search/(float)height;
00235 
00236     track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
00237     strcpy(track->name, "Track");
00238 
00239     track->tracker= settings->default_tracker;
00240     track->pyramid_levels= settings->default_pyramid_levels;
00241     track->minimum_correlation= settings->default_minimum_correlation;
00242     track->margin= settings->default_margin;
00243     track->pattern_match= settings->default_pattern_match;
00244     track->frames_limit= settings->default_frames_limit;
00245 
00246     memset(&marker, 0, sizeof(marker));
00247     marker.pos[0]= x;
00248     marker.pos[1]= y;
00249     marker.framenr= framenr;
00250 
00251     copy_v2_v2(track->pat_max, pat);
00252     negate_v2_v2(track->pat_min, pat);
00253 
00254     copy_v2_v2(track->search_max, search);
00255     negate_v2_v2(track->search_min, search);
00256 
00257     BKE_tracking_insert_marker(track, &marker);
00258 
00259     if(track->tracker == TRACKER_KLT)
00260         BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS);
00261 
00262     BLI_addtail(tracksbase, track);
00263     BKE_track_unique_name(tracksbase, track);
00264 
00265     return track;
00266 }
00267 
00268 MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker)
00269 {
00270     MovieTrackingMarker *old_marker= NULL;
00271 
00272     if(track->markersnr)
00273         old_marker= BKE_tracking_exact_marker(track, marker->framenr);
00274 
00275     if(old_marker) {
00276         *old_marker= *marker;
00277 
00278         return old_marker;
00279     } else {
00280         int a= track->markersnr;
00281 
00282         while(a--) {
00283             if(track->markers[a].framenr<marker->framenr)
00284                 break;
00285         }
00286 
00287         track->markersnr++;
00288 
00289         if(track->markers) track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
00290         else track->markers= MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers");
00291 
00292         memmove(track->markers+a+2, track->markers+a+1, (track->markersnr-a-2)*sizeof(MovieTrackingMarker));
00293         track->markers[a+1]= *marker;
00294 
00295         track->last_marker= a+1;
00296 
00297         return &track->markers[a+1];
00298     }
00299 }
00300 
00301 void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr)
00302 {
00303     int a= 0;
00304 
00305     while(a<track->markersnr) {
00306         if(track->markers[a].framenr==framenr) {
00307             if(track->markersnr>1) {
00308                 memmove(track->markers+a, track->markers+a+1, (track->markersnr-a-1)*sizeof(MovieTrackingMarker));
00309                 track->markersnr--;
00310                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
00311             } else {
00312                 MEM_freeN(track->markers);
00313                 track->markers= NULL;
00314                 track->markersnr= 0;
00315             }
00316 
00317             break;
00318         }
00319 
00320         a++;
00321     }
00322 }
00323 
00324 MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr)
00325 {
00326     int a= track->markersnr-1;
00327 
00328     if(!track->markersnr)
00329         return NULL;
00330 
00331     /* approximate pre-first framenr marker with first marker */
00332     if(framenr<track->markers[0].framenr)
00333         return &track->markers[0];
00334 
00335     if(track->last_marker<track->markersnr)
00336         a= track->last_marker;
00337 
00338     if(track->markers[a].framenr<=framenr) {
00339         while(a<track->markersnr && track->markers[a].framenr<=framenr) {
00340             if(track->markers[a].framenr==framenr) {
00341                 track->last_marker= a;
00342                 return &track->markers[a];
00343             }
00344             a++;
00345         }
00346 
00347         /* if there's no marker for exact position, use nearest marker from left side */
00348         return &track->markers[a-1];
00349     } else {
00350         while(a>=0 && track->markers[a].framenr>=framenr) {
00351             if(track->markers[a].framenr==framenr) {
00352                 track->last_marker= a;
00353                 return &track->markers[a];
00354             }
00355 
00356             a--;
00357         }
00358 
00359         /* if there's no marker for exact position, use nearest marker from left side */
00360         return &track->markers[a];
00361     }
00362 
00363     return NULL;
00364 }
00365 
00366 MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr)
00367 {
00368     MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
00369 
00370     if(marker->framenr!=framenr) {
00371         MovieTrackingMarker marker_new;
00372 
00373         marker_new= *marker;
00374         marker_new.framenr= framenr;
00375 
00376         BKE_tracking_insert_marker(track, &marker_new);
00377         marker= BKE_tracking_get_marker(track, framenr);
00378     }
00379 
00380     return marker;
00381 }
00382 
00383 MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr)
00384 {
00385     MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
00386 
00387     if(marker->framenr!=framenr)
00388         return NULL;
00389 
00390     return marker;
00391 }
00392 
00393 int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr)
00394 {
00395     return BKE_tracking_exact_marker(track, framenr) != 0;
00396 }
00397 
00398 void BKE_tracking_free_track(MovieTrackingTrack *track)
00399 {
00400     if(track->markers) MEM_freeN(track->markers);
00401 }
00402 
00403 static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite)
00404 {
00405     MovieTrackingMarker marker_new;
00406 
00407     marker_new= *ref_marker;
00408     marker_new.flag&= ~MARKER_TRACKED;
00409     marker_new.flag|= MARKER_DISABLED;
00410 
00411     if(before) marker_new.framenr--;
00412     else marker_new.framenr++;
00413 
00414     if(!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite)
00415         BKE_tracking_insert_marker(track, &marker_new);
00416 }
00417 
00418 void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action)
00419 {
00420     int a;
00421 
00422     if(action==TRACK_CLEAR_REMAINED) {
00423         a= 1;
00424         while(a<track->markersnr) {
00425             if(track->markers[a].framenr>ref_frame) {
00426                 track->markersnr= a;
00427                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
00428 
00429                 break;
00430             }
00431 
00432             a++;
00433         }
00434 
00435         if(track->markersnr)
00436             put_disabled_marker(track, &track->markers[track->markersnr-1], 0, 1);
00437     } else if(action==TRACK_CLEAR_UPTO) {
00438         a= track->markersnr-1;
00439         while(a>=0) {
00440             if(track->markers[a].framenr<=ref_frame) {
00441                 memmove(track->markers, track->markers+a, (track->markersnr-a)*sizeof(MovieTrackingMarker));
00442 
00443                 track->markersnr= track->markersnr-a;
00444                 track->markers= MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr);
00445 
00446                 break;
00447             }
00448 
00449             a--;
00450         }
00451 
00452         if(track->markersnr)
00453             put_disabled_marker(track, &track->markers[0], 1, 1);
00454     } else if(action==TRACK_CLEAR_ALL) {
00455         MovieTrackingMarker *marker, marker_new;
00456 
00457         marker= BKE_tracking_get_marker(track, ref_frame);
00458         marker_new= *marker;
00459 
00460         MEM_freeN(track->markers);
00461         track->markers= NULL;
00462         track->markersnr= 0;
00463 
00464         BKE_tracking_insert_marker(track, &marker_new);
00465 
00466         put_disabled_marker(track, &marker_new, 1, 1);
00467         put_disabled_marker(track, &marker_new, 0, 1);
00468     }
00469 }
00470 
00471 int BKE_tracking_test_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
00472 {
00473     int a= 0, b= 0;
00474     int count= 0;
00475 
00476     while(a<src_track->markersnr || b<dst_track->markersnr) {
00477         if(b>=dst_track->markersnr) {
00478             a++;
00479             count++;
00480         }
00481         else if(a>=src_track->markersnr) {
00482             b++;
00483             count++;
00484         }
00485         else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
00486             a++;
00487             count++;
00488         } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
00489             b++;
00490             count++;
00491         } else {
00492             if((src_track->markers[a].flag&MARKER_DISABLED)==0 && (dst_track->markers[b].flag&MARKER_DISABLED)==0)
00493                 return 0;
00494 
00495             a++;
00496             b++;
00497             count++;
00498         }
00499     }
00500 
00501     return count;
00502 }
00503 
00504 void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
00505 {
00506     int i, a= 0, b= 0, tot;
00507     MovieTrackingMarker *markers;
00508 
00509     tot= BKE_tracking_test_join_tracks(dst_track, src_track);
00510 
00511     markers= MEM_callocN(tot*sizeof(MovieTrackingMarker), "tracking joined tracks");
00512 
00513     for(i= 0; i<tot; i++) {
00514         if(b>=dst_track->markersnr) {
00515             markers[i]= src_track->markers[a++];
00516         }
00517         else if(a>=src_track->markersnr) {
00518             markers[i]= dst_track->markers[b++];
00519         }
00520         else if(src_track->markers[a].framenr<dst_track->markers[b].framenr) {
00521             markers[i]= src_track->markers[a++];
00522         } else if(src_track->markers[a].framenr>dst_track->markers[b].framenr) {
00523             markers[i]= dst_track->markers[b++];
00524         } else {
00525             if((src_track->markers[a].flag&MARKER_DISABLED)) markers[i]= dst_track->markers[b];
00526             else markers[i]= src_track->markers[a++];
00527 
00528             a++;
00529             b++;
00530         }
00531     }
00532 
00533     MEM_freeN(dst_track->markers);
00534 
00535     dst_track->markers= markers;
00536     dst_track->markersnr= tot;
00537 }
00538 
00539 static void tracking_tracks_free(ListBase *tracks)
00540 {
00541     MovieTrackingTrack *track;
00542 
00543     for(track= tracks->first; track; track= track->next) {
00544         BKE_tracking_free_track(track);
00545     }
00546 
00547     BLI_freelistN(tracks);
00548 }
00549 
00550 static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
00551 {
00552     if(reconstruction->cameras)
00553         MEM_freeN(reconstruction->cameras);
00554 }
00555 
00556 static void tracking_object_free(MovieTrackingObject *object)
00557 {
00558     tracking_tracks_free(&object->tracks);
00559     tracking_reconstruction_free(&object->reconstruction);
00560 }
00561 
00562 static void tracking_objects_free(ListBase *objects)
00563 {
00564     MovieTrackingObject *object;
00565 
00566     for(object= objects->first; object; object= object->next)
00567         tracking_object_free(object);
00568 
00569     BLI_freelistN(objects);
00570 }
00571 
00572 void BKE_tracking_free(MovieTracking *tracking)
00573 {
00574     tracking_tracks_free(&tracking->tracks);
00575     tracking_reconstruction_free(&tracking->reconstruction);
00576     tracking_objects_free(&tracking->objects);
00577 
00578     if(tracking->stabilization.scaleibuf)
00579         IMB_freeImBuf(tracking->stabilization.scaleibuf);
00580 
00581     if(tracking->camera.intrinsics)
00582         BKE_tracking_distortion_destroy(tracking->camera.intrinsics);
00583 }
00584 
00585 static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track)
00586 {
00587     MovieTrackingTrack *new_track;
00588 
00589     new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track");
00590 
00591     *new_track= *track;
00592     new_track->next = new_track->prev = NULL;
00593 
00594     new_track->markers = MEM_dupallocN(new_track->markers);
00595 
00596     return new_track;
00597 }
00598 
00599 /*********************** clipboard *************************/
00600 
00601 void BKE_tracking_free_clipboard(void)
00602 {
00603     MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track;
00604 
00605     while (track) {
00606         next_track = track->next;
00607 
00608         BKE_tracking_free_track(track);
00609         MEM_freeN(track);
00610 
00611         track = next_track;
00612     }
00613 }
00614 
00615 void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object)
00616 {
00617     ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
00618     MovieTrackingTrack *track = tracksbase->first;
00619 
00620     while (track) {
00621         if (TRACK_SELECTED(track)) {
00622             MovieTrackingTrack *new_track = duplicate_track(track);
00623 
00624             BLI_addtail(&tracking_clipboard.tracks, new_track);
00625         }
00626 
00627         track = track->next;
00628     }
00629 }
00630 
00631 int BKE_tracking_clipboard_has_tracks(void)
00632 {
00633     return tracking_clipboard.tracks.first != NULL;
00634 }
00635 
00636 void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object)
00637 {
00638     ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object);
00639     MovieTrackingTrack *track = tracking_clipboard.tracks.first;
00640 
00641     while (track) {
00642         MovieTrackingTrack *new_track = duplicate_track(track);
00643 
00644         BLI_addtail(tracksbase, new_track);
00645         BKE_track_unique_name(tracksbase, new_track);
00646 
00647         track = track->next;
00648     }
00649 }
00650 
00651 /*********************** tracks map *************************/
00652 
00653 typedef struct TracksMap {
00654     char object_name[MAX_NAME];
00655     int is_camera;
00656 
00657     int num_tracks;
00658     int customdata_size;
00659 
00660     char *customdata;
00661     MovieTrackingTrack *tracks;
00662 
00663     GHash *hash;
00664 
00665     int ptr;
00666 } TracksMap;
00667 
00668 static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size)
00669 {
00670     TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap");
00671 
00672     BLI_strncpy(map->object_name, object_name, sizeof(map->object_name));
00673     map->is_camera= is_camera;
00674 
00675     map->num_tracks= num_tracks;
00676     map->customdata_size= customdata_size;
00677 
00678     map->tracks= MEM_callocN(sizeof(MovieTrackingTrack)*num_tracks, "TrackingsMap tracks");
00679 
00680     if(customdata_size)
00681         map->customdata= MEM_callocN(customdata_size*num_tracks, "TracksMap customdata");
00682 
00683     map->hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "TracksMap hash");
00684 
00685     return map;
00686 }
00687 
00688 static int tracks_map_size(TracksMap *map)
00689 {
00690     return map->num_tracks;
00691 }
00692 
00693 static void tracks_map_get(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata)
00694 {
00695     *track= &map->tracks[index];
00696 
00697     if(map->customdata)
00698         *customdata= &map->customdata[index*map->customdata_size];
00699 }
00700 
00701 static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata)
00702 {
00703     MovieTrackingTrack new_track= *track;
00704 
00705     new_track.markers= MEM_dupallocN(new_track.markers);
00706 
00707     map->tracks[map->ptr]= new_track;
00708 
00709     if(customdata)
00710         memcpy(&map->customdata[map->ptr*map->customdata_size], customdata, map->customdata_size);
00711 
00712     BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track);
00713 
00714     map->ptr++;
00715 }
00716 
00717 static void tracks_map_merge(TracksMap *map, MovieTracking *tracking)
00718 {
00719     MovieTrackingTrack *track;
00720     MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
00721     ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL};
00722     ListBase *old_tracks;
00723     int a;
00724 
00725     if(map->is_camera) {
00726         old_tracks= &tracking->tracks;
00727     } else {
00728         MovieTrackingObject *object= BKE_tracking_named_object(tracking, map->object_name);
00729 
00730         if(!object) {
00731             /* object was deleted by user, create new one */
00732             object= BKE_tracking_new_object(tracking, map->object_name);
00733         }
00734 
00735         old_tracks= &object->tracks;
00736     }
00737 
00738     /* duplicate currently operating tracks to temporary list.
00739        this is needed to keep names in unique state and it's faster to change names
00740        of currently operating tracks (if needed) */
00741     for(a= 0; a<map->num_tracks; a++) {
00742         int replace_sel= 0;
00743         MovieTrackingTrack *new_track, *old;
00744 
00745         track= &map->tracks[a];
00746 
00747         /* find original of operating track in list of previously displayed tracks */
00748         old= BLI_ghash_lookup(map->hash, track);
00749         if(old) {
00750             MovieTrackingTrack *cur= old_tracks->first;
00751 
00752             while(cur) {
00753                 if(cur==old)
00754                     break;
00755 
00756                 cur= cur->next;
00757             }
00758 
00759             /* original track was found, re-use flags and remove this track */
00760             if(cur) {
00761                 if(act_track)
00762                     replace_sel= 1;
00763 
00764                 track->flag= cur->flag;
00765                 track->pat_flag= cur->pat_flag;
00766                 track->search_flag= cur->search_flag;
00767 
00768                 BKE_tracking_free_track(cur);
00769                 BLI_freelinkN(old_tracks, cur);
00770             }
00771         }
00772 
00773         new_track= duplicate_track(track);
00774 
00775         BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */
00776         BLI_ghash_insert(map->hash, track, new_track);
00777 
00778         if(replace_sel)     /* update current selection in clip */
00779             tracking->act_track= new_track;
00780 
00781         BLI_addtail(&tracks, new_track);
00782     }
00783 
00784     /* move all tracks, which aren't operating */
00785     track= old_tracks->first;
00786     while(track) {
00787         MovieTrackingTrack *next= track->next;
00788 
00789         track->next= track->prev= NULL;
00790         BLI_addtail(&new_tracks, track);
00791 
00792         track= next;
00793     }
00794 
00795     /* now move all tracks which are currently operating and keep their names unique */
00796     track= tracks.first;
00797     while(track) {
00798         MovieTrackingTrack *next= track->next;
00799 
00800         BLI_remlink(&tracks, track);
00801 
00802         track->next= track->prev= NULL;
00803         BLI_addtail(&new_tracks, track);
00804 
00805         BLI_uniquename(&new_tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
00806 
00807         track= next;
00808     }
00809 
00810     *old_tracks= new_tracks;
00811 }
00812 
00813 static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata))
00814 {
00815     int i= 0;
00816 
00817     BLI_ghash_free(map->hash, NULL, NULL);
00818 
00819     for(i= 0; i<map->num_tracks; i++) {
00820         if(map->customdata && customdata_free)
00821             customdata_free(&map->customdata[i*map->customdata_size]);
00822 
00823         BKE_tracking_free_track(&map->tracks[i]);
00824     }
00825 
00826     if(map->customdata)
00827         MEM_freeN(map->customdata);
00828 
00829     MEM_freeN(map->tracks);
00830     MEM_freeN(map);
00831 }
00832 
00833 /*********************** tracking *************************/
00834 
00835 typedef struct TrackContext {
00836 #ifdef WITH_LIBMV
00837     float keyframed_pos[2];
00838 
00839     /* ** KLT tracker ** */
00840     struct libmv_RegionTracker *region_tracker;
00841     float *patch;           /* keyframed patch */
00842 
00843     /* ** SAD tracker ** */
00844     int pattern_size;       /* size of pattern */
00845     unsigned char *pattern; /* keyframed pattern */
00846     unsigned char *warped;  /* warped version of reference */
00847 #else
00848     int pad;
00849 #endif
00850 } TrackContext;
00851 
00852 typedef struct MovieTrackingContext {
00853     MovieClipUser user;
00854     MovieClip *clip;
00855     int clip_flag;
00856 
00857     int first_time, frames;
00858 
00859     MovieTrackingSettings settings;
00860     TracksMap *tracks_map;
00861 
00862     short backwards, sequence;
00863     int sync_frame;
00864 } MovieTrackingContext;
00865 
00866 MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence)
00867 {
00868     MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext");
00869     MovieTracking *tracking= &clip->tracking;
00870     MovieTrackingSettings *settings= &tracking->settings;
00871     ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
00872     MovieTrackingTrack *track;
00873     MovieTrackingObject *object= BKE_tracking_active_object(tracking);
00874     int num_tracks= 0;
00875 
00876     context->settings= *settings;
00877     context->backwards= backwards;
00878     context->sync_frame= user->framenr;
00879     context->first_time= 1;
00880     context->sequence= sequence;
00881 
00882     /* count */
00883     track= tracksbase->first;
00884     while(track) {
00885         if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
00886             MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
00887 
00888             if((marker->flag&MARKER_DISABLED)==0)
00889                 num_tracks++;
00890         }
00891 
00892         track= track->next;
00893     }
00894 
00895     if(num_tracks) {
00896         int width, height;
00897 
00898         context->tracks_map= tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA,
00899                     num_tracks, sizeof(TrackContext));
00900 
00901         BKE_movieclip_get_size(clip, user, &width, &height);
00902 
00903         /* create tracking data */
00904         track= tracksbase->first;
00905         while(track) {
00906             if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) {
00907                 MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
00908 
00909                 if((marker->flag&MARKER_DISABLED)==0) {
00910                     TrackContext track_context;
00911 
00912                     memset(&track_context, 0, sizeof(TrackContext));
00913 
00914 #ifdef WITH_LIBMV
00915                     {
00916                         float patx, paty;
00917                         patx= (int)((track->pat_max[0]-track->pat_min[0])*width);
00918                         paty= (int)((track->pat_max[1]-track->pat_min[1])*height);
00919 
00920                         if(ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) {
00921                             float search_size_x= (track->search_max[0]-track->search_min[0])*width;
00922                             float search_size_y= (track->search_max[1]-track->search_min[1])*height;
00923                             float pattern_size_x= (track->pat_max[0]-track->pat_min[0])*width;
00924                             float pattern_size_y= (track->pat_max[1]-track->pat_min[1])*height;
00925                             int wndx= (int)patx/2, wndy= (int)paty/2;
00926 
00927                             /* compute the maximum pyramid size */
00928                             float search_to_pattern_ratio= MIN2(search_size_x,  search_size_y)
00929                                 / MAX2(pattern_size_x, pattern_size_y);
00930                             float log2_search_to_pattern_ratio = log(floor(search_to_pattern_ratio)) / M_LN2;
00931                             int max_pyramid_levels= floor(log2_search_to_pattern_ratio + 1);
00932 
00933                             /* try to accomodate the user's choice of pyramid level in a way
00934                              * that doesn't cause the coarsest pyramid pattern to be larger
00935                              * than the search size */
00936                             int level= MIN2(track->pyramid_levels, max_pyramid_levels);
00937 
00938                             if(track->tracker==TRACKER_KLT)
00939                                 track_context.region_tracker= libmv_pyramidRegionTrackerNew(100, level, MAX2(wndx, wndy), track->minimum_correlation);
00940                             else
00941                                 track_context.region_tracker= libmv_hybridRegionTrackerNew(100, MAX2(wndx, wndy), track->minimum_correlation);
00942                         }
00943                         else if(track->tracker==TRACKER_SAD) {
00944                             track_context.pattern_size= MAX2(patx, paty);
00945                         }
00946                     }
00947 #endif
00948 
00949                     tracks_map_insert(context->tracks_map, track, &track_context);
00950                 }
00951             }
00952 
00953             track= track->next;
00954         }
00955     }
00956 
00957     context->clip= clip;
00958 
00959     /* store needed clip flags passing to get_buffer functions
00960      * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip
00961      *   only in case Proxy/Timecode flag is set, so store this flag to use
00962      *   timecodes properly but reset render size to SIZE_FULL so correct resolution
00963      *   would be used for images
00964      * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might
00965      *   be stored in a different location
00966      * ignore all the rest pssible flags for now */
00967     context->clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS;
00968 
00969     context->user= *user;
00970     context->user.render_size= 0;
00971     context->user.render_flag= MCLIP_PROXY_RENDER_SIZE_FULL;
00972 
00973     if(!sequence)
00974         BLI_begin_threaded_malloc();
00975 
00976     return context;
00977 }
00978 
00979 static void track_context_free(void *customdata)
00980 {
00981     TrackContext *track_context= (TrackContext *)customdata;
00982 
00983 #if WITH_LIBMV
00984     if(track_context->region_tracker)
00985         libmv_regionTrackerDestroy(track_context->region_tracker);
00986 
00987     if(track_context->patch)
00988         MEM_freeN(track_context->patch);
00989 
00990     if(track_context->pattern)
00991         MEM_freeN(track_context->pattern);
00992 
00993     if(track_context->warped)
00994         MEM_freeN(track_context->warped);
00995 #else
00996         (void) track_context;
00997 #endif
00998 }
00999 
01000 void BKE_tracking_context_free(MovieTrackingContext *context)
01001 {
01002     if(!context->sequence)
01003         BLI_end_threaded_malloc();
01004 
01005     tracks_map_free(context->tracks_map, track_context_free);
01006 
01007     MEM_freeN(context);
01008 }
01009 
01010 /* zap channels from the imbuf that are disabled by the user. this can lead to
01011  * better tracks sometimes. however, instead of simply zeroing the channels
01012  * out, do a partial grayscale conversion so the display is better. */
01013 void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale)
01014 {
01015     int x, y;
01016     float scale;
01017 
01018     if(!disable_red && !disable_green && !disable_blue && !grayscale)
01019         return;
01020 
01021     /* If only some components are selected, it's important to rescale the result
01022      * appropriately so that e.g. if only blue is selected, it's not zeroed out. */
01023     scale = (disable_red   ? 0.0f : 0.2126f) +
01024             (disable_green ? 0.0f : 0.7152f) +
01025             (disable_blue  ? 0.0f : 0.0722f);
01026 
01027     for(y= 0; y<ibuf->y; y++) {
01028         for (x= 0; x<ibuf->x; x++) {
01029             int pixel= ibuf->x*y + x;
01030 
01031             if(ibuf->rect_float) {
01032                 float *rrgbf= ibuf->rect_float + pixel*4;
01033                 float r = disable_red   ? 0.0f : rrgbf[0];
01034                 float g = disable_green ? 0.0f : rrgbf[1];
01035                 float b = disable_blue  ? 0.0f : rrgbf[2];
01036                 if (grayscale) {
01037                     float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
01038                     rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
01039                 } else {
01040                     rrgbf[0] = r;
01041                     rrgbf[1] = g;
01042                     rrgbf[2] = b;
01043                 }
01044             } else {
01045                 char *rrgb= (char*)ibuf->rect + pixel*4;
01046                 char r = disable_red   ? 0 : rrgb[0];
01047                 char g = disable_green ? 0 : rrgb[1];
01048                 char b = disable_blue  ? 0 : rrgb[2];
01049                 if (grayscale) {
01050                     float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale;
01051                     rrgb[0] = rrgb[1] = rrgb[2] = gray;
01052                 } else {
01053                     rrgb[0] = r;
01054                     rrgb[1] = g;
01055                     rrgb[2] = b;
01056                 }
01057             }
01058         }
01059     }
01060 }
01061 
01062 static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
01063 {
01064     BKE_tracking_disable_imbuf_channels(ibuf, track->flag&TRACK_DISABLE_RED,
01065             track->flag&TRACK_DISABLE_GREEN, track->flag&TRACK_DISABLE_RED, grayscale);
01066 }
01067 
01068 static ImBuf *get_area_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
01069             float min[2], float max[2], int margin, int anchored, float pos[2], int origin[2])
01070 {
01071     ImBuf *tmpibuf;
01072     int x, y;
01073     int x1, y1, w, h;
01074     float mpos[2];
01075 
01076     copy_v2_v2(mpos, marker->pos);
01077     if(anchored)
01078         add_v2_v2(mpos, track->offset);
01079 
01080     if(pos)
01081         zero_v2(pos);
01082 
01083     x= mpos[0]*ibuf->x;
01084     y= mpos[1]*ibuf->y;
01085 
01086     w= (max[0]-min[0])*ibuf->x;
01087     h= (max[1]-min[1])*ibuf->y;
01088 
01089     w= w|1;
01090     h= h|1;
01091 
01092     x1= x-(int)(w/2.0f);
01093     y1= y-(int)(h/2.0f);
01094 
01095     /* dimensions should be odd */
01096     tmpibuf= IMB_allocImBuf(w+margin*2, h+margin*2, 32, IB_rect);
01097     IMB_rectcpy(tmpibuf, ibuf, 0, 0, x1-margin, y1-margin, w+margin*2, h+margin*2);
01098 
01099     if(pos != NULL) {
01100         pos[0]= mpos[0]*ibuf->x-x1+margin;
01101         pos[1]= mpos[1]*ibuf->y-y1+margin;
01102     }
01103 
01104     if(origin != NULL) {
01105         origin[0]= x1-margin;
01106         origin[1]= y1-margin;
01107     }
01108 
01109     if((track->flag & TRACK_PREVIEW_GRAYSCALE) ||
01110        (track->flag & TRACK_DISABLE_RED)       ||
01111        (track->flag & TRACK_DISABLE_GREEN)     ||
01112        (track->flag & TRACK_DISABLE_BLUE))
01113     {
01114         disable_imbuf_channels(tmpibuf, track, 1 /* grayscale */);
01115     }
01116 
01117     return tmpibuf;
01118 }
01119 
01120 ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
01121             int margin, int anchored, float pos[2], int origin[2])
01122 {
01123     return get_area_imbuf(ibuf, track, marker, track->pat_min, track->pat_max, margin, anchored, pos, origin);
01124 }
01125 
01126 ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
01127             int margin, int anchored, float pos[2], int origin[2])
01128 {
01129     return get_area_imbuf(ibuf, track, marker, track->search_min, track->search_max, margin, anchored, pos, origin);
01130 }
01131 
01132 #ifdef WITH_LIBMV
01133 static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
01134             int *width_r, int *height_r, float pos[2], int origin[2])
01135 {
01136     ImBuf *tmpibuf;
01137     float *pixels, *fp;
01138     int x, y, width, height;
01139 
01140     width= (track->search_max[0]-track->search_min[0])*ibuf->x;
01141     height= (track->search_max[1]-track->search_min[1])*ibuf->y;
01142 
01143     tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
01144     disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
01145 
01146     *width_r= width;
01147     *height_r= height;
01148 
01149     fp= pixels= MEM_callocN(width*height*sizeof(float), "tracking floatBuf");
01150     for(y= 0; y<(int)height; y++) {
01151         for (x= 0; x<(int)width; x++) {
01152             int pixel= tmpibuf->x*y + x;
01153 
01154             if(tmpibuf->rect_float) {
01155                 float *rrgbf= tmpibuf->rect_float + pixel*4;
01156                 *fp= 0.2126*rrgbf[0] + 0.7152*rrgbf[1] + 0.0722*rrgbf[2];
01157             } else {
01158                 unsigned char *rrgb= (unsigned char*)tmpibuf->rect + pixel*4;
01159                 *fp= (0.2126*rrgb[0] + 0.7152*rrgb[1] + 0.0722*rrgb[2])/255.0f;
01160             }
01161             fp++;
01162         }
01163     }
01164 
01165     IMB_freeImBuf(tmpibuf);
01166 
01167     return pixels;
01168 }
01169 
01170 static unsigned char *get_ucharbuf(ImBuf *ibuf)
01171 {
01172     int x, y;
01173     unsigned char *pixels, *cp;
01174 
01175     cp= pixels= MEM_callocN(ibuf->x*ibuf->y*sizeof(unsigned char), "tracking ucharBuf");
01176     for(y= 0; y<ibuf->y; y++) {
01177         for (x= 0; x<ibuf->x; x++) {
01178             int pixel= ibuf->x*y + x;
01179 
01180             if(ibuf->rect_float) {
01181                 const float *rrgbf= ibuf->rect_float + pixel*4;
01182                 const float grey_f= 0.2126f*rrgbf[0] + 0.7152f*rrgbf[1] + 0.0722f*rrgbf[2];
01183                 *cp= FTOCHAR(grey_f);
01184             } else {
01185                 const unsigned char *rrgb= (unsigned char*)ibuf->rect + pixel*4;
01186                 *cp= 0.2126f*rrgb[0] + 0.7152f*rrgb[1] + 0.0722f*rrgb[2];
01187             }
01188             cp++;
01189         }
01190     }
01191 
01192     return pixels;
01193 }
01194 
01195 static unsigned char *get_search_bytebuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker,
01196             int *width_r, int *height_r, float pos[2], int origin[2])
01197 {
01198     ImBuf *tmpibuf;
01199     unsigned char *pixels;
01200 
01201     tmpibuf= BKE_tracking_get_search_imbuf(ibuf, track, marker, 0, 0, pos, origin);
01202     disable_imbuf_channels(tmpibuf, track, 0 /* don't grayscale */);
01203 
01204     *width_r= tmpibuf->x;
01205     *height_r= tmpibuf->y;
01206 
01207     pixels= get_ucharbuf(tmpibuf);
01208 
01209     IMB_freeImBuf(tmpibuf);
01210 
01211     return pixels;
01212 }
01213 
01214 static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr)
01215 {
01216     ImBuf *ibuf;
01217     MovieClipUser user= context->user;
01218 
01219     user.framenr= framenr;
01220 
01221     ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag);
01222 
01223     return ibuf;
01224 }
01225 
01226 static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track,
01227             MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed)
01228 {
01229     int framenr= marker->framenr;
01230     int a= marker-track->markers;
01231 
01232     *marker_keyed= marker;
01233 
01234     while(a>=0 && a<track->markersnr) {
01235         int next= (context->backwards) ? a+1 : a-1;
01236         int is_keyframed= 0;
01237         MovieTrackingMarker *cur_marker= &track->markers[a];
01238         MovieTrackingMarker *next_marker= NULL;
01239 
01240         if(next>=0 && next<track->markersnr)
01241             next_marker= &track->markers[next];
01242 
01243         /* if next mrker is disabled, stop searching keyframe and use current frame as keyframe */
01244         if(next_marker && next_marker->flag&MARKER_DISABLED)
01245             is_keyframed= 1;
01246 
01247         is_keyframed|= (cur_marker->flag&MARKER_TRACKED)==0;
01248 
01249         if(is_keyframed) {
01250             framenr= cur_marker->framenr;
01251             *marker_keyed= cur_marker;
01252             break;
01253         }
01254 
01255         a= next;
01256     }
01257 
01258     return get_frame_ibuf(context, framenr);
01259 }
01260 
01261 static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker,
01262             int curfra, MovieTrackingMarker **marker_keyed)
01263 {
01264     ImBuf *ibuf= NULL;
01265 
01266     if(track->pattern_match == TRACK_MATCH_KEYFRAME) {
01267         ibuf= get_keyframed_ibuf(context, track, marker, marker_keyed);
01268     } else {
01269         ibuf= get_frame_ibuf(context, curfra);
01270 
01271         /* use current marker as keyframed position */
01272         *marker_keyed= marker;
01273     }
01274 
01275     return ibuf;
01276 }
01277 
01278 static void get_warped(TrackContext *track_context, int x, int y, int width, unsigned char *image)
01279 {
01280     int i, j;
01281 
01282     for(i=0; i<track_context->pattern_size; i++) {
01283         for(j=0; j<track_context->pattern_size; j++) {
01284             track_context->warped[i*track_context->pattern_size+j]=
01285                     image[(y+i-track_context->pattern_size/2)*width+x+j-track_context->pattern_size/2];
01286         }
01287     }
01288 }
01289 
01290 #endif
01291 
01292 void BKE_tracking_sync(MovieTrackingContext *context)
01293 {
01294     MovieTracking *tracking= &context->clip->tracking;
01295     int newframe;
01296 
01297     tracks_map_merge(context->tracks_map, tracking);
01298 
01299     if(context->backwards) newframe= context->user.framenr+1;
01300     else newframe= context->user.framenr-1;
01301 
01302     context->sync_frame= newframe;
01303 }
01304 
01305 void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context)
01306 {
01307     user->framenr= context->sync_frame;
01308 }
01309 
01310 int BKE_tracking_next(MovieTrackingContext *context)
01311 {
01312     ImBuf *ibuf_new;
01313     int curfra= context->user.framenr;
01314     int a, ok= 0, map_size;
01315 
01316     map_size= tracks_map_size(context->tracks_map);
01317 
01318     /* nothing to track, avoid unneeded frames reading to save time and memory */
01319     if(!map_size)
01320         return 0;
01321 
01322     if(context->backwards) context->user.framenr--;
01323     else context->user.framenr++;
01324 
01325     ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag);
01326     if(!ibuf_new)
01327         return 0;
01328 
01329     #pragma omp parallel for private(a) shared(ibuf_new, ok) if(map_size>1)
01330     for(a= 0; a<map_size; a++) {
01331         TrackContext *track_context = NULL;
01332         MovieTrackingTrack *track;
01333         MovieTrackingMarker *marker;
01334 
01335         tracks_map_get(context->tracks_map, a, &track, (void**)&track_context);
01336 
01337         marker= BKE_tracking_exact_marker(track, curfra);
01338 
01339         if(marker && (marker->flag&MARKER_DISABLED)==0) {
01340 #ifdef WITH_LIBMV
01341             int width, height, origin[2], tracked= 0, need_readjust= 0;
01342             float pos[2], margin[2], dim[2];
01343             double x1, y1, x2, y2;
01344             ImBuf *ibuf= NULL;
01345             MovieTrackingMarker marker_new, *marker_keyed;
01346             int onbound= 0, nextfra;
01347 
01348             if(track->pattern_match==TRACK_MATCH_KEYFRAME)
01349                 need_readjust= context->first_time;
01350             else
01351                 need_readjust= 1;
01352 
01353             if(context->backwards) nextfra= curfra-1;
01354             else nextfra= curfra+1;
01355 
01356             /* margin from frame boundaries */
01357             sub_v2_v2v2(dim, track->pat_max, track->pat_min);
01358             margin[0]= margin[1]= MAX2(dim[0], dim[1]) / 2.0f;
01359 
01360             margin[0]= MAX2(margin[0], (float)track->margin / ibuf_new->x);
01361             margin[1]= MAX2(margin[1], (float)track->margin / ibuf_new->y);
01362 
01363             /* do not track markers which are too close to boundary */
01364             if(marker->pos[0]<margin[0] || marker->pos[0]>1.0f-margin[0] ||
01365                marker->pos[1]<margin[1] || marker->pos[1]>1.0f-margin[1]) {
01366                 onbound= 1;
01367             }
01368             else if(ELEM(track->tracker, TRACKER_KLT, TRACKER_HYBRID)) {
01369                 float *patch_new;
01370 
01371                 if(need_readjust) {
01372                     /* calculate patch for keyframed position */
01373                     ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
01374 
01375                     if(track_context->patch)
01376                         MEM_freeN(track_context->patch);
01377 
01378                     track_context->patch= get_search_floatbuf(ibuf, track, marker_keyed, &width, &height, track_context->keyframed_pos, origin);
01379 
01380                     IMB_freeImBuf(ibuf);
01381                 }
01382 
01383                 patch_new= get_search_floatbuf(ibuf_new, track, marker, &width, &height, pos, origin);
01384 
01385                 x1= track_context->keyframed_pos[0];
01386                 y1= track_context->keyframed_pos[1];
01387 
01388                 x2= pos[0];
01389                 y2= pos[1];
01390 
01391                 tracked= libmv_regionTrackerTrack(track_context->region_tracker, track_context->patch, patch_new,
01392                             width, height, x1, y1, &x2, &y2);
01393 
01394                 MEM_freeN(patch_new);
01395             }
01396             else if(track->tracker==TRACKER_SAD) {
01397                 unsigned char *image_new;
01398                 float correlation;
01399                 float warp[3][2]={{0}};
01400 
01401                 if(need_readjust) {
01402                     unsigned char *image;
01403 
01404                     /* calculate pattern for keyframed position */
01405                     ibuf= get_adjust_ibuf(context, track, marker, curfra, &marker_keyed);
01406 
01407                     image= get_search_bytebuf(ibuf, track, marker_keyed, &width, &height, pos, origin);
01408 
01409                     memset(warp, 0, sizeof(warp));
01410                     warp[0][0]= 1;
01411                     warp[1][1]= 1;
01412                     warp[2][0]= pos[0];
01413                     warp[2][1]= pos[1];
01414 
01415                     if(!track_context->pattern) {
01416                         int square= track_context->pattern_size*track_context->pattern_size;
01417                         track_context->pattern= MEM_callocN(sizeof(unsigned char)*square, "trackking pattern");
01418                     }
01419 
01420                     libmv_SADSamplePattern(image, width, warp, track_context->pattern, track_context->pattern_size);
01421 
01422                     MEM_freeN(image);
01423                     IMB_freeImBuf(ibuf);
01424                 }
01425 
01426                 image_new= get_search_bytebuf(ibuf_new, track, marker, &width, &height, pos, origin);
01427 
01428                 if(track_context->warped==NULL) {
01429                     unsigned char *image_old;
01430 
01431                     ibuf= get_frame_ibuf(context, curfra);
01432 
01433                     if(track_context->warped==NULL) {
01434                         int square= track_context->pattern_size*track_context->pattern_size;
01435                         track_context->warped= MEM_callocN(sizeof(unsigned char)*square, "trackking warped");
01436                     }
01437 
01438                     image_old= get_search_bytebuf(ibuf, track, marker, &width, &height, pos, origin);
01439                     get_warped(track_context, pos[0], pos[1], width, image_old);
01440                     IMB_freeImBuf(ibuf);
01441                     MEM_freeN(image_old);
01442                 }
01443 
01444                 memset(warp, 0, sizeof(warp));
01445                 warp[0][0]= 1;
01446                 warp[1][1]= 1;
01447                 warp[2][0]= pos[0];
01448                 warp[2][1]= pos[1];
01449 
01450                 correlation= libmv_SADTrackerTrack(track_context->pattern, track_context->warped,
01451                             track_context->pattern_size, image_new, width, width, height, warp);
01452 
01453                 x2= warp[2][0];
01454                 y2= warp[2][1];
01455 
01456                 tracked= track->minimum_correlation < correlation;
01457 
01458                 if(tracked)
01459                     get_warped(track_context, x2, y2, width, image_new);
01460 
01461                 MEM_freeN(image_new);
01462             }
01463 
01464             if(tracked && !onbound && finite(x2) && finite(y2)) {
01465                 if(context->first_time) {
01466                     #pragma omp critical
01467                     {
01468                         /* check if there's no keyframe/tracked markers before tracking marker.
01469                            if so -- create disabled marker before currently tracking "segment" */
01470                         put_disabled_marker(track, marker, !context->backwards, 0);
01471                     }
01472                 }
01473 
01474                 memset(&marker_new, 0, sizeof(marker_new));
01475 
01476                 if(!onbound) {
01477                     marker_new.pos[0]= (origin[0]+x2)/ibuf_new->x;
01478                     marker_new.pos[1]= (origin[1]+y2)/ibuf_new->y;
01479                 } else {
01480                     copy_v2_v2(marker_new.pos, marker->pos);
01481                 }
01482 
01483                 marker_new.flag|= MARKER_TRACKED;
01484                 marker_new.framenr= nextfra;
01485 
01486                 #pragma omp critical
01487                 {
01488                     BKE_tracking_insert_marker(track, &marker_new);
01489                 }
01490 
01491                 /* make currently tracked segment be finished with disabled marker */
01492                 #pragma omp critical
01493                 {
01494                     put_disabled_marker(track, &marker_new, context->backwards, 0);
01495                 }
01496             } else {
01497                 marker_new= *marker;
01498 
01499                 marker_new.framenr= nextfra;
01500                 marker_new.flag|= MARKER_DISABLED;
01501 
01502                 #pragma omp critical
01503                 {
01504                     BKE_tracking_insert_marker(track, &marker_new);
01505                 }
01506             }
01507 
01508             ok= 1;
01509 #endif
01510         }
01511     }
01512 
01513     IMB_freeImBuf(ibuf_new);
01514 
01515     context->first_time= 0;
01516     context->frames++;
01517 
01518     return ok;
01519 }
01520 
01521 /*********************** camera solving *************************/
01522 
01523 typedef struct MovieReconstructContext {
01524 #ifdef WITH_LIBMV
01525     struct libmv_Tracks *tracks;
01526     int keyframe1, keyframe2;
01527     short refine_flags;
01528 
01529     struct libmv_Reconstruction *reconstruction;
01530 #endif
01531     char object_name[MAX_NAME];
01532     int is_camera;
01533 
01534     float focal_length;
01535     float principal_point[2];
01536     float k1, k2, k3;
01537 
01538     float reprojection_error;
01539 
01540     TracksMap *tracks_map;
01541 
01542     int sfra, efra;
01543 } MovieReconstructContext;
01544 
01545 typedef struct ReconstructProgressData {
01546     short *stop;
01547     short *do_update;
01548     float *progress;
01549     char *stats_message;
01550     int message_size;
01551 } ReconstructProgressData;
01552 
01553 #if WITH_LIBMV
01554 static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height)
01555 {
01556     int tracknr= 0;
01557     MovieTrackingTrack *track;
01558     struct libmv_Tracks *tracks= libmv_tracksNew();
01559 
01560     track= tracksbase->first;
01561     while(track) {
01562         int a= 0;
01563 
01564         for(a= 0; a<track->markersnr; a++) {
01565             MovieTrackingMarker *marker= &track->markers[a];
01566 
01567             if((marker->flag&MARKER_DISABLED)==0)
01568                 libmv_tracksInsert(tracks, marker->framenr, tracknr,
01569                             marker->pos[0]*width, marker->pos[1]*height);
01570         }
01571 
01572         track= track->next;
01573         tracknr++;
01574     }
01575 
01576     return tracks;
01577 }
01578 
01579 static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *context, MovieTracking *tracking)
01580 {
01581     struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
01582     struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction);
01583 
01584     float aspy= 1.0f/tracking->camera.pixel_aspect;
01585 
01586     double focal_length, principal_x, principal_y, k1, k2, k3;
01587     int width, height;
01588 
01589     libmv_CameraIntrinsicsExtract(libmv_intrinsics, &focal_length, &principal_x, &principal_y,
01590             &k1, &k2, &k3, &width, &height);
01591 
01592     tracking->camera.focal= focal_length;
01593     tracking->camera.principal[0]= principal_x;
01594 
01595     /* todo: verify divide by aspy is correct */
01596     tracking->camera.principal[1]= principal_y / aspy;
01597     tracking->camera.k1= k1;
01598     tracking->camera.k2= k2;
01599 }
01600 
01601 static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking)
01602 {
01603     struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction;
01604     MovieTrackingReconstruction *reconstruction= NULL;
01605     MovieReconstructedCamera *reconstructed;
01606     MovieTrackingTrack *track;
01607     ListBase *tracksbase=  NULL;
01608     int ok= 1, tracknr= 0, a, origin_set= 0;
01609     int sfra= context->sfra, efra= context->efra;
01610     float imat[4][4];
01611 
01612     if(context->is_camera) {
01613         tracksbase= &tracking->tracks;
01614         reconstruction= &tracking->reconstruction;
01615     }
01616     else {
01617         MovieTrackingObject *object= BKE_tracking_named_object(tracking, context->object_name);
01618 
01619         tracksbase= &object->tracks;
01620         reconstruction= &object->reconstruction;
01621     }
01622 
01623     unit_m4(imat);
01624 
01625     track= tracksbase->first;
01626     while(track) {
01627         double pos[3];
01628 
01629         if(libmv_reporojectionPointForTrack(libmv_reconstruction, tracknr, pos)) {
01630             track->bundle_pos[0]= pos[0];
01631             track->bundle_pos[1]= pos[1];
01632             track->bundle_pos[2]= pos[2];
01633 
01634             track->flag|= TRACK_HAS_BUNDLE;
01635             track->error= libmv_reporojectionErrorForTrack(libmv_reconstruction, tracknr);
01636         } else {
01637             track->flag&= ~TRACK_HAS_BUNDLE;
01638             ok= 0;
01639 
01640             printf("No bundle for track #%d '%s'\n", tracknr, track->name);
01641         }
01642 
01643         track= track->next;
01644         tracknr++;
01645     }
01646 
01647     if(reconstruction->cameras)
01648         MEM_freeN(reconstruction->cameras);
01649 
01650     reconstruction->camnr= 0;
01651     reconstruction->cameras= NULL;
01652     reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera");
01653 
01654     for(a= sfra; a<=efra; a++) {
01655         double matd[4][4];
01656 
01657         if(libmv_reporojectionCameraForImage(libmv_reconstruction, a, matd)) {
01658             int i, j;
01659             float mat[4][4];
01660             float error= libmv_reporojectionErrorForImage(libmv_reconstruction, a);
01661 
01662             for(i=0; i<4; i++)
01663                 for(j= 0; j<4; j++)
01664                     mat[i][j]= matd[i][j];
01665 
01666             if(!origin_set) {
01667                 copy_m4_m4(imat, mat);
01668                 invert_m4(imat);
01669                 origin_set= 1;
01670             }
01671 
01672             if(origin_set)
01673                 mult_m4_m4m4(mat, imat, mat);
01674 
01675             copy_m4_m4(reconstructed[reconstruction->camnr].mat, mat);
01676             reconstructed[reconstruction->camnr].framenr= a;
01677             reconstructed[reconstruction->camnr].error= error;
01678             reconstruction->camnr++;
01679         } else {
01680             ok= 0;
01681             printf("No camera for frame %d\n", a);
01682         }
01683     }
01684 
01685     if(reconstruction->camnr) {
01686         reconstruction->cameras= MEM_callocN(reconstruction->camnr*sizeof(MovieReconstructedCamera), "reconstructed camera");
01687         memcpy(reconstruction->cameras, reconstructed, reconstruction->camnr*sizeof(MovieReconstructedCamera));
01688     }
01689 
01690     if(origin_set) {
01691         track= tracksbase->first;
01692         while(track) {
01693             if(track->flag&TRACK_HAS_BUNDLE)
01694                 mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos);
01695 
01696             track= track->next;
01697         }
01698     }
01699 
01700     MEM_freeN(reconstructed);
01701 
01702     return ok;
01703 }
01704 
01705 static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking)
01706 {
01707     /* take the intrinscis back from libmv */
01708     retrieve_libmv_reconstruct_intrinscis(context, tracking);
01709 
01710     return retrieve_libmv_reconstruct_tracks(context, tracking);
01711 }
01712 
01713 static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object)
01714 {
01715     int refine= tracking->settings.refine_camera_intrinsics;
01716     int flags= 0;
01717 
01718     if((object->flag&TRACKING_OBJECT_CAMERA)==0)
01719         return 0;
01720 
01721     if(refine&REFINE_FOCAL_LENGTH)
01722         flags|= LIBMV_REFINE_FOCAL_LENGTH;
01723 
01724     if(refine&REFINE_PRINCIPAL_POINT)
01725         flags|= LIBMV_REFINE_PRINCIPAL_POINT;
01726 
01727     if(refine&REFINE_RADIAL_DISTORTION_K1)
01728         flags|= REFINE_RADIAL_DISTORTION_K1;
01729 
01730     if(refine&REFINE_RADIAL_DISTORTION_K2)
01731         flags|= REFINE_RADIAL_DISTORTION_K2;
01732 
01733     return flags;
01734 }
01735 
01736 static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase)
01737 {
01738     int tot= 0;
01739     int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2;
01740     MovieTrackingTrack *track;
01741 
01742     track= tracksbase->first;
01743     while(track) {
01744         if(BKE_tracking_has_marker(track, frame1))
01745             if(BKE_tracking_has_marker(track, frame2))
01746                 tot++;
01747 
01748         track= track->next;
01749     }
01750 
01751     return tot;
01752 }
01753 #endif
01754 
01755 int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size)
01756 {
01757 #if WITH_LIBMV
01758     ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
01759 
01760     if(count_tracks_on_both_keyframes(tracking, tracksbase)<8) {
01761         BLI_strncpy(error_msg, "At least 8 tracks on both of keyframes are needed for reconstruction", error_size);
01762         return 0;
01763     }
01764 
01765     return 1;
01766 #else
01767     BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size);
01768     (void)tracking;
01769     (void)object;
01770 
01771     return 0;
01772 #endif
01773 }
01774 
01775 MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking,
01776             MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height)
01777 {
01778     MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data");
01779     MovieTrackingCamera *camera= &tracking->camera;
01780     ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
01781     float aspy= 1.0f/tracking->camera.pixel_aspect;
01782     int num_tracks= BLI_countlist(tracksbase);
01783     int sfra= INT_MAX, efra= INT_MIN;
01784     MovieTrackingTrack *track;
01785 
01786     BLI_strncpy(context->object_name, object->name, sizeof(context->object_name));
01787     context->is_camera = object->flag&TRACKING_OBJECT_CAMERA;
01788 
01789     context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0);
01790 
01791     track= tracksbase->first;
01792     while(track) {
01793         int first= 0, last= track->markersnr-1;
01794         MovieTrackingMarker *first_marker= &track->markers[0];
01795         MovieTrackingMarker *last_marker= &track->markers[track->markersnr-1];
01796 
01797         /* find first not-disabled marker */
01798         while(first<=track->markersnr-1 && first_marker->flag&MARKER_DISABLED) {
01799             first++;
01800             first_marker++;
01801         }
01802 
01803         /* find last not-disabled marker */
01804         while(last>=0 && last_marker->flag&MARKER_DISABLED) {
01805             last--;
01806             last_marker--;
01807         }
01808 
01809         if(first<track->markersnr-1)
01810             sfra= MIN2(sfra, first_marker->framenr);
01811 
01812         if(last>=0)
01813             efra= MAX2(efra, last_marker->framenr);
01814 
01815         tracks_map_insert(context->tracks_map, track, NULL);
01816 
01817         track= track->next;
01818     }
01819 
01820     context->sfra= sfra;
01821     context->efra= efra;
01822 
01823 #ifdef WITH_LIBMV
01824     context->tracks= create_libmv_tracks(tracksbase, width, height*aspy);
01825     context->keyframe1= keyframe1;
01826     context->keyframe2= keyframe2;
01827     context->refine_flags= get_refine_intrinsics_flags(tracking, object);
01828 #else
01829     (void) width;
01830     (void) height;
01831     (void) keyframe1;
01832     (void) keyframe2;
01833 #endif
01834 
01835     context->focal_length= camera->focal;
01836     context->principal_point[0]= camera->principal[0];
01837     context->principal_point[1]= camera->principal[1]*aspy;
01838 
01839     context->k1= camera->k1;
01840     context->k2= camera->k2;
01841     context->k2= camera->k2;
01842 
01843     return context;
01844 }
01845 
01846 void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context)
01847 {
01848 #ifdef WITH_LIBMV
01849     if(context->reconstruction)
01850             libmv_destroyReconstruction(context->reconstruction);
01851 
01852     libmv_tracksDestroy(context->tracks);
01853 #endif
01854 
01855     tracks_map_free(context->tracks_map, NULL);
01856 
01857     MEM_freeN(context);
01858 }
01859 
01860 #ifdef WITH_LIBMV
01861 static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message)
01862 {
01863     ReconstructProgressData *progressdata= customdata;
01864 
01865     if(progressdata->progress) {
01866         *progressdata->progress= progress;
01867         *progressdata->do_update= 1;
01868     }
01869 
01870     BLI_snprintf(progressdata->stats_message, progressdata->message_size,
01871             "Solving camera | %s", message);
01872 }
01873 #endif
01874 
01875 #if 0
01876 static int solve_reconstruction_testbreak_cb(void *customdata)
01877 {
01878     ReconstructProgressData *progressdata= customdata;
01879 
01880     if(progressdata->stop && *progressdata->stop)
01881         return 1;
01882 
01883     return G.afbreek;
01884 }
01885 #endif
01886 
01887 void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop,
01888             short *do_update, float *progress, char *stats_message, int message_size)
01889 {
01890 #ifdef WITH_LIBMV
01891     float error;
01892 
01893     ReconstructProgressData progressdata;
01894 
01895     progressdata.stop= stop;
01896     progressdata.do_update= do_update;
01897     progressdata.progress= progress;
01898     progressdata.stats_message= stats_message;
01899     progressdata.message_size= message_size;
01900 
01901     context->reconstruction = libmv_solveReconstruction(context->tracks,
01902         context->keyframe1, context->keyframe2,
01903         context->refine_flags,
01904         context->focal_length,
01905         context->principal_point[0], context->principal_point[1],
01906         context->k1, context->k2, context->k3,
01907         solve_reconstruction_update_cb, &progressdata);
01908 
01909     error= libmv_reprojectionError(context->reconstruction);
01910 
01911     context->reprojection_error= error;
01912 #else
01913     (void) context;
01914     (void) stop;
01915     (void) do_update;
01916     (void) progress;
01917     (void) stats_message;
01918     (void) message_size;
01919 #endif
01920 }
01921 
01922 int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking)
01923 {
01924     MovieTrackingReconstruction *reconstruction;
01925 
01926     tracks_map_merge(context->tracks_map, tracking);
01927 
01928     if(context->is_camera) {
01929         reconstruction= &tracking->reconstruction;
01930     }
01931     else {
01932         MovieTrackingObject *object;
01933 
01934         object= BKE_tracking_named_object(tracking, context->object_name);
01935         reconstruction= &object->reconstruction;
01936     }
01937 
01938     reconstruction->error= context->reprojection_error;
01939     reconstruction->flag|= TRACKING_RECONSTRUCTED;
01940 
01941 #ifdef WITH_LIBMV
01942     if(!retrieve_libmv_reconstruct(context, tracking))
01943         return 0;
01944 #endif
01945 
01946     return 1;
01947 }
01948 
01949 void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
01950 {
01951     BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
01952 }
01953 
01954 MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name)
01955 {
01956     ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
01957     MovieTrackingTrack *track= tracksbase->first;
01958 
01959     while(track) {
01960         if(!strcmp(track->name, name))
01961             return track;
01962 
01963         track= track->next;
01964     }
01965 
01966     return NULL;
01967 }
01968 
01969 static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest)
01970 {
01971     MovieReconstructedCamera *cameras= reconstruction->cameras;
01972     int a= 0, d= 1;
01973 
01974     if(!reconstruction->camnr)
01975         return -1;
01976 
01977     if(framenr<cameras[0].framenr) {
01978         if(nearest) return 0;
01979         else return -1;
01980     }
01981 
01982     if(framenr>cameras[reconstruction->camnr-1].framenr) {
01983         if(nearest) return reconstruction->camnr-1;
01984         else return -1;
01985     }
01986 
01987     if(reconstruction->last_camera<reconstruction->camnr)
01988         a= reconstruction->last_camera;
01989 
01990     if(cameras[a].framenr>=framenr)
01991         d= -1;
01992 
01993     while(a>=0 && a<reconstruction->camnr) {
01994         int cfra= cameras[a].framenr;
01995 
01996         /* check if needed framenr was "skipped" -- no data for requested frame */
01997 
01998         if(d>0 && cfra>framenr) {
01999             /* interpolate with previous position */
02000             if(nearest) return a-1;
02001             else break;
02002         }
02003 
02004         if(d<0 && cfra<framenr) {
02005             /* interpolate with next position */
02006             if(nearest) return a;
02007             else break;
02008         }
02009 
02010         if(cfra==framenr) {
02011             reconstruction->last_camera= a;
02012 
02013             return a;
02014         }
02015 
02016         a+= d;
02017     }
02018 
02019     return -1;
02020 }
02021 
02022 static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4])
02023 {
02024     if((object->flag&TRACKING_OBJECT_CAMERA)==0) {
02025         float smat[4][4];
02026 
02027         scale_m4_fl(smat, 1.0f/object->scale);
02028         mult_m4_m4m4(mat, mat, smat);
02029     }
02030 }
02031 
02032 MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking,
02033             MovieTrackingObject *object, int framenr)
02034 {
02035     MovieTrackingReconstruction *reconstruction;
02036     int a;
02037 
02038     reconstruction= BKE_tracking_object_reconstruction(tracking, object);
02039     a= reconstruction_camera_index(reconstruction, framenr, 0);
02040 
02041     if(a==-1)
02042         return NULL;
02043 
02044     return &reconstruction->cameras[a];
02045 }
02046 
02047 void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object,
02048             int framenr, float mat[4][4])
02049 {
02050     MovieTrackingReconstruction *reconstruction;
02051     MovieReconstructedCamera *cameras;
02052     int a;
02053 
02054     reconstruction= BKE_tracking_object_reconstruction(tracking, object);
02055     cameras= reconstruction->cameras;
02056     a= reconstruction_camera_index(reconstruction, framenr, 1);
02057 
02058     if(a==-1) {
02059         unit_m4(mat);
02060         return;
02061     }
02062 
02063     if(cameras[a].framenr!=framenr && a>0 && a<reconstruction->camnr-1) {
02064         float t= ((float)framenr-cameras[a].framenr) / (cameras[a+1].framenr-cameras[a].framenr);
02065 
02066         blend_m4_m4m4(mat, cameras[a].mat, cameras[a+1].mat, t);
02067     } else {
02068         copy_m4_m4(mat, cameras[a].mat);
02069     }
02070 
02071     scale_reconstructed_camera(object, mat);
02072 }
02073 
02074 void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4])
02075 {
02076     if(!ob) {
02077         if(scene->camera) ob= scene->camera;
02078         else ob= scene_find_camera(scene);
02079     }
02080 
02081     if(ob)
02082         where_is_object_mat(scene, ob, mat);
02083     else
02084         unit_m4(mat);
02085 }
02086 
02087 void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
02088 {
02089     *shiftx= (0.5f*winx-tracking->camera.principal[0]) / winx;
02090     *shifty= (0.5f*winy-tracking->camera.principal[1]) / winx;
02091 }
02092 
02093 void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
02094 {
02095     float focal= tracking->camera.focal;
02096 
02097     camera->sensor_x= tracking->camera.sensor_width;
02098     camera->sensor_fit= CAMERA_SENSOR_FIT_AUTO;
02099     camera->lens= focal*camera->sensor_x/width;
02100 
02101     scene->r.xsch= width*tracking->camera.pixel_aspect;
02102     scene->r.ysch= height;
02103 
02104     scene->r.xasp= 1.0f;
02105     scene->r.yasp= 1.0f;
02106 
02107     BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty);
02108 }
02109 
02110 void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object,
02111             int framenr, int winx, int winy, float mat[4][4])
02112 {
02113     MovieReconstructedCamera *camera;
02114     float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx;
02115     float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
02116     float winmat[4][4];
02117     float ycor= 1.0f/tracking->camera.pixel_aspect;
02118     float shiftx, shifty, winside= MAX2(winx, winy);
02119 
02120     BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty);
02121 
02122     clipsta= 0.1f;
02123     clipend= 1000.0f;
02124 
02125     if(winx >= winy)
02126         viewfac= (lens*winx)/tracking->camera.sensor_width;
02127     else
02128         viewfac= (ycor*lens*winy)/tracking->camera.sensor_width;
02129 
02130     pixsize= clipsta/viewfac;
02131 
02132     left= -0.5f*(float)winx + shiftx*winside;
02133     bottom= -0.5f*(ycor)*(float)winy + shifty*winside;
02134     right=  0.5f*(float)winx + shiftx*winside;
02135     top=  0.5f*(ycor)*(float)winy + shifty*winside;
02136 
02137     left *= pixsize;
02138     right *= pixsize;
02139     bottom *= pixsize;
02140     top *= pixsize;
02141 
02142     perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
02143 
02144     camera= BKE_tracking_get_reconstructed_camera(tracking, object, framenr);
02145 
02146     if(camera) {
02147         float imat[4][4];
02148 
02149         invert_m4_m4(imat, camera->mat);
02150         mult_m4_m4m4(mat, winmat, imat);
02151     } else copy_m4_m4(mat, winmat);
02152 }
02153 
02154 ListBase *BKE_tracking_get_tracks(MovieTracking *tracking)
02155 {
02156     MovieTrackingObject *object= BKE_tracking_active_object(tracking);
02157 
02158     if(object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
02159         return &object->tracks;
02160     }
02161 
02162     return &tracking->tracks;
02163 }
02164 
02165 MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking)
02166 {
02167     ListBase *tracksbase;
02168 
02169     if(!tracking->act_track)
02170         return NULL;
02171 
02172     tracksbase= BKE_tracking_get_tracks(tracking);
02173 
02174     /* check that active track is in current tracks list */
02175     if(BLI_findindex(tracksbase, tracking->act_track) >= 0)
02176         return tracking->act_track;
02177 
02178     return NULL;
02179 }
02180 
02181 MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking)
02182 {
02183     return BLI_findlink(&tracking->objects, tracking->objectnr);
02184 }
02185 
02186 MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking)
02187 {
02188     MovieTrackingObject *object= tracking->objects.first;
02189 
02190     while(object) {
02191         if(object->flag & TRACKING_OBJECT_CAMERA)
02192             return object;
02193 
02194         object= object->next;
02195     }
02196 
02197     return NULL;
02198 }
02199 
02200 ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object)
02201 {
02202     if(object->flag & TRACKING_OBJECT_CAMERA) {
02203         return &tracking->tracks;
02204     }
02205 
02206     return &object->tracks;
02207 }
02208 
02209 MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object)
02210 {
02211     if(object->flag & TRACKING_OBJECT_CAMERA) {
02212         return &tracking->reconstruction;
02213     }
02214 
02215     return &object->reconstruction;
02216 }
02217 
02218 MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking)
02219 {
02220     MovieTrackingObject *object= BKE_tracking_active_object(tracking);
02221 
02222     return BKE_tracking_object_reconstruction(tracking, object);
02223 }
02224 
02225 void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
02226 {
02227     MovieTrackingCamera *camera= &tracking->camera;
02228 
02229 #ifdef WITH_LIBMV
02230     double x, y;
02231     float aspy= 1.0f/tracking->camera.pixel_aspect;
02232 
02233     /* normalize coords */
02234     x= (co[0]-camera->principal[0]) / camera->focal;
02235     y= (co[1]-camera->principal[1] * aspy) / camera->focal;
02236 
02237     libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
02238                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
02239 
02240     /* result is in image coords already */
02241     nco[0]= x;
02242     nco[1]= y;
02243 #else
02244     (void)camera;
02245     (void)co;
02246     (void)nco;
02247 #endif
02248 }
02249 
02250 void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2])
02251 {
02252     MovieTrackingCamera *camera= &tracking->camera;
02253 
02254 #ifdef WITH_LIBMV
02255     double x= co[0], y= co[1];
02256     float aspy= 1.0f/tracking->camera.pixel_aspect;
02257 
02258     libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
02259                 camera->k1, camera->k2, camera->k3, x, y, &x, &y);
02260 
02261     nco[0]= x * camera->focal + camera->principal[0];
02262     nco[1]= y * camera->focal + camera->principal[1] * aspy;
02263 #else
02264     (void)camera;
02265     (void)co;
02266     (void)nco;
02267 #endif
02268 }
02269 
02270 #ifdef WITH_LIBMV
02271 static int point_in_stroke(bGPDstroke *stroke, float x, float y)
02272 {
02273     int i, prev;
02274     int count= 0;
02275     bGPDspoint *points= stroke->points;
02276 
02277     prev= stroke->totpoints-1;
02278 
02279     for(i= 0; i<stroke->totpoints; i++) {
02280         if((points[i].y<y && points[prev].y>=y) || (points[prev].y<y && points[i].y>=y)) {
02281             float fac= (y-points[i].y)/(points[prev].y-points[i].y);
02282 
02283             if (points[i].x+fac*(points[prev].x-points[i].x)<x)
02284                 count++;
02285         }
02286 
02287         prev= i;
02288     }
02289 
02290     return count%2;
02291 }
02292 
02293 static int point_in_layer(bGPDlayer *layer, float x, float y)
02294 {
02295     bGPDframe *frame= layer->frames.first;
02296 
02297     while(frame) {
02298         bGPDstroke *stroke= frame->strokes.first;
02299         while(stroke) {
02300             if(point_in_stroke(stroke, x, y))
02301                 return 1;
02302 
02303             stroke= stroke->next;
02304         }
02305         frame= frame->next;
02306     }
02307 
02308     return 0;
02309 }
02310 
02311 static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase,
02312             struct libmv_Features *features, int framenr, int width, int height,
02313             bGPDlayer *layer, int place_outside_layer)
02314 {
02315     int a;
02316 
02317     a= libmv_countFeatures(features);
02318     while(a--) {
02319         MovieTrackingTrack *track;
02320         double x, y, size, score;
02321         int ok= 1;
02322         float xu, yu;
02323 
02324         libmv_getFeature(features, a, &x, &y, &score, &size);
02325 
02326         xu= x/width;
02327         yu= y/height;
02328 
02329         if(layer)
02330             ok= point_in_layer(layer, xu, yu)!=place_outside_layer;
02331 
02332         if(ok) {
02333             track= BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height);
02334             track->flag|= SELECT;
02335             track->pat_flag|= SELECT;
02336             track->search_flag|= SELECT;
02337         }
02338     }
02339 }
02340 #endif
02341 
02342 void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf,
02343             int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer,
02344             int place_outside_layer)
02345 {
02346 #ifdef WITH_LIBMV
02347     struct libmv_Features *features;
02348     unsigned char *pixels= get_ucharbuf(ibuf);
02349 
02350     features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x,
02351             margin, min_trackness, min_distance);
02352 
02353     MEM_freeN(pixels);
02354 
02355     retrieve_libmv_features(tracking, tracksbase, features, framenr,
02356             ibuf->x, ibuf->y, layer, place_outside_layer);
02357 
02358     libmv_destroyFeatures(features);
02359 #else
02360     (void)tracking;
02361     (void)tracksbase;
02362     (void)ibuf;
02363     (void)framenr;
02364     (void)margin;
02365     (void)min_trackness;
02366     (void)min_distance;
02367     (void)layer;
02368     (void)place_outside_layer;
02369 #endif
02370 }
02371 
02372 MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r)
02373 {
02374     MovieTrackingObject *object;
02375     int cur= 1;
02376 
02377     object= tracking->objects.first;
02378     while(object) {
02379         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
02380         MovieTrackingTrack *track= tracksbase->first;
02381 
02382         while(track) {
02383             if(track->flag&TRACK_HAS_BUNDLE) {
02384                 if(cur==tracknr) {
02385                     *tracksbase_r= tracksbase;
02386                     return track;
02387                 }
02388 
02389                 cur++;
02390             }
02391 
02392             track= track->next;
02393         }
02394 
02395         object= object->next;
02396     }
02397 
02398     *tracksbase_r= NULL;
02399 
02400     return NULL;
02401 }
02402 
02403 static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2])
02404 {
02405     int ok= 0;
02406     float min[2], max[2];
02407     MovieTrackingTrack *track;
02408 
02409     INIT_MINMAX2(min, max);
02410 
02411     (void) tracking;
02412 
02413     track= tracking->tracks.first;
02414     while(track) {
02415         if(track->flag&TRACK_USE_2D_STAB) {
02416             MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr);
02417 
02418             DO_MINMAX2(marker->pos, min, max);
02419 
02420             ok= 1;
02421         }
02422 
02423         track= track->next;
02424     }
02425 
02426     median[0]= (max[0]+min[0])/2.0f;
02427     median[1]= (max[1]+min[1])/2.0f;
02428 
02429     return ok;
02430 }
02431 
02432 static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height,
02433             float firstmedian[2], float median[2], float loc[2], float *scale, float *angle)
02434 {
02435     MovieTrackingStabilization *stab= &tracking->stabilization;
02436 
02437     *scale= (stab->scale-1.0f)*stab->scaleinf+1.0f;
02438     *angle= 0.0f;
02439 
02440     loc[0]= (firstmedian[0]-median[0])*width*(*scale);
02441     loc[1]= (firstmedian[1]-median[1])*height*(*scale);
02442 
02443     mul_v2_fl(loc, stab->locinf);
02444 
02445     if((stab->flag&TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) {
02446         MovieTrackingMarker *marker;
02447         float a[2], b[2];
02448         float x0= (float)width/2.0f, y0= (float)height/2.0f;
02449         float x= median[0]*width, y= median[1]*height;
02450 
02451         marker= BKE_tracking_get_marker(stab->rot_track, 1);
02452         sub_v2_v2v2(a, marker->pos, firstmedian);
02453         a[0]*= width;
02454         a[1]*= height;
02455 
02456         marker= BKE_tracking_get_marker(stab->rot_track, framenr);
02457         sub_v2_v2v2(b, marker->pos, median);
02458         b[0]*= width;
02459         b[1]*= height;
02460 
02461         *angle= -atan2(a[0]*b[1]-a[1]*b[0], a[0]*b[0]+a[1]*b[1]);
02462         *angle*= stab->rotinf;
02463 
02464         /* convert to rotation around image center */
02465         loc[0]-= (x0 + (x-x0)*cosf(*angle)-(y-y0)*sinf(*angle) - x)*(*scale);
02466         loc[1]-= (y0 + (x-x0)*sinf(*angle)+(y-y0)*cosf(*angle) - y)*(*scale);
02467     }
02468 }
02469 
02470 static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height)
02471 {
02472     float firstmedian[2];
02473     MovieTrackingStabilization *stab= &tracking->stabilization;
02474 
02475     if(stab->ok)
02476         return stab->scale;
02477 
02478     if(stabilization_median_point(tracking, 1, firstmedian)) {
02479         int sfra= INT_MAX, efra= INT_MIN, cfra;
02480         float delta[2]= {0.0f, 0.0f}, scalex= 1.0f, scaley= 1.0f;
02481         MovieTrackingTrack *track;
02482 
02483         stab->scale= 1.0f;
02484 
02485         track= tracking->tracks.first;
02486         while(track) {
02487             if(track->flag&TRACK_USE_2D_STAB ||
02488                ((stab->flag&TRACKING_STABILIZE_ROTATION) && track==stab->rot_track)) {
02489                 sfra= MIN2(sfra, track->markers[0].framenr);
02490                 efra= MAX2(efra, track->markers[track->markersnr-1].framenr);
02491             }
02492 
02493             track= track->next;
02494         }
02495 
02496         for(cfra=sfra; cfra<=efra; cfra++) {
02497             float median[2], near[2];
02498             float loc[2], scale, angle;
02499 
02500             stabilization_median_point(tracking, cfra, median);
02501 
02502             calculate_stabdata(tracking, cfra, width, height, firstmedian, median,
02503                         loc, &scale, &angle);
02504 
02505             if(angle==0.0f) {
02506                 loc[0]= fabsf(loc[0]);
02507                 loc[1]= fabsf(loc[1]);
02508 
02509                 delta[0]= MAX2(delta[0], loc[0]);
02510                 delta[1]= MAX2(delta[1], loc[1]);
02511 
02512                 near[0]= MIN2(median[0], 1.0f-median[0]);
02513                 near[1]= MIN2(median[1], 1.0f-median[1]);
02514                 near[0]= MAX2(near[0], 0.05f);
02515                 near[1]= MAX2(near[1], 0.05f);
02516 
02517                 scalex= 1.0f+delta[0]/(near[0]*width);
02518                 scaley= 1.0f+delta[1]/(near[1]*height);
02519             } else {
02520                 int i;
02521                 float mat[4][4];
02522                 float points[4][2]={{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}};
02523 
02524                 BKE_tracking_stabdata_to_mat4(width, height, loc, scale, angle, mat);
02525 
02526                 for(i= 0; i<4; i++) {
02527                     int j;
02528                     float a[3]= {0.0f, 0.0f, 0.0f}, b[3]= {0.0f, 0.0f, 0.0f};
02529 
02530                     copy_v3_v3(a, points[i]);
02531                     copy_v3_v3(b, points[(i+1)%4]);
02532 
02533                     mul_m4_v3(mat, a);
02534                     mul_m4_v3(mat, b);
02535 
02536                     for(j= 0; j<4; j++) {
02537                         float point[3]= {points[j][0], points[j][1], 0.0f};
02538                         float v1[3], v2[3];
02539 
02540                         sub_v3_v3v3(v1, b, a);
02541                         sub_v3_v3v3(v2, point, a);
02542 
02543                         if(cross_v2v2(v1, v2) >= 0.0f) {
02544                             float dist= dist_to_line_v2(point, a, b);
02545                             if(i%2==0) {
02546                                 scalex= MAX2(scalex, (width+2*dist)/width);
02547                             } else {
02548                                 scaley= MAX2(scaley, (height+2*dist)/height);
02549                             }
02550                         }
02551                     }
02552                 }
02553             }
02554         }
02555 
02556         stab->scale= MAX2(scalex, scaley);
02557 
02558         if(stab->maxscale>0.0f)
02559             stab->scale= MIN2(stab->scale, stab->maxscale);
02560     } else {
02561         stab->scale= 1.0f;
02562     }
02563 
02564     stab->ok= 1;
02565 
02566     return stab->scale;
02567 }
02568 
02569 static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill)
02570 {
02571     int flags;
02572 
02573     if(cacheibuf && (cacheibuf->x != srcibuf->x || cacheibuf->y != srcibuf->y)) {
02574         IMB_freeImBuf(cacheibuf);
02575         cacheibuf= NULL;
02576     }
02577 
02578     flags= IB_rect;
02579 
02580     if(srcibuf->rect_float)
02581         flags|= IB_rectfloat;
02582 
02583     if(cacheibuf) {
02584         if(fill) {
02585             float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
02586             IMB_rectfill(cacheibuf, col);
02587         }
02588     }
02589     else {
02590         cacheibuf= IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags);
02591         cacheibuf->profile= srcibuf->profile;
02592     }
02593 
02594     return cacheibuf;
02595 }
02596 
02597 void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle)
02598 {
02599     float firstmedian[2], median[2];
02600     MovieTrackingStabilization *stab= &tracking->stabilization;
02601 
02602     if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
02603         zero_v2(loc);
02604         *scale= 1.0f;
02605         *angle= 0.0f;
02606 
02607         return;
02608     }
02609 
02610     if(stabilization_median_point(tracking, 1, firstmedian)) {
02611         stabilization_median_point(tracking, framenr, median);
02612 
02613         if((stab->flag&TRACKING_AUTOSCALE)==0)
02614             stab->scale= 1.0f;
02615 
02616         if(!stab->ok) {
02617             if(stab->flag&TRACKING_AUTOSCALE)
02618                 stabilization_auto_scale_factor(tracking, width, height);
02619 
02620             calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
02621 
02622             stab->ok= 1;
02623         } else {
02624             calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle);
02625         }
02626     } else {
02627         zero_v2(loc);
02628         *scale= 1.0f;
02629         *angle= 0.0f;
02630     }
02631 }
02632 
02633 ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, float loc[2], float *scale, float *angle)
02634 {
02635     float tloc[2], tscale, tangle;
02636     MovieTrackingStabilization *stab= &tracking->stabilization;
02637     ImBuf *tmpibuf;
02638     float width= ibuf->x, height= ibuf->y;
02639 
02640     if(loc)     copy_v2_v2(tloc, loc);
02641     if(scale)   tscale= *scale;
02642 
02643     if((stab->flag&TRACKING_2D_STABILIZATION)==0) {
02644         if(loc)     zero_v2(loc);
02645         if(scale)   *scale= 1.0f;
02646 
02647         return ibuf;
02648     }
02649 
02650     BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle);
02651 
02652     tmpibuf= stabilize_alloc_ibuf(NULL, ibuf, 1);
02653 
02654     /* scale would be handled by matrix transformation when angle is non-zero */
02655     if(tscale!=1.0f && tangle==0.0f) {
02656         ImBuf *scaleibuf;
02657 
02658         stabilization_auto_scale_factor(tracking, width, height);
02659 
02660         scaleibuf= stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0);
02661         stab->scaleibuf= scaleibuf;
02662 
02663         IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
02664         IMB_scalefastImBuf(scaleibuf, ibuf->x*tscale, ibuf->y*tscale);
02665 
02666         ibuf= scaleibuf;
02667     }
02668 
02669     if(tangle==0.0f) {
02670         /* if angle is zero, then it's much faster to use rect copy
02671            but could be issues with subpixel precisions */
02672         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);
02673     } else {
02674         float mat[4][4];
02675         int i, j;
02676 
02677         BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, tloc, tscale, tangle, mat);
02678         invert_m4(mat);
02679 
02680         for(j=0; j<tmpibuf->y; j++) {
02681             for(i=0; i<tmpibuf->x;i++) {
02682                 float vec[3]= {i, j, 0};
02683 
02684                 mul_v3_m4v3(vec, mat, vec);
02685 
02686                 /* TODO: add selector for interpolation method */
02687                 neareast_interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j);
02688             }
02689         }
02690     }
02691 
02692     tmpibuf->userflags|= IB_MIPMAP_INVALID;
02693 
02694     if(tmpibuf->rect_float)
02695         tmpibuf->userflags|= IB_RECT_INVALID;
02696 
02697     if(loc)     copy_v2_v2(loc, tloc);
02698     if(scale)   *scale= tscale;
02699     if(angle)   *angle= tangle;
02700 
02701     return tmpibuf;
02702 }
02703 
02704 void BKE_tracking_stabdata_to_mat4(int width, int height, float loc[2], float scale, float angle, float mat[4][4])
02705 {
02706     float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
02707     float svec[3]= {scale, scale, scale};
02708 
02709     unit_m4(rmat);
02710     unit_m4(lmat);
02711     unit_m4(smat);
02712     unit_m4(cmat);
02713 
02714     /* image center as rotation center */
02715     cmat[3][0]= (float)width/2.0f;
02716     cmat[3][1]= (float)height/2.0f;
02717     invert_m4_m4(icmat, cmat);
02718 
02719     size_to_mat4(smat, svec);       /* scale matrix */
02720     add_v2_v2(lmat[3], loc);        /* tranlation matrix */
02721     rotate_m4(rmat, 'Z', angle);    /* rotation matrix */
02722 
02723     /* compose transformation matrix */
02724     mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);
02725 }
02726 
02727 MovieDistortion *BKE_tracking_distortion_create(void)
02728 {
02729     MovieDistortion *distortion;
02730 
02731     distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
02732 
02733     return distortion;
02734 }
02735 
02736 MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion)
02737 {
02738     MovieDistortion *new_distortion;
02739 
02740     new_distortion= MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
02741 
02742 #ifdef WITH_LIBMV
02743     new_distortion->intrinsics= libmv_CameraIntrinsicsCopy(distortion->intrinsics);
02744 #else
02745     (void)distortion;
02746 #endif
02747 
02748     return new_distortion;
02749 }
02750 
02751 void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height)
02752 {
02753     MovieTrackingCamera *camera= &tracking->camera;
02754     float aspy= 1.0f/tracking->camera.pixel_aspect;
02755 
02756 #ifdef WITH_LIBMV
02757     if(!distortion->intrinsics) {
02758         distortion->intrinsics= libmv_CameraIntrinsicsNew(camera->focal,
02759                 camera->principal[0], camera->principal[1] * aspy,
02760                 camera->k1, camera->k2, camera->k3, width, height * aspy);
02761     } else {
02762         libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
02763                 camera->principal[0], camera->principal[1] * aspy,
02764                 camera->k1, camera->k2, camera->k3, width, height * aspy);
02765     }
02766 #else
02767     (void)distortion;
02768     (void)width;
02769     (void)height;
02770     (void)camera;
02771     (void)aspy;
02772 #endif
02773 }
02774 
02775 ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking,
02776             ImBuf *ibuf, int width, int height, float overscan, int undistort)
02777 {
02778     ImBuf *resibuf;
02779 
02780     BKE_tracking_distortion_update(distortion, tracking, width, height);
02781 
02782     resibuf= IMB_dupImBuf(ibuf);
02783 
02784     if(ibuf->rect_float) {
02785 #ifdef WITH_LIBMV
02786         if(undistort) {
02787             libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics,
02788                         ibuf->rect_float, resibuf->rect_float,
02789                         ibuf->x, ibuf->y, overscan, ibuf->channels);
02790         } else {
02791             libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics,
02792                         ibuf->rect_float, resibuf->rect_float,
02793                         ibuf->x, ibuf->y, overscan, ibuf->channels);
02794         }
02795 #endif
02796 
02797         ibuf->userflags|= IB_RECT_INVALID;
02798     } else {
02799 #ifdef WITH_LIBMV
02800         if(undistort) {
02801                 libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics,
02802                             (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
02803                             ibuf->x, ibuf->y, overscan, ibuf->channels);
02804         } else {
02805             libmv_CameraIntrinsicsDistortByte(distortion->intrinsics,
02806                         (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect,
02807                         ibuf->x, ibuf->y, overscan, ibuf->channels);
02808         }
02809 #endif
02810     }
02811 
02812 #ifndef WITH_LIBMV
02813     (void)overscan;
02814     (void)undistort;
02815 #endif
02816 
02817     return resibuf;
02818 }
02819 
02820 void BKE_tracking_distortion_destroy(MovieDistortion *distortion)
02821 {
02822 #ifdef WITH_LIBMV
02823     libmv_CameraIntrinsicsDestroy(distortion->intrinsics);
02824 #endif
02825 
02826     MEM_freeN(distortion);
02827 }
02828 
02829 ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
02830 {
02831     MovieTrackingCamera *camera= &tracking->camera;
02832 
02833     if(camera->intrinsics == NULL)
02834         camera->intrinsics= BKE_tracking_distortion_create();
02835 
02836     return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1);
02837 }
02838 
02839 ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan)
02840 {
02841     MovieTrackingCamera *camera= &tracking->camera;
02842 
02843     if(camera->intrinsics == NULL)
02844         camera->intrinsics= BKE_tracking_distortion_create();
02845 
02846     return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0);
02847 }
02848 
02849 /* area - which part of marker should be selected. see TRACK_AREA_* constants */
02850 void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend)
02851 {
02852     if(extend) {
02853         BKE_tracking_track_flag(track, area, SELECT, 0);
02854     } else {
02855         MovieTrackingTrack *cur= tracksbase->first;
02856 
02857         while(cur) {
02858             if(cur==track) {
02859                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
02860                 BKE_tracking_track_flag(cur, area, SELECT, 0);
02861             }
02862             else {
02863                 BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1);
02864             }
02865 
02866             cur= cur->next;
02867         }
02868     }
02869 }
02870 
02871 void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area)
02872 {
02873     BKE_tracking_track_flag(track, area, SELECT, 1);
02874 }
02875 
02876 MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name)
02877 {
02878     MovieTrackingObject *object= MEM_callocN(sizeof(MovieTrackingObject), "tracking object");
02879 
02880     if(tracking->tot_object==0) {
02881         /* first object is always camera */
02882         BLI_strncpy(object->name, "Camera", sizeof(object->name));
02883 
02884         object->flag|= TRACKING_OBJECT_CAMERA;
02885     }
02886     else {
02887         BLI_strncpy(object->name, name, sizeof(object->name));
02888     }
02889 
02890     BLI_addtail(&tracking->objects, object);
02891 
02892     tracking->tot_object++;
02893     tracking->objectnr= BLI_countlist(&tracking->objects) - 1;
02894 
02895     BKE_tracking_object_unique_name(tracking, object);
02896 
02897     return object;
02898 }
02899 
02900 void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object)
02901 {
02902     MovieTrackingTrack *track;
02903     int index= BLI_findindex(&tracking->objects, object);
02904 
02905     if(index<0)
02906         return;
02907 
02908     if(object->flag & TRACKING_OBJECT_CAMERA) {
02909         /* object used for camera solving can't be deleted */
02910         return;
02911     }
02912 
02913     track= object->tracks.first;
02914     while(track) {
02915         if(track==tracking->act_track)
02916             tracking->act_track= NULL;
02917 
02918         track= track->next;
02919     }
02920 
02921     tracking_object_free(object);
02922     BLI_freelinkN(&tracking->objects, object);
02923 
02924     tracking->tot_object--;
02925 
02926     if(index>0)
02927         tracking->objectnr= index-1;
02928     else
02929         tracking->objectnr= 0;
02930 }
02931 
02932 void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object)
02933 {
02934     BLI_uniquename(&tracking->objects, object, "Object", '.', offsetof(MovieTrackingObject, name), sizeof(object->name));
02935 }
02936 
02937 MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name)
02938 {
02939     MovieTrackingObject *object= tracking->objects.first;
02940 
02941     while(object) {
02942         if(!strcmp(object->name, name))
02943             return object;
02944 
02945         object= object->next;
02946     }
02947 
02948     return NULL;
02949 }