diff options
Diffstat (limited to 'source/blender/blenkernel/intern/tracking.c')
-rw-r--r-- | source/blender/blenkernel/intern/tracking.c | 3038 |
1 files changed, 1561 insertions, 1477 deletions
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 0aa0d36c537..43fe94d625b 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -76,7 +76,191 @@ static struct { ListBase tracks; } tracking_clipboard; -/*********************** space transformation functions *************************/ +/*********************** Common functions *************************/ + +static MovieTrackingTrack *tracking_track_duplicate(MovieTrackingTrack *track) +{ + MovieTrackingTrack *new_track; + + new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track"); + + *new_track = *track; + new_track->next = new_track->prev = NULL; + + new_track->markers = MEM_dupallocN(new_track->markers); + + return new_track; +} + +static void tracking_tracks_free(ListBase *tracks) +{ + MovieTrackingTrack *track; + + for (track = tracks->first; track; track = track->next) { + BKE_tracking_track_free(track); + } + + BLI_freelistN(tracks); +} + +static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction) +{ + if (reconstruction->cameras) + MEM_freeN(reconstruction->cameras); +} + +static void tracking_object_free(MovieTrackingObject *object) +{ + tracking_tracks_free(&object->tracks); + tracking_reconstruction_free(&object->reconstruction); +} + +static void tracking_objects_free(ListBase *objects) +{ + MovieTrackingObject *object; + + for (object = objects->first; object; object = object->next) + tracking_object_free(object); + + BLI_freelistN(objects); +} + +static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) +{ + MovieTrackingDopesheetChannel *channel; + + channel = dopesheet->channels.first; + while (channel) { + if (channel->segments) { + MEM_freeN(channel->segments); + } + + channel = channel->next; + } + + BLI_freelistN(&dopesheet->channels); + + dopesheet->channels.first = dopesheet->channels.last = NULL; + dopesheet->tot_channel = 0; +} + +void BKE_tracking_free(MovieTracking *tracking) +{ + tracking_tracks_free(&tracking->tracks); + tracking_reconstruction_free(&tracking->reconstruction); + tracking_objects_free(&tracking->objects); + + if (tracking->stabilization.scaleibuf) + IMB_freeImBuf(tracking->stabilization.scaleibuf); + + if (tracking->camera.intrinsics) + BKE_tracking_distortion_free(tracking->camera.intrinsics); + + tracking_dopesheet_free(&tracking->dopesheet); +} + +void BKE_tracking_settings_init(MovieTracking *tracking) +{ + tracking->camera.sensor_width = 35.0f; + tracking->camera.pixel_aspect = 1.0f; + tracking->camera.units = CAMERA_UNITS_MM; + + tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION; + tracking->settings.default_minimum_correlation = 0.75; + tracking->settings.default_pattern_size = 11; + tracking->settings.default_search_size = 61; + tracking->settings.keyframe1 = 1; + tracking->settings.keyframe2 = 30; + tracking->settings.dist = 1; + tracking->settings.object_distance = 1; + + tracking->stabilization.scaleinf = 1.0f; + tracking->stabilization.locinf = 1.0f; + tracking->stabilization.rotinf = 1.0f; + tracking->stabilization.maxscale = 2.0f; + + BKE_tracking_object_add(tracking, "Camera"); +} + +ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking) +{ + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); + + if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) { + return &object->tracks; + } + + return &tracking->tracks; +} + +MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking) +{ + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); + + return BKE_tracking_object_get_reconstruction(tracking, object); +} + +void BKE_tracking_get_camera_object_matrix(Scene *scene, Object *ob, float mat[4][4]) +{ + if (!ob) { + if (scene->camera) + ob = scene->camera; + else + ob = BKE_scene_camera_find(scene); + } + + if (ob) + BKE_object_where_is_calc_mat4(scene, ob, mat); + else + unit_m4(mat); +} + +void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object, + int framenr, int winx, int winy, float mat[4][4]) +{ + MovieReconstructedCamera *camera; + float lens = tracking->camera.focal * tracking->camera.sensor_width / (float)winx; + float viewfac, pixsize, left, right, bottom, top, clipsta, clipend; + float winmat[4][4]; + float ycor = 1.0f / tracking->camera.pixel_aspect; + float shiftx, shifty, winside = MAX2(winx, winy); + + BKE_tracking_camera_shift_get(tracking, winx, winy, &shiftx, &shifty); + + clipsta = 0.1f; + clipend = 1000.0f; + + if (winx >= winy) + viewfac = (lens * winx) / tracking->camera.sensor_width; + else + viewfac = (ycor * lens * winy) / tracking->camera.sensor_width; + + pixsize = clipsta / viewfac; + + left = -0.5f * (float)winx + shiftx * winside; + bottom = -0.5f * (ycor) * (float)winy + shifty * winside; + right = 0.5f * (float)winx + shiftx * winside; + top = 0.5f * (ycor) * (float)winy + shifty * winside; + + left *= pixsize; + right *= pixsize; + bottom *= pixsize; + top *= pixsize; + + perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); + + camera = BKE_tracking_camera_get_reconstructed(tracking, object, framenr); + + if (camera) { + float imat[4][4]; + + invert_m4_m4(imat, camera->mat); + mult_m4_m4m4(mat, winmat, imat); + } + else copy_m4_m4(mat, winmat); +} + +/* **** space transformation functions **** */ /* Three coordinate frames: Frame, Search, and Marker * Two units: Pixels, Unified @@ -100,7 +284,8 @@ static void marker_to_frame_unified(const MovieTrackingMarker *marker, const flo static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height, const MovieTrackingMarker *marker, - const float marker_unified_coords[2], float frame_pixel_coords[2]) + const float marker_unified_coords[2], + float frame_pixel_coords[2]) { marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords); @@ -168,6 +353,7 @@ static void get_marker_coords_for_tracking(int frame_width, int frame_height, search_pixel_x[i] = pixel_coords[0]; search_pixel_y[i] = pixel_coords[1]; } + /* Convert the center position (aka "pos"); this is the origin */ unified_coords[0] = 0.0; unified_coords[1] = 0.0; @@ -211,121 +397,81 @@ static void set_marker_coords_from_tracking(int frame_width, int frame_height, M } #endif -/*********************** common functions *************************/ +/*********************** clipboard *************************/ -void BKE_tracking_init_settings(MovieTracking *tracking) +void BKE_tracking_clipboard_free(void) { - tracking->camera.sensor_width = 35.0f; - tracking->camera.pixel_aspect = 1.0f; - tracking->camera.units = CAMERA_UNITS_MM; + MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track; - tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION; - tracking->settings.default_minimum_correlation = 0.75; - tracking->settings.default_pattern_size = 11; - tracking->settings.default_search_size = 61; - tracking->settings.keyframe1 = 1; - tracking->settings.keyframe2 = 30; - tracking->settings.dist = 1; - tracking->settings.object_distance = 1; + while (track) { + next_track = track->next; - tracking->stabilization.scaleinf = 1.0f; - tracking->stabilization.locinf = 1.0f; - tracking->stabilization.rotinf = 1.0f; - tracking->stabilization.maxscale = 2.0f; + BKE_tracking_track_free(track); + MEM_freeN(track); - BKE_tracking_new_object(tracking, "Camera"); + track = next_track; + } } -void BKE_tracking_clamp_marker(MovieTrackingMarker *marker, int event) +void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) { - int a; - float pat_min[2], pat_max[2]; + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + BKE_tracking_clipboard_free(); - if (event == CLAMP_PAT_DIM) { - for (a = 0; a < 2; a++) { - /* search shouldn't be resized smaller than pattern */ - marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); - marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); + while (track) { + if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) { + MovieTrackingTrack *new_track = tracking_track_duplicate(track); + + BLI_addtail(&tracking_clipboard.tracks, new_track); } + + track = track->next; } - else if (event == CLAMP_PAT_POS) { - float dim[2]; +} - sub_v2_v2v2(dim, pat_max, pat_min); +int BKE_tracking_clipboard_has_tracks(void) +{ + return tracking_clipboard.tracks.first != NULL; +} - for (a = 0; a < 2; a++) { - int b; - /* pattern shouldn't be moved outside of search */ - if (pat_min[a] < marker->search_min[a]) { - for (b = 0; b < 4; b++) - marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a]; - } - if (pat_max[a] > marker->search_max[a]) { - for (b = 0; b < 4; b++) - marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a]; - } - } - } - else if (event == CLAMP_SEARCH_DIM) { - for (a = 0; a < 2; a++) { - /* search shouldn't be resized smaller than pattern */ - marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); - marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); - } - } - else if (event == CLAMP_SEARCH_POS) { - float dim[2]; +void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object) +{ + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracking_clipboard.tracks.first; - sub_v2_v2v2(dim, marker->search_max, marker->search_min); + while (track) { + MovieTrackingTrack *new_track = tracking_track_duplicate(track); - for (a = 0; a < 2; a++) { - /* search shouldn't be moved inside pattern */ - if (marker->search_min[a] > pat_min[a]) { - marker->search_min[a] = pat_min[a]; - marker->search_max[a] = marker->search_min[a] + dim[a]; - } - if (marker->search_max[a] < pat_max[a]) { - marker->search_max[a] = pat_max[a]; - marker->search_min[a] = marker->search_max[a] - dim[a]; - } - } - } - else if (event == CLAMP_SEARCH_DIM) { - float dim[2]; - sub_v2_v2v2(dim, pat_max, pat_min); - for (a = 0; a < 2; a++) { - marker->search_min[a] = pat_min[a]; - marker->search_max[a] = pat_max[a]; - } + BLI_addtail(tracksbase, new_track); + BKE_tracking_track_unique_name(tracksbase, new_track); + + track = track->next; } } -void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear) +/*********************** Tracks *************************/ + +static void tracking_marker_insert_disabled(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, + int before, int overwrite) { - if (area == TRACK_AREA_NONE) - return; + MovieTrackingMarker marker_new; - if (clear) { - if (area & TRACK_AREA_POINT) - track->flag &= ~flag; - if (area & TRACK_AREA_PAT) - track->pat_flag &= ~flag; - if (area & TRACK_AREA_SEARCH) - track->search_flag &= ~flag; - } - else { - if (area & TRACK_AREA_POINT) - track->flag |= flag; - if (area & TRACK_AREA_PAT) - track->pat_flag |= flag; - if (area & TRACK_AREA_SEARCH) - track->search_flag |= flag; - } + marker_new = *ref_marker; + marker_new.flag &= ~MARKER_TRACKED; + marker_new.flag |= MARKER_DISABLED; + + if (before) + marker_new.framenr--; + else + marker_new.framenr++; + + if (overwrite || !BKE_tracking_track_has_marker_at_frame(track, marker_new.framenr)) + BKE_tracking_marker_insert(track, &marker_new); } -MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y, +MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, ListBase *tracksbase, float x, float y, int framenr, int width, int height) { MovieTrackingTrack *track; @@ -345,6 +491,7 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr track = MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track"); strcpy(track->name, "Track"); + /* fill track's settings from default settings */ track->motion_model = settings->default_motion_model; track->minimum_correlation = settings->default_minimum_correlation; track->margin = settings->default_margin; @@ -370,22 +517,415 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr copy_v2_v2(marker.search_max, search); negate_v2_v2(marker.search_min, search); - BKE_tracking_insert_marker(track, &marker); + BKE_tracking_marker_insert(track, &marker); BLI_addtail(tracksbase, track); - BKE_track_unique_name(tracksbase, track); + BKE_tracking_track_unique_name(tracksbase, track); return track; } -MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker) +void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track) +{ + BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); +} + +void BKE_tracking_track_free(MovieTrackingTrack *track) +{ + if (track->markers) + MEM_freeN(track->markers); +} + +void BKE_tracking_track_flag_set(MovieTrackingTrack *track, int area, int flag) +{ + if (area == TRACK_AREA_NONE) + return; + + if (area & TRACK_AREA_POINT) + track->flag |= flag; + if (area & TRACK_AREA_PAT) + track->pat_flag |= flag; + if (area & TRACK_AREA_SEARCH) + track->search_flag |= flag; +} + +void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag) +{ + if (area == TRACK_AREA_NONE) + return; + + if (area & TRACK_AREA_POINT) + track->flag &= ~flag; + if (area & TRACK_AREA_PAT) + track->pat_flag &= ~flag; + if (area & TRACK_AREA_SEARCH) + track->search_flag &= ~flag; +} + +int BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr) +{ + return BKE_tracking_marker_get_exact(track, framenr) != 0; +} + +int BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr) +{ + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr); + + return marker && (marker->flag & MARKER_DISABLED) == 0; +} + +void BKE_tracking_track_path_clear(MovieTrackingTrack *track, int ref_frame, int action) +{ + int a; + + if (action == TRACK_CLEAR_REMAINED) { + a = 1; + + while (a < track->markersnr) { + if (track->markers[a].framenr > ref_frame) { + track->markersnr = a; + track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr); + + break; + } + + a++; + } + + if (track->markersnr) + tracking_marker_insert_disabled(track, &track->markers[track->markersnr - 1], FALSE, TRUE); + } + else if (action == TRACK_CLEAR_UPTO) { + a = track->markersnr - 1; + + while (a >= 0) { + if (track->markers[a].framenr <= ref_frame) { + memmove(track->markers, track->markers + a, (track->markersnr - a) * sizeof(MovieTrackingMarker)); + + track->markersnr = track->markersnr - a; + track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr); + + break; + } + + a--; + } + + if (track->markersnr) + tracking_marker_insert_disabled(track, &track->markers[0], TRUE, TRUE); + } + else if (action == TRACK_CLEAR_ALL) { + MovieTrackingMarker *marker, marker_new; + + marker = BKE_tracking_marker_get(track, ref_frame); + marker_new = *marker; + + MEM_freeN(track->markers); + track->markers = NULL; + track->markersnr = 0; + + BKE_tracking_marker_insert(track, &marker_new); + + tracking_marker_insert_disabled(track, &marker_new, TRUE, TRUE); + tracking_marker_insert_disabled(track, &marker_new, FALSE, TRUE); + } +} + +void BKE_tracking_tracks_join(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) +{ + int i = 0, a = 0, b = 0, tot; + MovieTrackingMarker *markers; + + tot = dst_track->markersnr + src_track->markersnr; + markers = MEM_callocN(tot * sizeof(MovieTrackingMarker), "tmp tracking joined tracks"); + + while (a < src_track->markersnr || b < dst_track->markersnr) { + if (b >= dst_track->markersnr) { + markers[i] = src_track->markers[a++]; + } + else if (a >= src_track->markersnr) { + markers[i] = dst_track->markers[b++]; + } + else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) { + markers[i] = src_track->markers[a++]; + } + else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) { + markers[i] = dst_track->markers[b++]; + } + else { + if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) { + if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) { + /* both tracks are enabled on this frame, so find the whole segment + * on which tracks are intersecting and blend tracks using linear + * interpolation to prevent jumps + */ + + MovieTrackingMarker *marker_a, *marker_b; + int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr; + int j, inverse = 0; + + inverse = (b == 0) || + (dst_track->markers[b - 1].flag & MARKER_DISABLED) || + (dst_track->markers[b - 1].framenr != frame - 1); + + /* find length of intersection */ + while (a < src_track->markersnr && b < dst_track->markersnr) { + marker_a = &src_track->markers[a]; + marker_b = &dst_track->markers[b]; + + if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED) + break; + + if (marker_a->framenr != frame || marker_b->framenr != frame) + break; + + frame++; + len++; + a++; + b++; + } + + a = start_a; + b = start_b; + + /* linear interpolation for intersecting frames */ + for (j = 0; j < len; j++) { + float fac = 0.5f; + + if (len > 1) + fac = 1.0f / (len - 1) * j; + + if (inverse) + fac = 1.0f - fac; + + marker_a = &src_track->markers[a]; + marker_b = &dst_track->markers[b]; + + markers[i] = dst_track->markers[b]; + interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac); + a++; + b++; + i++; + } + + /* this values will be incremented at the end of the loop cycle */ + a--; b--; i--; + } + else { + markers[i] = src_track->markers[a]; + } + } + else { + markers[i] = dst_track->markers[b]; + } + + a++; + b++; + } + + i++; + } + + MEM_freeN(dst_track->markers); + + dst_track->markers = MEM_callocN(i * sizeof(MovieTrackingMarker), "tracking joined tracks"); + memcpy(dst_track->markers, markers, i * sizeof(MovieTrackingMarker)); + + dst_track->markersnr = i; + + MEM_freeN(markers); +} + +MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieTrackingObject *object, const char *name) +{ + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; + + while (track) { + if (!strcmp(track->name, name)) + return track; + + track = track->next; + } + + return NULL; +} + +MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r) +{ + MovieTrackingObject *object; + int cur = 1; + + object = tracking->objects.first; + while (object) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; + + while (track) { + if (track->flag & TRACK_HAS_BUNDLE) { + if (cur == tracknr) { + *tracksbase_r = tracksbase; + return track; + } + + cur++; + } + + track = track->next; + } + + object = object->next; + } + + *tracksbase_r = NULL; + + return NULL; +} + +MovieTrackingTrack *BKE_tracking_track_get_active(MovieTracking *tracking) +{ + ListBase *tracksbase; + + if (!tracking->act_track) + return NULL; + + tracksbase = BKE_tracking_get_active_tracks(tracking); + + /* check that active track is in current tracks list */ + if (BLI_findindex(tracksbase, tracking->act_track) >= 0) + return tracking->act_track; + + return NULL; +} + +static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) +{ + bGPDlayer *layer; + + if (!track->gpd) + return NULL; + + layer = track->gpd->layers.first; + + while (layer) { + if (layer->flag & GP_LAYER_ACTIVE) { + bGPDframe *frame = layer->frames.first; + int ok = FALSE; + + while (frame) { + if (frame->strokes.first) { + ok = TRUE; + } + + frame = frame->next; + } + + if (ok) + return layer; + } + + layer = layer->next; + } + + return NULL; +} + +static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height, + MovieTrackingMarker *marker, bGPDlayer *layer, + float *mask, int mask_width, int mask_height) +{ + bGPDframe *frame = layer->frames.first; + + while (frame) { + bGPDstroke *stroke = frame->strokes.first; + + while (stroke) { + bGPDspoint *stroke_points = stroke->points; + float *mask_points, *fp; + int i; + + if (stroke->flag & GP_STROKE_2DSPACE) { + fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float), + "track mask rasterization points"); + + for (i = 0; i < stroke->totpoints; i++, fp += 2) { + fp[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width / mask_width; + fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height; + } + + PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE /* XXX- TODO: make on/off for AA*/); + + MEM_freeN(mask_points); + } + + stroke = stroke->next; + } + + frame = frame->next; + } +} + +float *BKE_tracking_track_get_mask(int frame_width, int frame_height, + MovieTrackingTrack *track, MovieTrackingMarker *marker) +{ + float *mask = NULL; + bGPDlayer *layer = track_mask_gpencil_layer_get(track); + int mask_width, mask_height; + + mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width; + mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height; + + if (layer) { + mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask"); + + track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer, + mask, mask_width, mask_height); + } + + return mask; +} + +/* area - which part of marker should be selected. see TRACK_AREA_* constants */ +void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend) +{ + if (extend) { + BKE_tracking_track_flag_set(track, area, SELECT); + } + else { + MovieTrackingTrack *cur = tracksbase->first; + + while (cur) { + if ((cur->flag & TRACK_HIDDEN) == 0) { + if (cur == track) { + BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT); + BKE_tracking_track_flag_set(cur, area, SELECT); + } + else { + BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT); + } + } + + cur = cur->next; + } + } +} + +void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area) +{ + BKE_tracking_track_flag_clear(track, area, SELECT); +} + +/*********************** Marker *************************/ + +MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker) { MovieTrackingMarker *old_marker = NULL; if (track->markersnr) - old_marker = BKE_tracking_exact_marker(track, marker->framenr); + old_marker = BKE_tracking_marker_get_exact(track, marker->framenr); if (old_marker) { + /* simply replace settings for already allocated marker */ *old_marker = *marker; return old_marker; @@ -393,6 +933,7 @@ MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, Movie else { int a = track->markersnr; + /* find position in array where to add new marker */ while (a--) { if (track->markers[a].framenr < marker->framenr) break; @@ -405,8 +946,11 @@ MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, Movie else track->markers = MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers"); + /* shift array to "free" space for new marker */ memmove(track->markers + a + 2, track->markers + a + 1, (track->markersnr - a - 2) * sizeof(MovieTrackingMarker)); + + /* put new marker */ track->markers[a + 1] = *marker; track->last_marker = a + 1; @@ -415,7 +959,7 @@ MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, Movie } } -void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr) +void BKE_tracking_marker_delete(MovieTrackingTrack *track, int framenr) { int a = 0; @@ -440,17 +984,73 @@ void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr) } } -void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2]) +void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) { - INIT_MINMAX2(min, max); + int a; + float pat_min[2], pat_max[2]; - DO_MINMAX2(marker->pattern_corners[0], min, max); - DO_MINMAX2(marker->pattern_corners[1], min, max); - DO_MINMAX2(marker->pattern_corners[2], min, max); - DO_MINMAX2(marker->pattern_corners[3], min, max); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + if (event == CLAMP_PAT_DIM) { + for (a = 0; a < 2; a++) { + /* search shouldn't be resized smaller than pattern */ + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); + } + } + else if (event == CLAMP_PAT_POS) { + float dim[2]; + + sub_v2_v2v2(dim, pat_max, pat_min); + + for (a = 0; a < 2; a++) { + int b; + /* pattern shouldn't be moved outside of search */ + if (pat_min[a] < marker->search_min[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a]; + } + if (pat_max[a] > marker->search_max[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a]; + } + } + } + else if (event == CLAMP_SEARCH_DIM) { + for (a = 0; a < 2; a++) { + /* search shouldn't be resized smaller than pattern */ + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); + } + } + else if (event == CLAMP_SEARCH_POS) { + float dim[2]; + + sub_v2_v2v2(dim, marker->search_max, marker->search_min); + + for (a = 0; a < 2; a++) { + /* search shouldn't be moved inside pattern */ + if (marker->search_min[a] > pat_min[a]) { + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = marker->search_min[a] + dim[a]; + } + if (marker->search_max[a] < pat_max[a]) { + marker->search_max[a] = pat_max[a]; + marker->search_min[a] = marker->search_max[a] - dim[a]; + } + } + } + else if (event == CLAMP_SEARCH_DIM) { + float dim[2]; + sub_v2_v2v2(dim, pat_max, pat_min); + for (a = 0; a < 2; a++) { + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = pat_max[a]; + } + } } -MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr) +MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr) { int a = track->markersnr - 1; @@ -495,9 +1095,19 @@ MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int fram return NULL; } -MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr) +MovieTrackingMarker *BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr) +{ + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + + if (marker->framenr != framenr) + return NULL; + + return marker; +} + +MovieTrackingMarker *BKE_tracking_marker_ensure(MovieTrackingTrack *track, int framenr) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); if (marker->framenr != framenr) { MovieTrackingMarker marker_new; @@ -505,352 +1115,663 @@ MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int f marker_new = *marker; marker_new.framenr = framenr; - BKE_tracking_insert_marker(track, &marker_new); - marker = BKE_tracking_get_marker(track, framenr); + BKE_tracking_marker_insert(track, &marker_new); + marker = BKE_tracking_marker_get(track, framenr); } return marker; } -MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr) +void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2]) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); - - if (marker->framenr != framenr) - return NULL; + INIT_MINMAX2(min, max); - return marker; + DO_MINMAX2(marker->pattern_corners[0], min, max); + DO_MINMAX2(marker->pattern_corners[1], min, max); + DO_MINMAX2(marker->pattern_corners[2], min, max); + DO_MINMAX2(marker->pattern_corners[3], min, max); } -int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr) +/*********************** Object *************************/ + +MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name) { - return BKE_tracking_exact_marker(track, framenr) != 0; + MovieTrackingObject *object = MEM_callocN(sizeof(MovieTrackingObject), "tracking object"); + + if (tracking->tot_object == 0) { + /* first object is always camera */ + BLI_strncpy(object->name, "Camera", sizeof(object->name)); + + object->flag |= TRACKING_OBJECT_CAMERA; + } + else { + BLI_strncpy(object->name, name, sizeof(object->name)); + } + + BLI_addtail(&tracking->objects, object); + + tracking->tot_object++; + tracking->objectnr = BLI_countlist(&tracking->objects) - 1; + + object->scale = 1.0f; + + BKE_tracking_object_unique_name(tracking, object); + + return object; } -int BKE_tracking_has_enabled_marker(MovieTrackingTrack *track, int framenr) +void BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object) { - MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + MovieTrackingTrack *track; + int index = BLI_findindex(&tracking->objects, object); - return marker && (marker->flag & MARKER_DISABLED) == 0; + if (index < 0) + return; + + if (object->flag & TRACKING_OBJECT_CAMERA) { + /* object used for camera solving can't be deleted */ + return; + } + + track = object->tracks.first; + while (track) { + if (track == tracking->act_track) + tracking->act_track = NULL; + + track = track->next; + } + + tracking_object_free(object); + BLI_freelinkN(&tracking->objects, object); + + tracking->tot_object--; + + if (index > 0) + tracking->objectnr = index - 1; + else + tracking->objectnr = 0; } -void BKE_tracking_free_track(MovieTrackingTrack *track) +void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object) { - if (track->markers) - MEM_freeN(track->markers); + BLI_uniquename(&tracking->objects, object, "Object", '.', + offsetof(MovieTrackingObject, name), sizeof(object->name)); } -static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite) +MovieTrackingObject *BKE_tracking_object_get_named(MovieTracking *tracking, const char *name) { - MovieTrackingMarker marker_new; + MovieTrackingObject *object = tracking->objects.first; - marker_new = *ref_marker; - marker_new.flag &= ~MARKER_TRACKED; - marker_new.flag |= MARKER_DISABLED; + while (object) { + if (!strcmp(object->name, name)) + return object; - if (before) - marker_new.framenr--; - else - marker_new.framenr++; + object = object->next; + } - if (!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite) - BKE_tracking_insert_marker(track, &marker_new); + return NULL; } -void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action) +MovieTrackingObject *BKE_tracking_object_get_active(MovieTracking *tracking) { - int a; + return BLI_findlink(&tracking->objects, tracking->objectnr); +} - if (action == TRACK_CLEAR_REMAINED) { - a = 1; +MovieTrackingObject *BKE_tracking_object_get_camera(MovieTracking *tracking) +{ + MovieTrackingObject *object = tracking->objects.first; - while (a < track->markersnr) { - if (track->markers[a].framenr > ref_frame) { - track->markersnr = a; - track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr); + while (object) { + if (object->flag & TRACKING_OBJECT_CAMERA) + return object; - break; - } + object = object->next; + } - a++; - } + return NULL; +} - if (track->markersnr) - put_disabled_marker(track, &track->markers[track->markersnr - 1], 0, 1); +ListBase *BKE_tracking_object_get_tracks(MovieTracking *tracking, MovieTrackingObject *object) +{ + if (object->flag & TRACKING_OBJECT_CAMERA) { + return &tracking->tracks; } - else if (action == TRACK_CLEAR_UPTO) { - a = track->markersnr - 1; - - while (a >= 0) { - if (track->markers[a].framenr <= ref_frame) { - memmove(track->markers, track->markers + a, (track->markersnr - a) * sizeof(MovieTrackingMarker)); - track->markersnr = track->markersnr - a; - track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr); + return &object->tracks; +} - break; - } +MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(MovieTracking *tracking, + MovieTrackingObject *object) +{ + if (object->flag & TRACKING_OBJECT_CAMERA) { + return &tracking->reconstruction; + } - a--; - } + return &object->reconstruction; +} - if (track->markersnr) - put_disabled_marker(track, &track->markers[0], 1, 1); - } - else if (action == TRACK_CLEAR_ALL) { - MovieTrackingMarker *marker, marker_new; +/*********************** Camera *************************/ - marker = BKE_tracking_get_marker(track, ref_frame); - marker_new = *marker; +static int reconstructed_camera_index_get(MovieTrackingReconstruction *reconstruction, int framenr, int nearest) +{ + MovieReconstructedCamera *cameras = reconstruction->cameras; + int a = 0, d = 1; - MEM_freeN(track->markers); - track->markers = NULL; - track->markersnr = 0; + if (!reconstruction->camnr) + return -1; - BKE_tracking_insert_marker(track, &marker_new); + if (framenr < cameras[0].framenr) { + if (nearest) + return 0; + else + return -1; + } - put_disabled_marker(track, &marker_new, 1, 1); - put_disabled_marker(track, &marker_new, 0, 1); + if (framenr > cameras[reconstruction->camnr - 1].framenr) { + if (nearest) + return reconstruction->camnr - 1; + else + return -1; } -} -void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) -{ - int i = 0, a = 0, b = 0, tot; - MovieTrackingMarker *markers; + if (reconstruction->last_camera < reconstruction->camnr) + a = reconstruction->last_camera; - tot = dst_track->markersnr + src_track->markersnr; - markers = MEM_callocN(tot * sizeof(MovieTrackingMarker), "tmp tracking joined tracks"); + if (cameras[a].framenr >= framenr) + d = -1; - while (a < src_track->markersnr || b < dst_track->markersnr) { - if (b >= dst_track->markersnr) { - markers[i] = src_track->markers[a++]; - } - else if (a >= src_track->markersnr) { - markers[i] = dst_track->markers[b++]; + while (a >= 0 && a < reconstruction->camnr) { + int cfra = cameras[a].framenr; + + /* check if needed framenr was "skipped" -- no data for requested frame */ + + if (d > 0 && cfra > framenr) { + /* interpolate with previous position */ + if (nearest) + return a - 1; + else + break; } - else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) { - markers[i] = src_track->markers[a++]; + + if (d < 0 && cfra < framenr) { + /* interpolate with next position */ + if (nearest) + return a; + else + break; } - else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) { - markers[i] = dst_track->markers[b++]; + + if (cfra == framenr) { + reconstruction->last_camera = a; + + return a; } - else { - if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) { - if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) { - /* both tracks are enabled on this frame, so find the whole segment - * on which tracks are intersecting and blend tracks using linear - * interpolation to prevent jumps - */ - MovieTrackingMarker *marker_a, *marker_b; - int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr; - int j, inverse = 0; + a += d; + } - inverse = (b == 0) || - (dst_track->markers[b - 1].flag & MARKER_DISABLED) || - (dst_track->markers[b - 1].framenr != frame - 1); + return -1; +} - /* find length of intersection */ - while (a < src_track->markersnr && b < dst_track->markersnr) { - marker_a = &src_track->markers[a]; - marker_b = &dst_track->markers[b]; +static void reconstructed_camera_scale_set(MovieTrackingObject *object, float mat[4][4]) +{ + if ((object->flag & TRACKING_OBJECT_CAMERA) == 0) { + float smat[4][4]; - if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED) - break; + scale_m4_fl(smat, 1.0f / object->scale); + mult_m4_m4m4(mat, mat, smat); + } +} - if (marker_a->framenr != frame || marker_b->framenr != frame) - break; - frame++; - len++; - a++; - b++; - } +/* converts principal offset from center to offset of blender's camera */ +void BKE_tracking_camera_shift_get(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty) +{ + /* indeed in both of cases it should be winx -- it's just how camera shift works for blender's camera */ + *shiftx = (0.5f * winx - tracking->camera.principal[0]) / winx; + *shifty = (0.5f * winy - tracking->camera.principal[1]) / winx; +} - a = start_a; - b = start_b; +void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height) +{ + float focal = tracking->camera.focal; - /* linear interpolation for intersecting frames */ - for (j = 0; j < len; j++) { - float fac = 0.5f; + camera->sensor_x = tracking->camera.sensor_width; + camera->sensor_fit = CAMERA_SENSOR_FIT_AUTO; + camera->lens = focal * camera->sensor_x / width; - if (len > 1) - fac = 1.0f / (len - 1) * j; + scene->r.xsch = width * tracking->camera.pixel_aspect; + scene->r.ysch = height; - if (inverse) - fac = 1.0f - fac; + scene->r.xasp = 1.0f; + scene->r.yasp = 1.0f; - marker_a = &src_track->markers[a]; - marker_b = &dst_track->markers[b]; + BKE_tracking_camera_shift_get(tracking, width, height, &camera->shiftx, &camera->shifty); +} - markers[i] = dst_track->markers[b]; - interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac); - a++; - b++; - i++; - } +MovieReconstructedCamera *BKE_tracking_camera_get_reconstructed(MovieTracking *tracking, + MovieTrackingObject *object, int framenr) +{ + MovieTrackingReconstruction *reconstruction; + int a; - /* this values will be incremented at the end of the loop cycle */ - a--; b--; i--; - } - else markers[i] = src_track->markers[a]; - } - else markers[i] = dst_track->markers[b]; + reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + a = reconstructed_camera_index_get(reconstruction, framenr, FALSE); - a++; - b++; - } + if (a == -1) + return NULL; - i++; - } + return &reconstruction->cameras[a]; +} - MEM_freeN(dst_track->markers); +void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking, MovieTrackingObject *object, + int framenr, float mat[4][4]) +{ + MovieTrackingReconstruction *reconstruction; + MovieReconstructedCamera *cameras; + int a; - dst_track->markers = MEM_callocN(i * sizeof(MovieTrackingMarker), "tracking joined tracks"); - memcpy(dst_track->markers, markers, i * sizeof(MovieTrackingMarker)); + reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + cameras = reconstruction->cameras; + a = reconstructed_camera_index_get(reconstruction, framenr, 1); - dst_track->markersnr = i; + if (a == -1) { + unit_m4(mat); - MEM_freeN(markers); -} + return; + } -static void tracking_tracks_free(ListBase *tracks) -{ - MovieTrackingTrack *track; + if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) { + float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr); - for (track = tracks->first; track; track = track->next) { - BKE_tracking_free_track(track); + blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t); + } + else { + copy_m4_m4(mat, cameras[a].mat); } - BLI_freelistN(tracks); + reconstructed_camera_scale_set(object, mat); } -static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction) +/*********************** Distortion/Undistortion *************************/ + +MovieDistortion *BKE_tracking_distortion_new(void) { - if (reconstruction->cameras) - MEM_freeN(reconstruction->cameras); + MovieDistortion *distortion; + + distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); + + return distortion; } -static void tracking_object_free(MovieTrackingObject *object) +void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, + int calibration_width, int calibration_height) { - tracking_tracks_free(&object->tracks); - tracking_reconstruction_free(&object->reconstruction); + MovieTrackingCamera *camera = &tracking->camera; + float aspy = 1.0f / tracking->camera.pixel_aspect; + +#ifdef WITH_LIBMV + if (!distortion->intrinsics) { + distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal, + camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, + calibration_width, calibration_height * aspy); + } + else { + libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal, + camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, + calibration_width, calibration_height * aspy); + } +#else + (void) distortion; + (void) width; + (void) height; + (void) camera; + (void) aspy; +#endif } -static void tracking_objects_free(ListBase *objects) +MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion) { - MovieTrackingObject *object; + MovieDistortion *new_distortion; - for (object = objects->first; object; object = object->next) - tracking_object_free(object); + new_distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); - BLI_freelistN(objects); +#ifdef WITH_LIBMV + new_distortion->intrinsics = libmv_CameraIntrinsicsCopy(distortion->intrinsics); +#else + (void) distortion; +#endif + + return new_distortion; } -static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) +ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, ImBuf *ibuf, + int calibration_width, int calibration_height, float overscan, int undistort) { - MovieTrackingDopesheetChannel *channel; + ImBuf *resibuf; - channel = dopesheet->channels.first; - while (channel) { - if (channel->segments) { - MEM_freeN(channel->segments); + BKE_tracking_distortion_update(distortion, tracking, calibration_width, calibration_height); + + resibuf = IMB_dupImBuf(ibuf); + +#ifdef WITH_LIBMV + if (ibuf->rect_float) { + if (undistort) { + libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics, + ibuf->rect_float, resibuf->rect_float, + ibuf->x, ibuf->y, overscan, ibuf->channels); + } + else { + libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics, + ibuf->rect_float, resibuf->rect_float, + ibuf->x, ibuf->y, overscan, ibuf->channels); } - channel = channel->next; + resibuf->userflags |= IB_RECT_INVALID; } + else { + if (undistort) { + libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics, + (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, + ibuf->x, ibuf->y, overscan, ibuf->channels); + } + else { + libmv_CameraIntrinsicsDistortByte(distortion->intrinsics, + (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, + ibuf->x, ibuf->y, overscan, ibuf->channels); + } + } +#else + (void) overscan; + (void) undistort; - BLI_freelistN(&dopesheet->channels); + if (ibuf->rect_float) { + resibuf->userflags |= IB_RECT_INVALID; + } +#endif - dopesheet->channels.first = dopesheet->channels.last = NULL; - dopesheet->tot_channel = 0; + return resibuf; } -void BKE_tracking_free(MovieTracking *tracking) +void BKE_tracking_distortion_free(MovieDistortion *distortion) { - tracking_tracks_free(&tracking->tracks); - tracking_reconstruction_free(&tracking->reconstruction); - tracking_objects_free(&tracking->objects); +#ifdef WITH_LIBMV + libmv_CameraIntrinsicsDestroy(distortion->intrinsics); +#endif - if (tracking->stabilization.scaleibuf) - IMB_freeImBuf(tracking->stabilization.scaleibuf); + MEM_freeN(distortion); +} - if (tracking->camera.intrinsics) - BKE_tracking_distortion_destroy(tracking->camera.intrinsics); +void BKE_tracking_distort_v2(MovieTracking *tracking, float co[2], float nco[2]) +{ + MovieTrackingCamera *camera = &tracking->camera; - tracking_dopesheet_free(&tracking->dopesheet); +#ifdef WITH_LIBMV + double x, y; + float aspy = 1.0f / tracking->camera.pixel_aspect; + + /* normalize coords */ + x = (co[0] - camera->principal[0]) / camera->focal; + y = (co[1] - camera->principal[1] * aspy) / camera->focal; + + libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, x, y, &x, &y); + + /* result is in image coords already */ + nco[0] = x; + nco[1] = y; +#else + (void) camera; + (void) co; + (void) nco; +#endif } -static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track) +void BKE_tracking_undistort_v2(MovieTracking *tracking, float co[2], float nco[2]) { - MovieTrackingTrack *new_track; + MovieTrackingCamera *camera = &tracking->camera; - new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track"); +#ifdef WITH_LIBMV + double x = co[0], y = co[1]; + float aspy = 1.0f / tracking->camera.pixel_aspect; - *new_track = *track; - new_track->next = new_track->prev = NULL; + libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, x, y, &x, &y); - new_track->markers = MEM_dupallocN(new_track->markers); + nco[0] = x * camera->focal + camera->principal[0]; + nco[1] = y * camera->focal + camera->principal[1] * aspy; +#else + (void) camera; + (void) co; + (void) nco; +#endif +} - return new_track; +ImBuf *BKE_tracking_undistort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width, + int calibration_height, float overscan) +{ + MovieTrackingCamera *camera = &tracking->camera; + + if (camera->intrinsics == NULL) + camera->intrinsics = BKE_tracking_distortion_new(); + + return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width, + calibration_height, overscan, TRUE); } -/*********************** clipboard *************************/ +ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width, + int calibration_height, float overscan) +{ + MovieTrackingCamera *camera = &tracking->camera; + + if (camera->intrinsics == NULL) + camera->intrinsics = BKE_tracking_distortion_new(); + + return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width, + calibration_height, overscan, FALSE); +} -void BKE_tracking_free_clipboard(void) +/*********************** Image sampling *************************/ + +static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) { - MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track; + BKE_tracking_disable_channels(ibuf, track->flag & TRACK_DISABLE_RED, + track->flag & TRACK_DISABLE_GREEN, + track->flag & TRACK_DISABLE_BLUE, grayscale); +} - while (track) { - next_track = track->next; +ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf, + MovieTrackingTrack *track, MovieTrackingMarker *marker, + int use_mask, int num_samples_x, int num_samples_y, + float pos[2]) +{ +#ifdef WITH_LIBMV + ImBuf *pattern_ibuf; + double src_pixel_x[5], src_pixel_y[5]; + double warped_position_x, warped_position_y; + float *mask = NULL; - BKE_tracking_free_track(track); - MEM_freeN(track); + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; - track = next_track; + if (!search_ibuf->rect_float) { + IMB_float_from_rect(search_ibuf); + } + + get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y); + + if (use_mask) { + mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker); + } + + libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4, + src_pixel_x, src_pixel_y, num_samples_x, + num_samples_y, mask, pattern_ibuf->rect_float, + &warped_position_x, &warped_position_y); + + if (pos) { + pos[0] = warped_position_x; + pos[1] = warped_position_y; + } + + if (mask) { + MEM_freeN(mask); } + + return pattern_ibuf; +#else + ImBuf *pattern_ibuf; + + /* real sampling requires libmv, but areas are supposing pattern would be + * sampled if search area does exists, so we'll need to create empty + * pattern area here to prevent adding NULL-checks all over just to deal + * with situation when lubmv is disabled + */ + + (void) frame_width; + (void) frame_height; + (void) search_ibuf; + (void) marker; + (void) track; + (void) use_mask; + + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + + pos[0] = num_samples_x / 2.0f; + pos[1] = num_samples_y / 2.0f; + + return pattern_ibuf; +#endif } -void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) +ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int anchored, int disable_channels) { - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; + ImBuf *pattern_ibuf, *search_ibuf; + float pat_min[2], pat_max[2]; + int num_samples_x, num_samples_y; - BKE_tracking_free_clipboard(); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - while (track) { - if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) { - MovieTrackingTrack *new_track = duplicate_track(track); + num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x; + num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y; - BLI_addtail(&tracking_clipboard.tracks, new_track); - } + search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); - track = track->next; - } + pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker, + FALSE, num_samples_x, num_samples_y, NULL); + + IMB_freeImBuf(search_ibuf); + + return pattern_ibuf; } -int BKE_tracking_clipboard_has_tracks(void) +ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int anchored, int disable_channels) { - return tracking_clipboard.tracks.first != NULL; + ImBuf *searchibuf; + int x, y, w, h; + float search_origin[2]; + + get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin); + + x = search_origin[0]; + y = search_origin[1]; + + if (anchored) { + x += track->offset[0] * ibuf->x; + y += track->offset[1] * ibuf->y; + } + + w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; + h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; + + searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); + searchibuf->profile = ibuf->profile; + + IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); + + if (disable_channels) { + if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || + (track->flag & TRACK_DISABLE_RED) || + (track->flag & TRACK_DISABLE_GREEN) || + (track->flag & TRACK_DISABLE_BLUE)) + { + disable_imbuf_channels(searchibuf, track, TRUE); + } + } + + return searchibuf; } -void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object) +/* zap channels from the imbuf that are disabled by the user. this can lead to + * better tracks sometimes. however, instead of simply zeroing the channels + * out, do a partial grayscale conversion so the display is better. + */ +void BKE_tracking_disable_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, + int grayscale) { - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - MovieTrackingTrack *track = tracking_clipboard.tracks.first; + int x, y; + float scale; - while (track) { - MovieTrackingTrack *new_track = duplicate_track(track); + if (!disable_red && !disable_green && !disable_blue && !grayscale) + return; - BLI_addtail(tracksbase, new_track); - BKE_track_unique_name(tracksbase, new_track); + /* if only some components are selected, it's important to rescale the result + * appropriately so that e.g. if only blue is selected, it's not zeroed out. + */ + scale = (disable_red ? 0.0f : 0.2126f) + + (disable_green ? 0.0f : 0.7152f) + + (disable_blue ? 0.0f : 0.0722f); - track = track->next; + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + int pixel = ibuf->x * y + x; + + if (ibuf->rect_float) { + float *rrgbf = ibuf->rect_float + pixel * 4; + float r = disable_red ? 0.0f : rrgbf[0]; + float g = disable_green ? 0.0f : rrgbf[1]; + float b = disable_blue ? 0.0f : rrgbf[2]; + + if (grayscale) { + float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale; + + rrgbf[0] = rrgbf[1] = rrgbf[2] = gray; + } + else { + rrgbf[0] = r; + rrgbf[1] = g; + rrgbf[2] = b; + } + } + else { + char *rrgb = (char *)ibuf->rect + pixel * 4; + char r = disable_red ? 0 : rrgb[0]; + char g = disable_green ? 0 : rrgb[1]; + char b = disable_blue ? 0 : rrgb[2]; + + if (grayscale) { + float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale; + + rrgb[0] = rrgb[1] = rrgb[2] = gray; + } + else { + rrgb[0] = r; + rrgb[1] = g; + rrgb[2] = b; + } + } + } } + + if (ibuf->rect_float) + ibuf->userflags |= IB_RECT_INVALID; } -/*********************** tracks map *************************/ +/*********************** Tracks map *************************/ typedef struct TracksMap { char object_name[MAX_NAME]; @@ -887,12 +1808,12 @@ static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num return map; } -static int tracks_map_size(TracksMap *map) +static int tracks_map_get_size(TracksMap *map) { return map->num_tracks; } -static void tracks_map_get(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata) +static void tracks_map_get_indexed_element(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata) { *track = &map->tracks[index]; @@ -919,7 +1840,7 @@ static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *c static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) { MovieTrackingTrack *track; - MovieTrackingTrack *act_track = BKE_tracking_active_track(tracking); + MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); MovieTrackingTrack *rot_track = tracking->stabilization.rot_track; ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL}; ListBase *old_tracks; @@ -929,11 +1850,11 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) old_tracks = &tracking->tracks; } else { - MovieTrackingObject *object = BKE_tracking_named_object(tracking, map->object_name); + MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name); if (!object) { /* object was deleted by user, create new one */ - object = BKE_tracking_new_object(tracking, map->object_name); + object = BKE_tracking_object_add(tracking, map->object_name); } old_tracks = &object->tracks; @@ -972,12 +1893,12 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) track->pat_flag = cur->pat_flag; track->search_flag = cur->search_flag; - BKE_tracking_free_track(cur); + BKE_tracking_track_free(cur); BLI_freelinkN(old_tracks, cur); } } - new_track = duplicate_track(track); + new_track = tracking_track_duplicate(track); BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */ BLI_ghash_insert(map->hash, track, new_track); @@ -1030,7 +1951,7 @@ static void tracks_map_free(TracksMap *map, void (*customdata_free)(void *custom if (map->customdata && customdata_free) customdata_free(&map->customdata[i * map->customdata_size]); - BKE_tracking_free_track(&map->tracks[i]); + BKE_tracking_track_free(&map->tracks[i]); } if (map->customdata) @@ -1040,7 +1961,7 @@ static void tracks_map_free(TracksMap *map, void (*customdata_free)(void *custom MEM_freeN(map); } -/*********************** tracking *************************/ +/*********************** 2D tracking *************************/ typedef struct TrackContext { #ifdef WITH_LIBMV @@ -1073,16 +1994,33 @@ typedef struct MovieTrackingContext { int sync_frame; } MovieTrackingContext; +static void track_context_free(void *customdata) +{ + TrackContext *track_context = (TrackContext *)customdata; + +#if WITH_LIBMV + if (track_context->search_area) + MEM_freeN(track_context->search_area); + + if (track_context->mask) + MEM_freeN(track_context->mask); + +#else + (void)track_context; +#endif +} + MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence) { MovieTrackingContext *context = MEM_callocN(sizeof(MovieTrackingContext), "trackingContext"); MovieTracking *tracking = &clip->tracking; MovieTrackingSettings *settings = &tracking->settings; - ListBase *tracksbase = BKE_tracking_get_tracks(tracking); + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); MovieTrackingTrack *track; - MovieTrackingObject *object = BKE_tracking_active_object(tracking); + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); int num_tracks = 0; + context->clip = clip; context->settings = *settings; context->backwards = backwards; context->sync_frame = user->framenr; @@ -1094,7 +2032,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u while (track) { if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) { int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) num_tracks++; @@ -1103,6 +2041,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u track = track->next; } + /* create tracking contextx for all tracks which would be tracked */ if (num_tracks) { int width, height; @@ -1116,7 +2055,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u while (track) { if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) { int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) { TrackContext track_context; @@ -1129,8 +2068,6 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u } } - context->clip = clip; - /* store needed clip flags passing to get_buffer functions * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip * only in case Proxy/Timecode flag is set, so store this flag to use @@ -1152,22 +2089,6 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u return context; } -static void track_context_free(void *customdata) -{ - TrackContext *track_context = (TrackContext *)customdata; - -#if WITH_LIBMV - if (track_context->search_area) - MEM_freeN(track_context->search_area); - - if (track_context->mask) - MEM_freeN(track_context->mask); - -#else - (void)track_context; -#endif -} - void BKE_tracking_context_free(MovieTrackingContext *context) { if (!context->sequence) @@ -1178,291 +2099,32 @@ void BKE_tracking_context_free(MovieTrackingContext *context) MEM_freeN(context); } -/* zap channels from the imbuf that are disabled by the user. this can lead to - * better tracks sometimes. however, instead of simply zeroing the channels - * out, do a partial grayscale conversion so the display is better. - */ -void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, - int grayscale) -{ - int x, y; - float scale; - - if (!disable_red && !disable_green && !disable_blue && !grayscale) - return; - - /* If only some components are selected, it's important to rescale the result - * appropriately so that e.g. if only blue is selected, it's not zeroed out. - */ - scale = (disable_red ? 0.0f : 0.2126f) + - (disable_green ? 0.0f : 0.7152f) + - (disable_blue ? 0.0f : 0.0722f); - - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - int pixel = ibuf->x * y + x; - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + pixel * 4; - float r = disable_red ? 0.0f : rrgbf[0]; - float g = disable_green ? 0.0f : rrgbf[1]; - float b = disable_blue ? 0.0f : rrgbf[2]; - - if (grayscale) { - float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale; - - rrgbf[0] = rrgbf[1] = rrgbf[2] = gray; - } - else { - rrgbf[0] = r; - rrgbf[1] = g; - rrgbf[2] = b; - } - } - else { - char *rrgb = (char *)ibuf->rect + pixel * 4; - char r = disable_red ? 0 : rrgb[0]; - char g = disable_green ? 0 : rrgb[1]; - char b = disable_blue ? 0 : rrgb[2]; - - if (grayscale) { - float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale; - - rrgb[0] = rrgb[1] = rrgb[2] = gray; - } - else { - rrgb[0] = r; - rrgb[1] = g; - rrgb[2] = b; - } - } - } - } - - if (ibuf->rect_float) - ibuf->userflags |= IB_RECT_INVALID; -} - -static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) -{ - BKE_tracking_disable_imbuf_channels(ibuf, track->flag & TRACK_DISABLE_RED, - track->flag & TRACK_DISABLE_GREEN, track->flag & TRACK_DISABLE_BLUE, grayscale); -} - -ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, ImBuf *search_ibuf, - MovieTrackingTrack *track, MovieTrackingMarker *marker, - int use_mask, int num_samples_x, int num_samples_y, - float pos[2]) -{ -#ifdef WITH_LIBMV - ImBuf *pattern_ibuf; - double src_pixel_x[5], src_pixel_y[5]; - double warped_position_x, warped_position_y; - float *mask = NULL; - - pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); - pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; - - if (!search_ibuf->rect_float) { - IMB_float_from_rect(search_ibuf); - } - - get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y); - - if (use_mask) { - mask = BKE_tracking_track_mask_get(frame_width, frame_height, track, marker); - } - - libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4, - src_pixel_x, src_pixel_y, num_samples_x, - num_samples_y, mask, pattern_ibuf->rect_float, - &warped_position_x, &warped_position_y); - - if (pos) { - pos[0] = warped_position_x; - pos[1] = warped_position_y; - } - - if (mask) { - MEM_freeN(mask); - } - - return pattern_ibuf; -#else - ImBuf *pattern_ibuf; - - /* real sampling requires libmv, but areas are supposing pattern would be - * sampled if search area does exists, so we'll need to create empty - * pattern area here to prevent adding NULL-checks all over just to deal - * with situation when lubmv is disabled - */ - - (void) frame_width; - (void) frame_height; - (void) search_ibuf; - (void) marker; - (void) track; - (void) use_mask; - - pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); - - pos[0] = num_samples_x / 2.0f; - pos[1] = num_samples_y / 2.0f; - - return pattern_ibuf; -#endif -} - -ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int anchored, int disable_channels) +void BKE_tracking_context_sync(MovieTrackingContext *context) { - ImBuf *pattern_ibuf, *search_ibuf; - float pat_min[2], pat_max[2]; - int num_samples_x, num_samples_y; - - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - - num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x; - num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y; - - search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); - - pattern_ibuf = BKE_tracking_sample_pattern_imbuf(ibuf->x, ibuf->y, search_ibuf, track, marker, - FALSE, num_samples_x, num_samples_y, NULL); - - IMB_freeImBuf(search_ibuf); - - return pattern_ibuf; -} - -ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int anchored, int disable_channels) -{ - ImBuf *searchibuf; - int x, y, w, h; - float search_origin[2]; - - get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin); - - x = search_origin[0]; - y = search_origin[1]; - - if (anchored) { - x += track->offset[0] * ibuf->x; - y += track->offset[1] * ibuf->y; - } - - w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; - h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; - - searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); - searchibuf->profile = ibuf->profile; - - IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); - - if (disable_channels) { - if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || - (track->flag & TRACK_DISABLE_RED) || - (track->flag & TRACK_DISABLE_GREEN) || - (track->flag & TRACK_DISABLE_BLUE)) - { - disable_imbuf_channels(searchibuf, track, TRUE); - } - } - - return searchibuf; -} - -static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) -{ - bGPDlayer *layer; - - if (!track->gpd) - return NULL; - - layer = track->gpd->layers.first; - - while (layer) { - if (layer->flag & GP_LAYER_ACTIVE) { - bGPDframe *frame = layer->frames.first; - int ok = FALSE; - - while (frame) { - if (frame->strokes.first) { - ok = TRUE; - } - - frame = frame->next; - } - - if (ok) - return layer; - } - - layer = layer->next; - } - - return NULL; -} - -static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height, - MovieTrackingMarker *marker, bGPDlayer *layer, - float *mask, int mask_width, int mask_height) -{ - bGPDframe *frame = layer->frames.first; - - while (frame) { - bGPDstroke *stroke = frame->strokes.first; - - while (stroke) { - bGPDspoint *stroke_points = stroke->points; - float *mask_points, *fp; - int i; - - if (stroke->flag & GP_STROKE_2DSPACE) { - fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float), - "track mask rasterization points"); - - for (i = 0; i < stroke->totpoints; i++, fp += 2) { - fp[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width / mask_width; - fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height; - } + MovieTracking *tracking = &context->clip->tracking; + int newframe; - PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE /* XXX- TODO: make on/off for AA*/); + tracks_map_merge(context->tracks_map, tracking); - MEM_freeN(mask_points); - } + if (context->backwards) + newframe = context->user.framenr + 1; + else + newframe = context->user.framenr - 1; - stroke = stroke->next; - } + context->sync_frame = newframe; - frame = frame->next; - } + tracking->dopesheet.ok = FALSE; } -float *BKE_tracking_track_mask_get(int frame_width, int frame_height, - MovieTrackingTrack *track, MovieTrackingMarker *marker) +void BKE_tracking_context_sync_user(const MovieTrackingContext *context, MovieClipUser *user) { - float *mask = NULL; - bGPDlayer *layer = track_mask_gpencil_layer_get(track); - int mask_width, mask_height; - - mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width; - mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height; - - if (layer) { - mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask"); - - track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer, - mask, mask_width, mask_height); - } - - return mask; + user->framenr = context->sync_frame; } #ifdef WITH_LIBMV +/* **** utility functions for tracking **** */ -/* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ +/* convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { @@ -1483,12 +2145,12 @@ static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int for (i = 0; i < num_pixels; i++) { const unsigned char *pixel = rgba + i * 4; - *gray++ = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; + gray[i] = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; } } -static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int *width_r, int *height_r) +static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int *width_r, int *height_r) { ImBuf *searchibuf; float *gray_pixels; @@ -1499,9 +2161,6 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT width = searchibuf->x; height = searchibuf->y; - *width_r = searchibuf->x; - *height_r = searchibuf->y; - gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); if (searchibuf->rect_float) { @@ -1515,39 +2174,13 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT IMB_freeImBuf(searchibuf); - return gray_pixels; -} - -static unsigned char *get_ucharbuf(ImBuf *ibuf) -{ - int x, y; - unsigned char *pixels, *cp; - - cp = pixels = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned char), "tracking ucharBuf"); - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - int pixel = ibuf->x * y + x; - - if (ibuf->rect_float) { - const float *rrgbf = ibuf->rect_float + pixel * 4; - const float grey_f = 0.2126f * rrgbf[0] + 0.7152f * rrgbf[1] + 0.0722f * rrgbf[2]; + *width_r = width; + *height_r = height; - *cp = FTOCHAR(grey_f); - } - else { - const unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4; - - *cp = 0.2126f * rrgb[0] + 0.7152f * rrgb[1] + 0.0722f * rrgb[2]; - } - - cp++; - } - } - - return pixels; + return gray_pixels; } -static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) +static ImBuf *tracking_context_get_frame_ibuf(MovieTrackingContext *context, int framenr) { ImBuf *ibuf; MovieClipUser user = context->user; @@ -1559,13 +2192,11 @@ static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) return ibuf; } -static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, - MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed) +MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker) { - int framenr = marker->framenr; int a = marker - track->markers; - - *marker_keyed = marker; + MovieTrackingMarker *marker_keyed = marker; while (a >= 0 && a < track->markersnr) { int next = (context->backwards) ? a + 1 : a - 1; @@ -1583,8 +2214,7 @@ static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTra is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0; if (is_keyframed) { - framenr = cur_marker->framenr; - *marker_keyed = cur_marker; + marker_keyed = cur_marker; break; } @@ -1592,19 +2222,34 @@ static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTra a = next; } - return get_frame_ibuf(context, framenr); + return marker_keyed; +} + +static ImBuf *tracking_context_get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed_r) +{ + MovieTrackingMarker *marker_keyed; + int keyed_framenr; + + marker_keyed = tracking_context_get_keyframed_marker(context, track, marker); + keyed_framenr = marker_keyed->framenr; + + *marker_keyed_r = marker_keyed; + + return tracking_context_get_frame_ibuf(context, keyed_framenr); } -static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int curfra, MovieTrackingMarker **marker_keyed) +static ImBuf *tracking_context_get_reference_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker, int curfra, + MovieTrackingMarker **marker_keyed) { ImBuf *ibuf = NULL; if (track->pattern_match == TRACK_MATCH_KEYFRAME) { - ibuf = get_keyframed_ibuf(context, track, marker, marker_keyed); + ibuf = tracking_context_get_keyframed_ibuf(context, track, marker, marker_keyed); } else { - ibuf = get_frame_ibuf(context, curfra); + ibuf = tracking_context_get_frame_ibuf(context, curfra); /* use current marker as keyframed position */ *marker_keyed = marker; @@ -1613,7 +2258,78 @@ static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack return ibuf; } -static void marker_search_scale_after_tracking(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker) +static void track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context, + MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra, + int frame_width, int frame_height) +{ + MovieTrackingMarker *marker_keyed = NULL; + ImBuf *reference_ibuf = NULL; + int width, height; + + /* calculate patch for keyframed position */ + reference_ibuf = tracking_context_get_reference_ibuf(context, track, marker, curfra, &marker_keyed); + track_context->marker = *marker_keyed; + + if (track_context->search_area) { + MEM_freeN(track_context->search_area); + } + + track_context->search_area = track_get_search_floatbuf(reference_ibuf, track, marker_keyed, &width, &height); + track_context->search_area_height = height; + track_context->search_area_width = width; + + if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) { + if (track_context->mask) + MEM_freeN(track_context->mask); + + track_context->mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker); + } + + IMB_freeImBuf(reference_ibuf); +} + +static void tracking_configure_tracker(TrackContext *track_context, MovieTrackingTrack *track, + struct libmv_trackRegionOptions *options) +{ + options->motion_model = track->motion_model; + + options->use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0); + + options->use_normalization = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0); + + options->num_iterations = 50; + options->minimum_correlation = track->minimum_correlation; + options->sigma = 0.9; + + if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) + options->image1_mask = track_context->mask; +} + +/* returns FALSE if marker crossed margin area from frame bounds */ +static int tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker, + int frame_width, int frame_height) +{ + float pat_min[2], pat_max[2], dim[2], margin[2]; + + /* margin from frame boundaries */ + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + sub_v2_v2v2(dim, pat_max, pat_min); + margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f; + + margin[0] = MAX2(margin[0], (float)track->margin / frame_width); + margin[1] = MAX2(margin[1], (float)track->margin / frame_height); + + /* do not track markers which are too close to boundary */ + if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || + marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1]) + { + return FALSE; + } + + return TRUE; +} + +static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker) { float old_pat_min[2], old_pat_max[2]; float new_pat_min[2], new_pat_max[2]; @@ -1632,73 +2348,89 @@ static void marker_search_scale_after_tracking(const MovieTrackingMarker *old_ma new_marker->search_max[1] *= scale_y; } -#endif - -void BKE_tracking_sync(MovieTrackingContext *context) +static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track, + const MovieTrackingMarker *old_marker, int curfra, int tracked, + int frame_width, int frame_height, + double dst_pixel_x[5], double dst_pixel_y[5]) { - MovieTracking *tracking = &context->clip->tracking; - int newframe; + MovieTrackingMarker new_marker; + int frame_delta = context->backwards ? -1 : 1; + int nextfra = curfra + frame_delta; - tracks_map_merge(context->tracks_map, tracking); + new_marker = *old_marker; - if (context->backwards) - newframe = context->user.framenr + 1; - else - newframe = context->user.framenr - 1; + if (tracked) { + set_marker_coords_from_tracking(frame_width, frame_height, &new_marker, dst_pixel_x, dst_pixel_y); + new_marker.flag |= MARKER_TRACKED; + new_marker.framenr = nextfra; - context->sync_frame = newframe; + tracking_scale_marker_search(old_marker, &new_marker); - tracking->dopesheet.ok = FALSE; -} + if (context->first_time) { + /* check if there's no keyframe/tracked markers before tracking marker. + * if so -- create disabled marker before currently tracking "segment" + */ -void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context) -{ - user->framenr = context->sync_frame; + tracking_marker_insert_disabled(track, &new_marker, !context->backwards, FALSE); + } + + /* insert currently tracked marker */ + BKE_tracking_marker_insert(track, &new_marker); + + /* make currently tracked segment be finished with disabled marker */ + tracking_marker_insert_disabled(track, &new_marker, context->backwards, FALSE); + } + else { + new_marker.framenr = nextfra; + new_marker.flag |= MARKER_DISABLED; + + BKE_tracking_marker_insert(track, &new_marker); + } } -int BKE_tracking_next(MovieTrackingContext *context) +#endif + +int BKE_tracking_context_step(MovieTrackingContext *context) { ImBuf *destination_ibuf; + int frame_delta = context->backwards ? -1 : 1; int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr); + int nextfra; int a, ok = FALSE, map_size; int frame_width, frame_height; - map_size = tracks_map_size(context->tracks_map); + map_size = tracks_map_get_size(context->tracks_map); /* nothing to track, avoid unneeded frames reading to save time and memory */ if (!map_size) return FALSE; - if (context->backwards) - context->user.framenr--; - else - context->user.framenr++; + context->user.framenr += frame_delta; destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); if (!destination_ibuf) return FALSE; + nextfra = curfra + frame_delta; + frame_width = destination_ibuf->x; frame_height = destination_ibuf->y; - //#pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size>1) + #pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size>1) for (a = 0; a < map_size; a++) { TrackContext *track_context = NULL; MovieTrackingTrack *track; MovieTrackingMarker *marker; - tracks_map_get(context->tracks_map, a, &track, (void **)&track_context); + tracks_map_get_indexed_element(context->tracks_map, a, &track, (void **)&track_context); - marker = BKE_tracking_exact_marker(track, curfra); + marker = BKE_tracking_marker_get_exact(track, curfra); if (marker && (marker->flag & MARKER_DISABLED) == 0) { #ifdef WITH_LIBMV - int width, height, tracked = 0, need_readjust = 0; - float margin[2], dim[2], pat_min[2], pat_max[2]; - MovieTrackingMarker marker_new, *marker_keyed; - int onbound = FALSE, nextfra; + int width, height, tracked = FALSE, need_readjust; double dst_pixel_x[5], dst_pixel_y[5]; if (track->pattern_match == TRACK_MATCH_KEYFRAME) @@ -1706,29 +2438,10 @@ int BKE_tracking_next(MovieTrackingContext *context) else need_readjust = TRUE; - if (context->backwards) - nextfra = curfra - 1; - else - nextfra = curfra + 1; - - /* margin from frame boundaries */ - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - sub_v2_v2v2(dim, pat_max, pat_min); - margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f; - - margin[0] = MAX2(margin[0], (float)track->margin / destination_ibuf->x); - margin[1] = MAX2(margin[1], (float)track->margin / destination_ibuf->y); - /* do not track markers which are too close to boundary */ - if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || - marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1]) - { - onbound = TRUE; - } - else { + if (tracking_check_marker_margin(track, marker, frame_width, frame_height)) { /* to convert to the x/y split array format for libmv. */ - double src_pixel_x[5]; - double src_pixel_y[5]; + double src_pixel_x[5], src_pixel_y[5]; /* settings for the tracker */ struct libmv_trackRegionOptions options = {0}; @@ -1737,57 +2450,24 @@ int BKE_tracking_next(MovieTrackingContext *context) float *patch_new; if (need_readjust) { - ImBuf *reference_ibuf = NULL; - /* calculate patch for keyframed position */ - reference_ibuf = get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); - track_context->marker = *marker_keyed; - - if (track_context->search_area) - MEM_freeN(track_context->search_area); - - track_context->search_area = get_search_floatbuf(reference_ibuf, track, - marker_keyed, &width, &height); - track_context->search_area_height = height; - track_context->search_area_width = width; - - IMB_freeImBuf(reference_ibuf); - - if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) { - if (track_context->mask) - MEM_freeN(track_context->mask); - - track_context->mask = BKE_tracking_track_mask_get(frame_width, frame_height, - track, marker); - } + track_context_update_reference(context, track_context, track, marker, + curfra, frame_width, frame_height); } /* for now track to the same search area dimension as marker has got for current frame * will make all tracked markers in currently tracked segment have the same search area * size, but it's quite close to what is actually needed */ - patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height); - - /* Configure the tracker */ - options.motion_model = track->motion_model; - - options.use_brute = - ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0); + patch_new = track_get_search_floatbuf(destination_ibuf, track, marker, &width, &height); - options.use_normalization = - ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0); + /* configure the tracker */ + tracking_configure_tracker(track_context, track, &options); - options.num_iterations = 50; - options.minimum_correlation = track->minimum_correlation; - options.sigma = 0.9; - - if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) - options.image1_mask = track_context->mask; - - /* Convert the marker corners and center into pixel coordinates in the search/destination images. */ + /* convert the marker corners and center into pixel coordinates in the search/destination images. */ get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y); get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y); - /* Run the tracker! */ + /* run the tracker! */ tracked = libmv_trackRegion(&options, track_context->search_area, track_context->search_area_width, @@ -1799,42 +2479,10 @@ int BKE_tracking_next(MovieTrackingContext *context) MEM_freeN(patch_new); } - if (tracked && !onbound) { - memset(&marker_new, 0, sizeof(marker_new)); - marker_new = *marker; - set_marker_coords_from_tracking(frame_width, frame_height, &marker_new, dst_pixel_x, dst_pixel_y); - marker_new.flag |= MARKER_TRACKED; - marker_new.framenr = nextfra; - - marker_search_scale_after_tracking(marker, &marker_new); - - //#pragma omp critical - { - if (context->first_time) { - /* check if there's no keyframe/tracked markers before tracking marker. - * if so -- create disabled marker before currently tracking "segment" - */ - - put_disabled_marker(track, &marker_new, !context->backwards, 0); - } - - /* insert currently tracked marker */ - BKE_tracking_insert_marker(track, &marker_new); - - /* make currently tracked segment be finished with disabled marker */ - put_disabled_marker(track, &marker_new, context->backwards, 0); - } - } - else { - marker_new = *marker; - - marker_new.framenr = nextfra; - marker_new.flag |= MARKER_DISABLED; - - //#pragma omp critical - { - BKE_tracking_insert_marker(track, &marker_new); - } + #pragma omp critical + { + tracking_insert_new_marker(context, track, marker, curfra, tracked, + frame_width, frame_height, dst_pixel_x, dst_pixel_y); } ok = TRUE; @@ -1853,7 +2501,7 @@ int BKE_tracking_next(MovieTrackingContext *context) return ok; } -/*********************** camera solving *************************/ +/*********************** Camera solving *************************/ typedef struct MovieReconstructContext { #ifdef WITH_LIBMV @@ -1886,8 +2534,8 @@ typedef struct ReconstructProgressData { int message_size; } ReconstructProgressData; -#if WITH_LIBMV -static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height) +#ifdef WITH_LIBMV +static struct libmv_Tracks *libmv_tracks_new(ListBase *tracksbase, int width, int height) { int tracknr = 0; MovieTrackingTrack *track; @@ -1913,7 +2561,7 @@ static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, return tracks; } -static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *context, MovieTracking *tracking) +static void reconstruct_retrieve_libmv_intrinscis(MovieReconstructContext *context, MovieTracking *tracking) { struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction; struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction); @@ -1934,7 +2582,7 @@ static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *conte tracking->camera.k2 = k2; } -static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking) +static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking) { struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction; MovieTrackingReconstruction *reconstruction = NULL; @@ -1950,7 +2598,7 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M reconstruction = &tracking->reconstruction; } else { - MovieTrackingObject *object = BKE_tracking_named_object(tracking, context->object_name); + MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, context->object_name); tracksbase = &object->tracks; reconstruction = &object->reconstruction; @@ -2042,15 +2690,15 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M return ok; } -static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking) +static int reconstruct_retrieve_libmv(MovieReconstructContext *context, MovieTracking *tracking) { /* take the intrinscis back from libmv */ - retrieve_libmv_reconstruct_intrinscis(context, tracking); + reconstruct_retrieve_libmv_intrinscis(context, tracking); - return retrieve_libmv_reconstruct_tracks(context, tracking); + return reconstruct_retrieve_libmv_tracks(context, tracking); } -static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object) +static int reconstruct_refine_intrinsics_get_flags(MovieTracking *tracking, MovieTrackingObject *object) { int refine = tracking->settings.refine_camera_intrinsics; int flags = 0; @@ -2073,7 +2721,7 @@ static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObj return flags; } -static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase) +static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase) { int tot = 0; int frame1 = tracking->settings.keyframe1, frame2 = tracking->settings.keyframe2; @@ -2081,9 +2729,11 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tra track = tracksbase->first; while (track) { - if (BKE_tracking_has_enabled_marker(track, frame1)) - if (BKE_tracking_has_enabled_marker(track, frame2)) + if (BKE_tracking_track_has_enabled_marker_at_frame(track, frame1)) { + if (BKE_tracking_track_has_enabled_marker_at_frame(track, frame2)) { tot++; + } + } track = track->next; } @@ -2092,16 +2742,16 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tra } #endif -int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) +int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) { #if WITH_LIBMV - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) { /* TODO: check for number of tracks? */ return TRUE; } - else if (count_tracks_on_both_keyframes(tracking, tracksbase) < 8) { + else if (reconstruct_count_tracks_on_both_keyframes(tracking, tracksbase) < 8) { BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction", error_size); @@ -2124,7 +2774,7 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking * { MovieReconstructContext *context = MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data"); MovieTrackingCamera *camera = &tracking->camera; - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); float aspy = 1.0f / tracking->camera.pixel_aspect; int num_tracks = BLI_countlist(tracksbase); int sfra = INT_MAX, efra = INT_MIN; @@ -2134,6 +2784,14 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking * context->is_camera = object->flag & TRACKING_OBJECT_CAMERA; context->motion_flag = tracking->settings.motion_flag; + context->focal_length = camera->focal; + context->principal_point[0] = camera->principal[0]; + context->principal_point[1] = camera->principal[1] * aspy; + + context->k1 = camera->k1; + context->k2 = camera->k2; + context->k3 = camera->k3; + context->tracks_map = tracks_map_new(context->object_name, context->is_camera, num_tracks, 0); track = tracksbase->first; @@ -2169,10 +2827,10 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking * context->efra = efra; #ifdef WITH_LIBMV - context->tracks = create_libmv_tracks(tracksbase, width, height * aspy); + context->tracks = libmv_tracks_new(tracksbase, width, height * aspy); context->keyframe1 = keyframe1; context->keyframe2 = keyframe2; - context->refine_flags = get_refine_intrinsics_flags(tracking, object); + context->refine_flags = reconstruct_refine_intrinsics_get_flags(tracking, object); #else (void) width; (void) height; @@ -2180,14 +2838,6 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking * (void) keyframe2; #endif - context->focal_length = camera->focal; - context->principal_point[0] = camera->principal[0]; - context->principal_point[1] = camera->principal[1] * aspy; - - context->k1 = camera->k1; - context->k2 = camera->k2; - context->k3 = camera->k3; - return context; } @@ -2206,7 +2856,7 @@ void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context) } #ifdef WITH_LIBMV -static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message) +static void reconstruct_update_solve_cb(void *customdata, double progress, const char *message) { ReconstructProgressData *progressdata = customdata; @@ -2231,7 +2881,7 @@ static int solve_reconstruction_testbreak_cb(void *customdata) } #endif -void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop, short *do_update, +void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *stop, short *do_update, float *progress, char *stats_message, int message_size) { #ifdef WITH_LIBMV @@ -2250,7 +2900,7 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * context->focal_length, context->principal_point[0], context->principal_point[1], context->k1, context->k2, context->k3, - solve_reconstruction_update_cb, &progressdata); + reconstruct_update_solve_cb, &progressdata); } else { context->reconstruction = libmv_solveReconstruction(context->tracks, @@ -2259,7 +2909,7 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * context->focal_length, context->principal_point[0], context->principal_point[1], context->k1, context->k2, context->k3, - solve_reconstruction_update_cb, &progressdata); + reconstruct_update_solve_cb, &progressdata); } error = libmv_reprojectionError(context->reconstruction); @@ -2275,7 +2925,7 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * #endif } -int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking) +int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking) { MovieTrackingReconstruction *reconstruction; @@ -2287,7 +2937,7 @@ int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTr else { MovieTrackingObject *object; - object = BKE_tracking_named_object(tracking, context->object_name); + object = BKE_tracking_object_get_named(tracking, context->object_name); reconstruction = &object->reconstruction; } @@ -2295,350 +2945,17 @@ int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTr reconstruction->flag |= TRACKING_RECONSTRUCTED; #ifdef WITH_LIBMV - if (!retrieve_libmv_reconstruct(context, tracking)) + if (!reconstruct_retrieve_libmv(context, tracking)) return FALSE; #endif return TRUE; } -void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track) -{ - BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); -} - -MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name) -{ - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; - - while (track) { - if (!strcmp(track->name, name)) - return track; - - track = track->next; - } - - return NULL; -} - -static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest) -{ - MovieReconstructedCamera *cameras = reconstruction->cameras; - int a = 0, d = 1; - - if (!reconstruction->camnr) - return -1; - - if (framenr < cameras[0].framenr) { - if (nearest) - return 0; - else - return -1; - } - - if (framenr > cameras[reconstruction->camnr - 1].framenr) { - if (nearest) - return reconstruction->camnr - 1; - else - return -1; - } - - if (reconstruction->last_camera < reconstruction->camnr) - a = reconstruction->last_camera; - - if (cameras[a].framenr >= framenr) - d = -1; - - while (a >= 0 && a < reconstruction->camnr) { - int cfra = cameras[a].framenr; - - /* check if needed framenr was "skipped" -- no data for requested frame */ - - if (d > 0 && cfra > framenr) { - /* interpolate with previous position */ - if (nearest) - return a - 1; - else - break; - } - - if (d < 0 && cfra < framenr) { - /* interpolate with next position */ - if (nearest) - return a; - else - break; - } - - if (cfra == framenr) { - reconstruction->last_camera = a; - - return a; - } - - a += d; - } - - return -1; -} - -static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4]) -{ - if ((object->flag & TRACKING_OBJECT_CAMERA) == 0) { - float smat[4][4]; - - scale_m4_fl(smat, 1.0f / object->scale); - mult_m4_m4m4(mat, mat, smat); - } -} - -MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, - MovieTrackingObject *object, int framenr) -{ - MovieTrackingReconstruction *reconstruction; - int a; - - reconstruction = BKE_tracking_object_reconstruction(tracking, object); - a = reconstruction_camera_index(reconstruction, framenr, FALSE); - - if (a == -1) - return NULL; - - return &reconstruction->cameras[a]; -} - -void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object, - int framenr, float mat[4][4]) -{ - MovieTrackingReconstruction *reconstruction; - MovieReconstructedCamera *cameras; - int a; - - reconstruction = BKE_tracking_object_reconstruction(tracking, object); - cameras = reconstruction->cameras; - a = reconstruction_camera_index(reconstruction, framenr, 1); - - if (a == -1) { - unit_m4(mat); - - return; - } - - if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) { - float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr); - - blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t); - } - else { - copy_m4_m4(mat, cameras[a].mat); - } - - scale_reconstructed_camera(object, mat); -} - -void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4]) -{ - if (!ob) { - if (scene->camera) - ob = scene->camera; - else - ob = BKE_scene_camera_find(scene); - } - - if (ob) - BKE_object_where_is_calc_mat4(scene, ob, mat); - else - unit_m4(mat); -} - -void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty) -{ - /* indeed in both of cases it should be winx -- it's just how camera shift works for blender's camera */ - *shiftx = (0.5f * winx - tracking->camera.principal[0]) / winx; - *shifty = (0.5f * winy - tracking->camera.principal[1]) / winx; -} - -void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height) -{ - float focal = tracking->camera.focal; - - camera->sensor_x = tracking->camera.sensor_width; - camera->sensor_fit = CAMERA_SENSOR_FIT_AUTO; - camera->lens = focal * camera->sensor_x / width; - - scene->r.xsch = width * tracking->camera.pixel_aspect; - scene->r.ysch = height; - - scene->r.xasp = 1.0f; - scene->r.yasp = 1.0f; - - BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty); -} - -void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object, - int framenr, int winx, int winy, float mat[4][4]) -{ - MovieReconstructedCamera *camera; - float lens = tracking->camera.focal * tracking->camera.sensor_width / (float)winx; - float viewfac, pixsize, left, right, bottom, top, clipsta, clipend; - float winmat[4][4]; - float ycor = 1.0f / tracking->camera.pixel_aspect; - float shiftx, shifty, winside = MAX2(winx, winy); - - BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty); - - clipsta = 0.1f; - clipend = 1000.0f; - - if (winx >= winy) - viewfac = (lens * winx) / tracking->camera.sensor_width; - else - viewfac = (ycor * lens * winy) / tracking->camera.sensor_width; - - pixsize = clipsta / viewfac; - - left = -0.5f * (float)winx + shiftx * winside; - bottom = -0.5f * (ycor) * (float)winy + shifty * winside; - right = 0.5f * (float)winx + shiftx * winside; - top = 0.5f * (ycor) * (float)winy + shifty * winside; - - left *= pixsize; - right *= pixsize; - bottom *= pixsize; - top *= pixsize; - - perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); - - camera = BKE_tracking_get_reconstructed_camera(tracking, object, framenr); - - if (camera) { - float imat[4][4]; - - invert_m4_m4(imat, camera->mat); - mult_m4_m4m4(mat, winmat, imat); - } - else copy_m4_m4(mat, winmat); -} - -ListBase *BKE_tracking_get_tracks(MovieTracking *tracking) -{ - MovieTrackingObject *object = BKE_tracking_active_object(tracking); - - if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) { - return &object->tracks; - } - - return &tracking->tracks; -} - -MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking) -{ - ListBase *tracksbase; - - if (!tracking->act_track) - return NULL; - - tracksbase = BKE_tracking_get_tracks(tracking); - - /* check that active track is in current tracks list */ - if (BLI_findindex(tracksbase, tracking->act_track) >= 0) - return tracking->act_track; - - return NULL; -} - -MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking) -{ - return BLI_findlink(&tracking->objects, tracking->objectnr); -} - -MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking) -{ - MovieTrackingObject *object = tracking->objects.first; - - while (object) { - if (object->flag & TRACKING_OBJECT_CAMERA) - return object; - - object = object->next; - } - - return NULL; -} - -ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object) -{ - if (object->flag & TRACKING_OBJECT_CAMERA) { - return &tracking->tracks; - } - - return &object->tracks; -} - -MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object) -{ - if (object->flag & TRACKING_OBJECT_CAMERA) { - return &tracking->reconstruction; - } - - return &object->reconstruction; -} - -MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking) -{ - MovieTrackingObject *object = BKE_tracking_active_object(tracking); - - return BKE_tracking_object_reconstruction(tracking, object); -} - -void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2]) -{ - MovieTrackingCamera *camera = &tracking->camera; +/*********************** Feature detection *************************/ #ifdef WITH_LIBMV - double x, y; - float aspy = 1.0f / tracking->camera.pixel_aspect; - - /* normalize coords */ - x = (co[0] - camera->principal[0]) / camera->focal; - y = (co[1] - camera->principal[1] * aspy) / camera->focal; - - libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, x, y, &x, &y); - - /* result is in image coords already */ - nco[0] = x; - nco[1] = y; -#else - (void) camera; - (void) co; - (void) nco; -#endif -} - -void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2]) -{ - MovieTrackingCamera *camera = &tracking->camera; - -#ifdef WITH_LIBMV - double x = co[0], y = co[1]; - float aspy = 1.0f / tracking->camera.pixel_aspect; - - libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, x, y, &x, &y); - - nco[0] = x * camera->focal + camera->principal[0]; - nco[1] = y * camera->focal + camera->principal[1] * aspy; -#else - (void) camera; - (void) co; - (void) nco; -#endif -} - -#ifdef WITH_LIBMV -static int point_in_stroke(bGPDstroke *stroke, float x, float y) +static int check_point_in_stroke(bGPDstroke *stroke, float x, float y) { int i, prev; int count = 0; @@ -2660,7 +2977,7 @@ static int point_in_stroke(bGPDstroke *stroke, float x, float y) return count % 2; } -static int point_in_layer(bGPDlayer *layer, float x, float y) +static int check_point_in_layer(bGPDlayer *layer, float x, float y) { bGPDframe *frame = layer->frames.first; @@ -2668,7 +2985,7 @@ static int point_in_layer(bGPDlayer *layer, float x, float y) bGPDstroke *stroke = frame->strokes.first; while (stroke) { - if (point_in_stroke(stroke, x, y)) + if (check_point_in_stroke(stroke, x, y)) return TRUE; stroke = stroke->next; @@ -2679,9 +2996,9 @@ static int point_in_layer(bGPDlayer *layer, float x, float y) return FALSE; } -static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase, - struct libmv_Features *features, int framenr, int width, int height, - bGPDlayer *layer, int place_outside_layer) +static void detect_retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase, + struct libmv_Features *features, int framenr, int width, int height, + bGPDlayer *layer, int place_outside_layer) { int a; @@ -2698,16 +3015,45 @@ static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbas yu = y / height; if (layer) - ok = point_in_layer(layer, xu, yu) != place_outside_layer; + ok = check_point_in_layer(layer, xu, yu) != place_outside_layer; if (ok) { - track = BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height); + track = BKE_tracking_track_add(tracking, tracksbase, xu, yu, framenr, width, height); track->flag |= SELECT; track->pat_flag |= SELECT; track->search_flag |= SELECT; } } } + +static unsigned char *detect_get_frame_ucharbuf(ImBuf *ibuf) +{ + int x, y; + unsigned char *pixels, *cp; + + cp = pixels = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned char), "tracking ucharBuf"); + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + int pixel = ibuf->x * y + x; + + if (ibuf->rect_float) { + const float *rrgbf = ibuf->rect_float + pixel * 4; + const float grey_f = 0.2126f * rrgbf[0] + 0.7152f * rrgbf[1] + 0.0722f * rrgbf[2]; + + *cp = FTOCHAR(grey_f); + } + else { + const unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4; + + *cp = 0.2126f * rrgb[0] + 0.7152f * rrgb[1] + 0.0722f * rrgb[2]; + } + + cp++; + } + } + + return pixels; +} #endif void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf, @@ -2716,14 +3062,14 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImB { #ifdef WITH_LIBMV struct libmv_Features *features; - unsigned char *pixels = get_ucharbuf(ibuf); + unsigned char *pixels = detect_get_frame_ucharbuf(ibuf); features = libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, margin, min_trackness, min_distance); MEM_freeN(pixels); - retrieve_libmv_features(tracking, tracksbase, features, framenr, + detect_retrieve_libmv_features(tracking, tracksbase, features, framenr, ibuf->x, ibuf->y, layer, place_outside_layer); libmv_destroyFeatures(features); @@ -2740,38 +3086,9 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImB #endif } -MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r) -{ - MovieTrackingObject *object; - int cur = 1; - - object = tracking->objects.first; - while (object) { - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; - - while (track) { - if (track->flag & TRACK_HAS_BUNDLE) { - if (cur == tracknr) { - *tracksbase_r = tracksbase; - return track; - } - - cur++; - } - - track = track->next; - } - - object = object->next; - } - - *tracksbase_r = NULL; +/*********************** 2D stabilization *************************/ - return NULL; -} - -static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2]) +static int stabilization_median_point_get(MovieTracking *tracking, int framenr, float median[2]) { int ok = FALSE; float min[2], max[2]; @@ -2782,7 +3099,7 @@ static int stabilization_median_point(MovieTracking *tracking, int framenr, floa track = tracking->tracks.first; while (track) { if (track->flag & TRACK_USE_2D_STAB) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); DO_MINMAX2(marker->pos, min, max); @@ -2798,8 +3115,9 @@ static int stabilization_median_point(MovieTracking *tracking, int framenr, floa return ok; } -static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height, - float firstmedian[2], float median[2], float loc[2], float *scale, float *angle) +static void stabilization_calculate_data(MovieTracking *tracking, int framenr, float width, float height, + float firstmedian[2], float median[2], float loc[2], + float *scale, float *angle) { MovieTrackingStabilization *stab = &tracking->stabilization; @@ -2817,12 +3135,12 @@ static void calculate_stabdata(MovieTracking *tracking, int framenr, float width float x0 = (float)width / 2.0f, y0 = (float)height / 2.0f; float x = median[0] * width, y = median[1] * height; - marker = BKE_tracking_get_marker(stab->rot_track, 1); + marker = BKE_tracking_marker_get(stab->rot_track, 1); sub_v2_v2v2(a, marker->pos, firstmedian); a[0] *= width; a[1] *= height; - marker = BKE_tracking_get_marker(stab->rot_track, framenr); + marker = BKE_tracking_marker_get(stab->rot_track, framenr); sub_v2_v2v2(b, marker->pos, median); b[0] *= width; b[1] *= height; @@ -2836,7 +3154,7 @@ static void calculate_stabdata(MovieTracking *tracking, int framenr, float width } } -static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height) +static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, int width, int height) { float firstmedian[2]; MovieTrackingStabilization *stab = &tracking->stabilization; @@ -2845,7 +3163,7 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, if (stab->ok) return stab->scale; - if (stabilization_median_point(tracking, 1, firstmedian)) { + if (stabilization_median_point_get(tracking, 1, firstmedian)) { int sfra = INT_MAX, efra = INT_MIN, cfra; float scale = 1.0f; MovieTrackingTrack *track; @@ -2872,11 +3190,11 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}}; float si, co; - stabilization_median_point(tracking, cfra, median); + stabilization_median_point_get(tracking, cfra, median); - calculate_stabdata(tracking, cfra, width, height, firstmedian, median, loc, &tmp_scale, &angle); + stabilization_calculate_data(tracking, cfra, width, height, firstmedian, median, loc, &tmp_scale, &angle); - BKE_tracking_stabdata_to_mat4(width, height, aspect, loc, 1.0f, angle, mat); + BKE_tracking_stabilization_data_to_mat4(width, height, aspect, loc, 1.0f, angle, mat); si = sin(angle); co = cos(angle); @@ -2954,7 +3272,7 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, return stab->scale; } -static ImBuf *stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill) +static ImBuf *stabilization_allocate_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill) { int flags; @@ -2983,8 +3301,8 @@ static ImBuf *stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill) return cacheibuf; } -void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, - float loc[2], float *scale, float *angle) +void BKE_tracking_stabilization_data_get(MovieTracking *tracking, int framenr, int width, int height, + float loc[2], float *scale, float *angle) { float firstmedian[2], median[2]; MovieTrackingStabilization *stab = &tracking->stabilization; @@ -2997,22 +3315,22 @@ void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int w return; } - if (stabilization_median_point(tracking, 1, firstmedian)) { - stabilization_median_point(tracking, framenr, median); + if (stabilization_median_point_get(tracking, 1, firstmedian)) { + stabilization_median_point_get(tracking, framenr, median); if ((stab->flag & TRACKING_AUTOSCALE) == 0) stab->scale = 1.0f; if (!stab->ok) { if (stab->flag & TRACKING_AUTOSCALE) - stabilization_auto_scale_factor(tracking, width, height); + stabilization_calculate_autoscale_factor(tracking, width, height); - calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); + stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); stab->ok = TRUE; } else { - calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); + stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); } } else { @@ -3022,8 +3340,8 @@ void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int w } } -ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, - float loc[2], float *scale, float *angle) +ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf *ibuf, + float loc[2], float *scale, float *angle) { float tloc[2], tscale, tangle; MovieTrackingStabilization *stab = &tracking->stabilization; @@ -3047,17 +3365,17 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, return ibuf; } - BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle); + BKE_tracking_stabilization_data_get(tracking, framenr, width, height, tloc, &tscale, &tangle); - tmpibuf = stabilize_alloc_ibuf(NULL, ibuf, TRUE); + tmpibuf = stabilization_allocate_ibuf(NULL, ibuf, TRUE); /* scale would be handled by matrix transformation when angle is non-zero */ if (tscale != 1.0f && tangle == 0.0f) { ImBuf *scaleibuf; - stabilization_auto_scale_factor(tracking, width, height); + stabilization_calculate_autoscale_factor(tracking, width, height); - scaleibuf = stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0); + scaleibuf = stabilization_allocate_ibuf(stab->scaleibuf, ibuf, 0); stab->scaleibuf = scaleibuf; IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); @@ -3080,7 +3398,7 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, int i, j, filter = tracking->stabilization.filter; void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL; - BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); + BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); invert_m4(mat); if (filter == TRACKING_FILTER_NEAREAST) @@ -3121,8 +3439,8 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, return tmpibuf; } -void BKE_tracking_stabdata_to_mat4(int width, int height, float aspect, - float loc[2], float scale, float angle, float mat[4][4]) +void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, float loc[2], + float scale, float angle, float mat[4][4]) { float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4], amat[4][4], iamat[4][4]; float svec[3] = {scale, scale, scale}; @@ -3150,241 +3468,7 @@ void BKE_tracking_stabdata_to_mat4(int width, int height, float aspect, mul_serie_m4(mat, lmat, cmat, amat, rmat, iamat, smat, icmat, NULL); } -MovieDistortion *BKE_tracking_distortion_create(void) -{ - MovieDistortion *distortion; - - distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); - - return distortion; -} - -MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion) -{ - MovieDistortion *new_distortion; - - new_distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); - -#ifdef WITH_LIBMV - new_distortion->intrinsics = libmv_CameraIntrinsicsCopy(distortion->intrinsics); -#else - (void) distortion; -#endif - - return new_distortion; -} - -void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height) -{ - MovieTrackingCamera *camera = &tracking->camera; - float aspy = 1.0f / tracking->camera.pixel_aspect; - -#ifdef WITH_LIBMV - if (!distortion->intrinsics) { - distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal, - camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, width, height * aspy); - } - else { - libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal, - camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, width, height * aspy); - } -#else - (void) distortion; - (void) width; - (void) height; - (void) camera; - (void) aspy; -#endif -} - -ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, - ImBuf *ibuf, int width, int height, float overscan, int undistort) -{ - ImBuf *resibuf; - - BKE_tracking_distortion_update(distortion, tracking, width, height); - - resibuf = IMB_dupImBuf(ibuf); - - if (ibuf->rect_float) { -#ifdef WITH_LIBMV - if (undistort) { - libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } - else { - libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } -#endif - - resibuf->userflags |= IB_RECT_INVALID; - } - else { -#ifdef WITH_LIBMV - if (undistort) { - libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics, - (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } - else { - libmv_CameraIntrinsicsDistortByte(distortion->intrinsics, - (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } -#endif - } - -#ifndef WITH_LIBMV - (void) overscan; - (void) undistort; -#endif - - return resibuf; -} - -void BKE_tracking_distortion_destroy(MovieDistortion *distortion) -{ -#ifdef WITH_LIBMV - libmv_CameraIntrinsicsDestroy(distortion->intrinsics); -#endif - - MEM_freeN(distortion); -} - -ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan) -{ - MovieTrackingCamera *camera = &tracking->camera; - - if (camera->intrinsics == NULL) - camera->intrinsics = BKE_tracking_distortion_create(); - - return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1); -} - -ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan) -{ - MovieTrackingCamera *camera = &tracking->camera; - - if (camera->intrinsics == NULL) - camera->intrinsics = BKE_tracking_distortion_create(); - - return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0); -} - -/* area - which part of marker should be selected. see TRACK_AREA_* constants */ -void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend) -{ - if (extend) { - BKE_tracking_track_flag(track, area, SELECT, 0); - } - else { - MovieTrackingTrack *cur = tracksbase->first; - - while (cur) { - if ((cur->flag & TRACK_HIDDEN) == 0) { - if (cur == track) { - BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1); - BKE_tracking_track_flag(cur, area, SELECT, 0); - } - else { - BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1); - } - } - - cur = cur->next; - } - } -} - -void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area) -{ - BKE_tracking_track_flag(track, area, SELECT, 1); -} - -MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name) -{ - MovieTrackingObject *object = MEM_callocN(sizeof(MovieTrackingObject), "tracking object"); - - if (tracking->tot_object == 0) { - /* first object is always camera */ - BLI_strncpy(object->name, "Camera", sizeof(object->name)); - - object->flag |= TRACKING_OBJECT_CAMERA; - } - else { - BLI_strncpy(object->name, name, sizeof(object->name)); - } - - BLI_addtail(&tracking->objects, object); - - tracking->tot_object++; - tracking->objectnr = BLI_countlist(&tracking->objects) - 1; - - object->scale = 1.0f; - - BKE_tracking_object_unique_name(tracking, object); - - return object; -} - -void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object) -{ - MovieTrackingTrack *track; - int index = BLI_findindex(&tracking->objects, object); - - if (index < 0) - return; - - if (object->flag & TRACKING_OBJECT_CAMERA) { - /* object used for camera solving can't be deleted */ - return; - } - - track = object->tracks.first; - while (track) { - if (track == tracking->act_track) - tracking->act_track = NULL; - - track = track->next; - } - - tracking_object_free(object); - BLI_freelinkN(&tracking->objects, object); - - tracking->tot_object--; - - if (index > 0) - tracking->objectnr = index - 1; - else - tracking->objectnr = 0; -} - -void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object) -{ - BLI_uniquename(&tracking->objects, object, "Object", '.', - offsetof(MovieTrackingObject, name), sizeof(object->name)); -} - -MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name) -{ - MovieTrackingObject *object = tracking->objects.first; - - while (object) { - if (!strcmp(object->name, name)) - return object; - - object = object->next; - } - - return NULL; -} - -/*********************** dopesheet functions *************************/ +/*********************** Dopesheet functions *************************/ static int channels_alpha_sort(void *a, void *b) { @@ -3586,11 +3670,11 @@ void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking) void BKE_tracking_dopesheet_update(MovieTracking *tracking) { - MovieTrackingObject *object = BKE_tracking_active_object(tracking); + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingTrack *track; MovieTrackingReconstruction *reconstruction; - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); short sort_method = dopesheet->sort_method; short inverse = dopesheet->flag & TRACKING_DOPE_SORT_INVERSE; @@ -3602,7 +3686,7 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking) tracking_dopesheet_free(dopesheet); - reconstruction = BKE_tracking_object_reconstruction(tracking, object); + reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); for (track = tracksbase->first; track; track = track->next) { MovieTrackingDopesheetChannel *channel; |