Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/tracking.c')
-rw-r--r--source/blender/blenkernel/intern/tracking.c3038
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;