diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-12-30 15:03:59 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-01-01 20:32:48 +0400 |
commit | 2785e8e73d3473cf481ba65a6b50a50c194e63d8 (patch) | |
tree | 179263a95aa25ccf8ecd383786dd535419aeabe4 /source/blender/blenkernel/intern/tracking_util.c | |
parent | 5933b2455c409963580ea616047f2f2ee332ff71 (diff) |
Split tracking.c into several files
File tracking.c became rather huge and annoying to
maintain and it really contains several independent
areas of motrack pipeline.
Now we've got:
* tracking.c: general-purpose functions which are used
by blender, clip editor, RNA and so.
* tracking_detect.c: feature detection functions
(blender-side, logic is still in libmv).
* tracking_plane_tracker.c: blender-side 2D tracking logic.
* tracking_plane_tracker.c: plane track tracker.
* tracking_solver.c: functions for camera solving.
* tracking_stabilize.c: 2D stabilization functions.
* tracking_util.c: utility functions for all those files
and which shouldn't be public.
Diffstat (limited to 'source/blender/blenkernel/intern/tracking_util.c')
-rw-r--r-- | source/blender/blenkernel/intern/tracking_util.c | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c new file mode 100644 index 00000000000..b6ae1c0f5c3 --- /dev/null +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -0,0 +1,379 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * Keir Mierle + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/tracking_private.c + * \ingroup bke + * + * This file contains implementation of function which are used + * by multiple tracking files but which should not be public. + */ + +#include <stddef.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_movieclip_types.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_listbase.h" +#include "BLI_ghash.h" +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "BLF_translation.h" + +#include "BKE_tracking.h" + +#include "tracking_private.h" + +/*********************** Tracks map *************************/ + +TracksMap *tracks_map_new(const char *object_name, bool is_camera, int num_tracks, int customdata_size) +{ + TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap"); + + BLI_strncpy(map->object_name, object_name, sizeof(map->object_name)); + map->is_camera = is_camera; + + map->num_tracks = num_tracks; + map->customdata_size = customdata_size; + + map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks"); + + if (customdata_size) + map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata"); + + map->hash = BLI_ghash_ptr_new("TracksMap hash"); + + return map; +} + +int tracks_map_get_size(TracksMap *map) +{ + return map->num_tracks; +} + +void tracks_map_get_indexed_element(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata) +{ + *track = &map->tracks[index]; + + if (map->customdata) + *customdata = &map->customdata[index * map->customdata_size]; +} + +void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata) +{ + MovieTrackingTrack new_track = *track; + + new_track.markers = MEM_dupallocN(new_track.markers); + + map->tracks[map->ptr] = new_track; + + if (customdata) + memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size); + + BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track); + + map->ptr++; +} + +void tracks_map_merge(TracksMap *map, MovieTracking *tracking) +{ + MovieTrackingTrack *track; + ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL}; + ListBase *old_tracks; + int a; + + if (map->is_camera) { + old_tracks = &tracking->tracks; + } + else { + MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name); + + if (!object) { + /* object was deleted by user, create new one */ + object = BKE_tracking_object_add(tracking, map->object_name); + } + + old_tracks = &object->tracks; + } + + /* duplicate currently operating tracks to temporary list. + * this is needed to keep names in unique state and it's faster to change names + * of currently operating tracks (if needed) + */ + for (a = 0; a < map->num_tracks; a++) { + MovieTrackingTrack *old_track; + bool mapped_to_old = false; + + track = &map->tracks[a]; + + /* find original of operating track in list of previously displayed tracks */ + old_track = BLI_ghash_lookup(map->hash, track); + if (old_track) { + if (BLI_findindex(old_tracks, old_track) != -1) { + BLI_remlink(old_tracks, old_track); + + /* Copy flags like selection back to the track map. */ + track->flag = old_track->flag; + track->pat_flag = old_track->pat_flag; + track->search_flag = old_track->search_flag; + + /* Copy all the rest settings back from the map to the actual tracks. */ + MEM_freeN(old_track->markers); + *old_track = *track; + old_track->markers = MEM_dupallocN(old_track->markers); + + BLI_addtail(&tracks, old_track); + + mapped_to_old = true; + } + } + + if (mapped_to_old == false) { + MovieTrackingTrack *new_track = BKE_tracking_track_duplicate(track); + + /* Update old-new track mapping */ + BLI_ghash_remove(map->hash, track, NULL, NULL); + BLI_ghash_insert(map->hash, track, new_track); + + BLI_addtail(&tracks, new_track); + } + } + + /* move all tracks, which aren't operating */ + track = old_tracks->first; + while (track) { + MovieTrackingTrack *next = track->next; + BLI_addtail(&new_tracks, track); + track = next; + } + + /* now move all tracks which are currently operating and keep their names unique */ + track = tracks.first; + while (track) { + MovieTrackingTrack *next = track->next; + + BLI_remlink(&tracks, track); + + track->next = track->prev = NULL; + BLI_addtail(&new_tracks, track); + + BLI_uniquename(&new_tracks, track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.', + offsetof(MovieTrackingTrack, name), sizeof(track->name)); + + track = next; + } + + *old_tracks = new_tracks; +} + +void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata)) +{ + int i = 0; + + BLI_ghash_free(map->hash, NULL, NULL); + + for (i = 0; i < map->num_tracks; i++) { + if (map->customdata && customdata_free) + customdata_free(&map->customdata[i * map->customdata_size]); + + BKE_tracking_track_free(&map->tracks[i]); + } + + if (map->customdata) + MEM_freeN(map->customdata); + + MEM_freeN(map->tracks); + MEM_freeN(map); +} + +/*********************** Space transformation functions *************************/ + +/* Three coordinate frames: Frame, Search, and Marker + * Two units: Pixels, Unified + * Notation: {coordinate frame}_{unit}; for example, "search_pixel" are search + * window relative coordinates in pixels, and "frame_unified" are unified 0..1 + * coordinates relative to the entire frame. + */ +static void unified_to_pixel(int frame_width, int frame_height, + const float unified_coords[2], float pixel_coords[2]) +{ + pixel_coords[0] = unified_coords[0] * frame_width; + pixel_coords[1] = unified_coords[1] * frame_height; +} + +static void marker_to_frame_unified(const MovieTrackingMarker *marker, const float marker_unified_coords[2], + float frame_unified_coords[2]) +{ + frame_unified_coords[0] = marker_unified_coords[0] + marker->pos[0]; + frame_unified_coords[1] = marker_unified_coords[1] + marker->pos[1]; +} + +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]) +{ + marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); + unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords); +} + +void tracking_get_search_origin_frame_pixel(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + float frame_pixel[2]) +{ + /* Get the lower left coordinate of the search window and snap to pixel coordinates */ + marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker->search_min, frame_pixel); + frame_pixel[0] = (int)frame_pixel[0]; + frame_pixel[1] = (int)frame_pixel[1]; +} + +static void pixel_to_unified(int frame_width, int frame_height, const float pixel_coords[2], float unified_coords[2]) +{ + unified_coords[0] = pixel_coords[0] / frame_width; + unified_coords[1] = pixel_coords[1] / frame_height; +} + +static void marker_unified_to_search_pixel(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + const float marker_unified[2], float search_pixel[2]) +{ + float frame_pixel[2]; + float search_origin_frame_pixel[2]; + + marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel); + tracking_get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); + sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); +} + +static void search_pixel_to_marker_unified(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + const float search_pixel[2], float marker_unified[2]) +{ + float frame_unified[2]; + float search_origin_frame_pixel[2]; + + tracking_get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); + add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); + pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified); + + /* marker pos is in frame unified */ + sub_v2_v2v2(marker_unified, frame_unified, marker->pos); +} + +/* Each marker has 5 coordinates associated with it that get warped with + * tracking: the four corners ("pattern_corners"), and the center ("pos"). + * This function puts those 5 points into the appropriate frame for tracking + * (the "search" coordinate frame). + */ +void tracking_get_marker_coords_for_tracking(int frame_width, int frame_height, + const MovieTrackingMarker *marker, + double search_pixel_x[5], double search_pixel_y[5]) +{ + int i; + float unified_coords[2]; + float pixel_coords[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; i++) { + marker_unified_to_search_pixel(frame_width, frame_height, marker, marker->pattern_corners[i], pixel_coords); + search_pixel_x[i] = pixel_coords[0] - 0.5f; + search_pixel_y[i] = pixel_coords[1] - 0.5f; + } + + /* Convert the center position (aka "pos"); this is the origin */ + unified_coords[0] = 0.0f; + unified_coords[1] = 0.0f; + marker_unified_to_search_pixel(frame_width, frame_height, marker, unified_coords, pixel_coords); + + search_pixel_x[4] = pixel_coords[0] - 0.5f; + search_pixel_y[4] = pixel_coords[1] - 0.5f; +} + +/* Inverse of above. */ +void tracking_set_marker_coords_from_tracking(int frame_width, int frame_height, MovieTrackingMarker *marker, + const double search_pixel_x[5], const double search_pixel_y[5]) +{ + int i; + float marker_unified[2]; + float search_pixel[2]; + + /* Convert the corners into search space coordinates. */ + for (i = 0; i < 4; i++) { + search_pixel[0] = search_pixel_x[i] + 0.5; + search_pixel[1] = search_pixel_y[i] + 0.5; + search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker->pattern_corners[i]); + } + + /* Convert the center position (aka "pos"); this is the origin */ + search_pixel[0] = search_pixel_x[4] + 0.5; + search_pixel[1] = search_pixel_y[4] + 0.5; + search_pixel_to_marker_unified(frame_width, frame_height, marker, search_pixel, marker_unified); + + /* If the tracker tracked nothing, then "marker_unified" would be zero. + * Otherwise, the entire patch shifted, and that delta should be applied to + * all the coordinates. + */ + for (i = 0; i < 4; i++) { + marker->pattern_corners[i][0] -= marker_unified[0]; + marker->pattern_corners[i][1] -= marker_unified[1]; + } + + marker->pos[0] += marker_unified[0]; + marker->pos[1] += marker_unified[1]; +} + +/*********************** General purpose utility functions *************************/ + +/* Place a disabled marker before or after specified ref_marker. + * + * If before is truth, disabled marker is placed before reference + * one, and it's placed after it otherwise. + * + * If there's already a marker at the frame where disabled one + * is expected to be placed, nothing will happen if overwrite + * is false. + */ +void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker, + bool before, bool overwrite) +{ + MovieTrackingMarker marker_new; + + 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); +} |