From efb9b6c1c381057d7c03eef4355c85a887d14f05 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 14 Apr 2012 12:02:39 +0000 Subject: [PATCH 1/3] libmv: bundle new upstream version of libmv from own branch Added modal solver module which is needed for tripod solving. For details of this solver read changelog of libmv. --- extern/libmv/CMakeLists.txt | 2 + extern/libmv/ChangeLog | 19 ++- extern/libmv/files.txt | 2 + .../libmv/simple_pipeline/modal_solver.cc | 130 ++++++++++++++++++ .../libmv/simple_pipeline/modal_solver.h | 48 +++++++ extern/libmv/third_party/ssba/README.libmv | 0 6 files changed, 195 insertions(+), 6 deletions(-) create mode 100644 extern/libmv/libmv/simple_pipeline/modal_solver.cc create mode 100644 extern/libmv/libmv/simple_pipeline/modal_solver.h mode change 100755 => 100644 extern/libmv/third_party/ssba/README.libmv diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 02723b64b62..6be813883ec 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -69,6 +69,7 @@ set(SRC libmv/simple_pipeline/detect.cc libmv/simple_pipeline/initialize_reconstruction.cc libmv/simple_pipeline/intersect.cc + libmv/simple_pipeline/modal_solver.cc libmv/simple_pipeline/pipeline.cc libmv/simple_pipeline/reconstruction.cc libmv/simple_pipeline/resect.cc @@ -126,6 +127,7 @@ set(SRC libmv/simple_pipeline/detect.h libmv/simple_pipeline/initialize_reconstruction.h libmv/simple_pipeline/intersect.h + libmv/simple_pipeline/modal_solver.h libmv/simple_pipeline/pipeline.h libmv/simple_pipeline/reconstruction.h libmv/simple_pipeline/resect.h diff --git a/extern/libmv/ChangeLog b/extern/libmv/ChangeLog index 33068bddf90..7248e4c9cd9 100644 --- a/extern/libmv/ChangeLog +++ b/extern/libmv/ChangeLog @@ -1,3 +1,16 @@ +commit a44312a7beb2963b8e3bf8015c516d2eff40cc3d +Author: Sergey Sharybin +Date: Thu Apr 12 13:56:02 2012 +0600 + + Added solver for modal camera motion, currently supports only tripod solving + + This solver is intended to deal with such camera motions as tripod and panning, + where it's impossible to reconstruct exact position of markers in 3d view. + + It projects markers onto sphere and uses rigid registration of rotation to + find rotation angles which makes bundles from previous and current frame be + as closest as it's possible. + commit fa3842e472e3b9c789e47bf6d8f592aa40a84f16 Author: Sergey Sharybin Date: Thu Apr 12 12:32:48 2012 +0600 @@ -520,9 +533,3 @@ Author: Matthias Fauconneau Date: Fri Aug 19 16:04:37 2011 +0200 MSVC compatibility: heap allocate pattern, explicit float cast. - -commit 702658d2f8616964a6eeb3743fd85e97ac7ff09d -Author: Matthias Fauconneau -Date: Fri Aug 19 14:59:24 2011 +0200 - - Expose regularization parameters (areaPenalty and conditionPenalty) in API. diff --git a/extern/libmv/files.txt b/extern/libmv/files.txt index 1e564d3a2f2..85d09ce05b8 100644 --- a/extern/libmv/files.txt +++ b/extern/libmv/files.txt @@ -42,6 +42,8 @@ libmv/simple_pipeline/initialize_reconstruction.cc libmv/simple_pipeline/initialize_reconstruction.h libmv/simple_pipeline/intersect.cc libmv/simple_pipeline/intersect.h +libmv/simple_pipeline/modal_solver.cc +libmv/simple_pipeline/modal_solver.h libmv/simple_pipeline/pipeline.cc libmv/simple_pipeline/pipeline.h libmv/simple_pipeline/reconstruction.cc diff --git a/extern/libmv/libmv/simple_pipeline/modal_solver.cc b/extern/libmv/libmv/simple_pipeline/modal_solver.cc new file mode 100644 index 00000000000..ede0071dc64 --- /dev/null +++ b/extern/libmv/libmv/simple_pipeline/modal_solver.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2012 libmv authors. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include + +#include "libmv/logging/logging.h" +#include "libmv/simple_pipeline/modal_solver.h" +#include "libmv/simple_pipeline/rigid_registration.h" + +#ifdef _MSC_VER +# define snprintf _snprintf +#endif + +namespace libmv { + +static void ProjectMarkerOnSphere(Marker &marker, Vec3 &X) { + X(0) = marker.x; + X(1) = marker.y; + X(2) = 1.0; + + X *= 5.0 / X.norm(); +} + +static void ModalSolverLogProress(ProgressUpdateCallback *update_callback, + double progress) +{ + if (update_callback) { + char message[256]; + + snprintf(message, sizeof(message), "Solving progress %d%%", (int)(progress * 100)); + + update_callback->invoke(progress, message); + } +} + +void ModalSolver(Tracks &tracks, + EuclideanReconstruction *reconstruction, + ProgressUpdateCallback *update_callback) { + int max_image = tracks.MaxImage(); + int max_track = tracks.MaxTrack(); + + LG << "Max image: " << max_image; + LG << "Max track: " << max_track; + + Mat3 R = Mat3::Identity(); + + for (int image = 0; image <= max_image; ++image) { + vector all_markers = tracks.MarkersInImage(image); + + ModalSolverLogProress(update_callback, (float) image / max_image); + + // Skip empty frames without doing anything + if (all_markers.size() == 0) { + LG << "Skipping frame: " << image; + continue; + } + + vector points, reference_points; + + // Cnstruct pairs of markers from current and previous image, + // to reproject them and find rigid transformation between + // previous and current image + for (int track = 0; track <= max_track; ++track) { + EuclideanPoint *point = reconstruction->PointForTrack(track); + + if (point) { + Marker marker = tracks.MarkerInImageForTrack(image, track); + + if (marker.image == image) { + Vec3 X; + + LG << "Use track " << track << " for rigid registration between image " << + image - 1 << " and " << image; + + ProjectMarkerOnSphere(marker, X); + + points.push_back(R * point->X); + reference_points.push_back(X); + } + } + } + + if (points.size()) { + Mat3 dR = Mat3::Identity(); + + // Find rigid delta transformation from previous image to current image + RigidRegistration(reference_points, points, dR); + + R *= dR; + } + + reconstruction->InsertCamera(image, R, Vec3::Zero()); + + // Review if there's new tracks for which position might be reconstructed + for (int track = 0; track <= max_track; ++track) { + if (!reconstruction->PointForTrack(track)) { + Marker marker = tracks.MarkerInImageForTrack(image, track); + + if (marker.image == image) { + // New track appeared on this image, project it's position onto sphere + + LG << "Projecting track " << track << " at image " << image; + + Vec3 X; + ProjectMarkerOnSphere(marker, X); + reconstruction->InsertPoint(track, R.inverse() * X); + } + } + } + } +} + +} // namespace libmv diff --git a/extern/libmv/libmv/simple_pipeline/modal_solver.h b/extern/libmv/libmv/simple_pipeline/modal_solver.h new file mode 100644 index 00000000000..560b37c2987 --- /dev/null +++ b/extern/libmv/libmv/simple_pipeline/modal_solver.h @@ -0,0 +1,48 @@ +// Copyright (c) 2012 libmv authors. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#ifndef LIBMV_SIMPLE_PIPELINE_MODAL_SOLVER_H_ +#define LIBMV_SIMPLE_PIPELINE_MODAL_SOLVER_H_ + +#include "libmv/simple_pipeline/tracks.h" +#include "libmv/simple_pipeline/reconstruction.h" +#include "libmv/simple_pipeline/callbacks.h" + +namespace libmv { + +/*! + This solver solves such camera motion as tripod rotation, reconstructing + only camera motion itself. Bundles are not reconstructing properly, they're + just getting projected onto sphere. + + Markers from tracks object would be used for recosntruction, and algorithm + assumes thir's positions are undistorted already and they're in nnormalized + space. + + Reconstructed cameras and projected bundles would be added to reconstruction + object. +*/ +void ModalSolver(Tracks &tracks, + EuclideanReconstruction *reconstruction, + ProgressUpdateCallback *update_callback = NULL); + +} // namespace libmv + +#endif // LIBMV_SIMPLE_PIPELINE_MODAL_SOLVER_H_ diff --git a/extern/libmv/third_party/ssba/README.libmv b/extern/libmv/third_party/ssba/README.libmv old mode 100755 new mode 100644 From f9d9b4635da01c5a27ef9adbd3d3171f5ceeb47d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 14 Apr 2012 12:02:47 +0000 Subject: [PATCH 2/3] Camera tracking: support of tripod motion solving Expose option into interface to use modal solver which currently supports only tripod motion. This solver requires two tracks at least to reconstruct motion. Using more tracks aren't improving solution in general, just adds instability into solution and slows down things a lot. Refirement of camera intrinsics is supported by this solver. To use this solver just activate "Tripod Motion" checkbox in solver panel. --- extern/libmv/libmv-capi.cpp | 84 +++++++++++++++---- extern/libmv/libmv-capi.h | 3 + release/scripts/startup/bl_ui/space_clip.py | 4 + source/blender/blenkernel/intern/tracking.c | 34 ++++++-- source/blender/makesdna/DNA_tracking_types.h | 11 ++- source/blender/makesrna/intern/rna_tracking.c | 6 ++ 6 files changed, 113 insertions(+), 29 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index e4708e5907d..3f697d487b6 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -54,6 +54,7 @@ #include "libmv/simple_pipeline/pipeline.h" #include "libmv/simple_pipeline/camera_intrinsics.h" #include "libmv/simple_pipeline/rigid_registration.h" +#include "libmv/simple_pipeline/modal_solver.h" #include #include @@ -384,6 +385,31 @@ int libmv_refineParametersAreValid(int parameters) { LIBMV_REFINE_RADIAL_DISTORTION_K1)); } +void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics *intrinsics, + libmv::EuclideanReconstruction *reconstruction, int refine_intrinsics, + reconstruct_progress_update_cb progress_update_callback, void *callback_customdata) +{ + /* only a few combinations are supported but trust the caller */ + int libmv_refine_flags = 0; + + if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) { + libmv_refine_flags |= libmv::BUNDLE_FOCAL_LENGTH; + } + if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) { + libmv_refine_flags |= libmv::BUNDLE_PRINCIPAL_POINT; + } + if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) { + libmv_refine_flags |= libmv::BUNDLE_RADIAL_K1; + } + if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) { + libmv_refine_flags |= libmv::BUNDLE_RADIAL_K2; + } + + progress_update_callback(callback_customdata, 1.0, "Refining solution"); + + libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags, + reconstruction, intrinsics); +} libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2, int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, @@ -423,24 +449,48 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction, &update_callback); if (refine_intrinsics) { - /* only a few combinations are supported but trust the caller */ - int libmv_refine_flags = 0; - if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) { - libmv_refine_flags |= libmv::BUNDLE_FOCAL_LENGTH; - } - if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) { - libmv_refine_flags |= libmv::BUNDLE_PRINCIPAL_POINT; - } - if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) { - libmv_refine_flags |= libmv::BUNDLE_RADIAL_K1; - } - if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) { - libmv_refine_flags |= libmv::BUNDLE_RADIAL_K2; - } + libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, intrinsics, reconstruction, + refine_intrinsics, progress_update_callback, callback_customdata); + } - progress_update_callback(callback_customdata, 1.0, "Refining solution"); - libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags, - reconstruction, intrinsics); + progress_update_callback(callback_customdata, 1.0, "Finishing solution"); + libmv_reconstruction->tracks = *(libmv::Tracks *)tracks; + libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics); + + return (libmv_Reconstruction *)libmv_reconstruction; +} + +struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, int refine_intrinsics, double focal_length, + double principal_x, double principal_y, double k1, double k2, double k3, + reconstruct_progress_update_cb progress_update_callback, void *callback_customdata) +{ + /* Invert the camera intrinsics. */ + libmv::vector markers = ((libmv::Tracks*)tracks)->AllMarkers(); + libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction(); + libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction; + libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics; + + ReconstructUpdateCallback update_callback = + ReconstructUpdateCallback(progress_update_callback, callback_customdata); + + intrinsics->SetFocalLength(focal_length, focal_length); + intrinsics->SetPrincipalPoint(principal_x, principal_y); + intrinsics->SetRadialDistortion(k1, k2, k3); + + for (int i = 0; i < markers.size(); ++i) { + intrinsics->InvertIntrinsics(markers[i].x, + markers[i].y, + &(markers[i].x), + &(markers[i].y)); + } + + libmv::Tracks normalized_tracks(markers); + + libmv::ModalSolver(normalized_tracks, reconstruction, &update_callback); + + if (refine_intrinsics) { + libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, intrinsics, reconstruction, + refine_intrinsics, progress_update_callback, callback_customdata); } progress_update_callback(callback_customdata, 1.0, "Finishing solution"); diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index 01019832374..f72a72d494b 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -68,6 +68,9 @@ int libmv_refineParametersAreValid(int parameters); struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2, int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); +struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, int refine_intrinsics, double focal_length, + double principal_x, double principal_y, double k1, double k2, double k3, + reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]); double libmv_reporojectionErrorForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track); double libmv_reporojectionErrorForImage(struct libmv_Reconstruction *libmv_reconstruction, int image); diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index c7ab9de72ac..51a1751bb00 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -227,7 +227,11 @@ class CLIP_PT_tools_solve(Panel): else "Object Motion") col.operator("clip.clear_solution") + col = layout.column() + col.prop(settings, "use_tripod_solver") + col = layout.column(align=True) + col.active = not settings.use_tripod_solver col.prop(settings, "keyframe_a") col.prop(settings, "keyframe_b") diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 7654c361d14..9e3bc2648a5 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1523,6 +1523,7 @@ typedef struct MovieReconstructContext { #endif char object_name[MAX_NAME]; int is_camera; + short motion_flag; float focal_length; float principal_point[2]; @@ -1752,7 +1753,11 @@ int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *o #if WITH_LIBMV ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - if (count_tracks_on_both_keyframes(tracking, tracksbase)<8) { + 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) { BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction", error_size); return FALSE; @@ -1781,7 +1786,8 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking * MovieTrackingTrack *track; BLI_strncpy(context->object_name, object->name, sizeof(context->object_name)); - context->is_camera = object->flag&TRACKING_OBJECT_CAMERA; + context->is_camera = object->flag & TRACKING_OBJECT_CAMERA; + context->motion_flag = tracking->settings.motion_flag; context->tracks_map = tracks_map_new(context->object_name, context->is_camera, num_tracks, 0); @@ -1894,13 +1900,23 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * progressdata.stats_message = stats_message; progressdata.message_size = message_size; - context->reconstruction = libmv_solveReconstruction(context->tracks, - context->keyframe1, context->keyframe2, - context->refine_flags, - context->focal_length, - context->principal_point[0], context->principal_point[1], - context->k1, context->k2, context->k3, - solve_reconstruction_update_cb, &progressdata); + if (context->motion_flag & TRACKING_MOTION_MODAL) { + context->reconstruction = libmv_solveModal(context->tracks, + context->refine_flags, + context->focal_length, + context->principal_point[0], context->principal_point[1], + context->k1, context->k2, context->k3, + solve_reconstruction_update_cb, &progressdata); + } + else { + context->reconstruction = libmv_solveReconstruction(context->tracks, + context->keyframe1, context->keyframe2, + context->refine_flags, + context->focal_length, + context->principal_point[0], context->principal_point[1], + context->k1, context->k2, context->k3, + solve_reconstruction_update_cb, &progressdata); + } error = libmv_reprojectionError(context->reconstruction); diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 9c0f63028c1..2f099ed59f5 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -123,7 +123,7 @@ typedef struct MovieTrackingSettings { short default_pattern_match; /* re-adjust every N frames */ short default_flag; /* default flags like color channels used by default */ - short pod; + short motion_flag; /* flags describes motion type */ /* ** common tracker settings ** */ short speed; /* speed of tracking */ @@ -131,8 +131,8 @@ typedef struct MovieTrackingSettings { /* ** reconstruction settings ** */ int keyframe1, keyframe2; /* two keyframes for reconstrution initialization */ - /* ** which camera intrinsics to refine. uses on the REFINE_* flags */ - short refine_camera_intrinsics, pad23; + /* which camera intrinsics to refine. uses on the REFINE_* flags */ + short refine_camera_intrinsics, pad2; /* ** tool settings ** */ @@ -243,6 +243,11 @@ enum { /* MovieTrackingSettings->flag */ #define TRACKING_SETTINGS_SHOW_DEFAULT_EXPANDED (1<<0) +/* MovieTrackingSettings->motion_flag */ +#define TRACKING_MOTION_TRIPOD (1<<0) + +#define TRACKING_MOTION_MODAL (TRACKING_MOTION_TRIPOD) + /* MovieTrackingSettings->speed */ #define TRACKING_SPEED_FASTEST 0 #define TRACKING_SPEED_REALTIME 1 diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 56222c67a23..13948fde367 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -607,6 +607,12 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Expanded", "Show the expanded in the user interface"); RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); + /* solver settings */ + prop = RNA_def_property(srna, "use_tripod_solver", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "motion_flag", TRACKING_MOTION_TRIPOD); + RNA_def_property_ui_text(prop, "Tripod Motion", "Tracking footage is shooted by tripod camera and should use special sovler for this"); + /* limit frames */ prop = RNA_def_property(srna, "default_frames_limit", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); From 339efd5e0158706f3e0cd6251ee65c7446fc96ed Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 14 Apr 2012 12:02:54 +0000 Subject: [PATCH 3/3] Camera tracking: if there's no image for current frame display default grid and allow to interact with tracks for operators which doesn't require image. --- source/blender/blenkernel/intern/movieclip.c | 4 +- source/blender/editors/include/ED_screen.h | 1 + source/blender/editors/screen/area.c | 60 ++++++++++++++++++ source/blender/editors/space_clip/clip_draw.c | 5 ++ .../blender/editors/space_clip/tracking_ops.c | 33 +++++++--- .../blender/editors/space_image/image_draw.c | 61 +------------------ .../editors/transform/transform_conversions.c | 5 +- 7 files changed, 99 insertions(+), 70 deletions(-) diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 9a640bcb8eb..9f8585675e3 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -925,8 +925,8 @@ void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, in real_ibuf_size(clip, user, ibuf, width, height); } else { - *width = 0; - *height = 0; + *width = clip->lastsize[0]; + *height = clip->lastsize[1]; } if (ibuf) diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index f0fffb34b73..f62befdaa31 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -66,6 +66,7 @@ void ED_region_header(const struct bContext *C, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void region_scissor_winrct(struct ARegion *ar, struct rcti *winrct); void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float alpha); +void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); /* spaces */ void ED_spacetypes_init(void); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index bed17048ea1..d3da167cf72 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1813,3 +1813,63 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) BLF_position(fontid, 12, rect.ymin + 5, 0.0f); BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX); } + +void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) +{ + float gridsize, gridstep = 1.0f / 32.0f; + float fac, blendfac; + int x1, y1, x2, y2; + + /* the image is located inside (0,0),(1, 1) as set by view2d */ + UI_ThemeColorShade(TH_BACK, 20); + + UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x1, &y1); + UI_view2d_to_region_no_clip(&ar->v2d, 1.0f, 1.0f, &x2, &y2); + glRectf(x1, y1, x2, y2); + + /* gridsize adapted to zoom level */ + gridsize = 0.5f * (zoomx + zoomy); + if (gridsize <= 0.0f) + return; + + if (gridsize < 1.0f) { + while (gridsize < 1.0f) { + gridsize *= 4.0f; + gridstep *= 4.0f; + } + } + else { + while (gridsize >= 4.0f) { + gridsize /= 4.0f; + gridstep /= 4.0f; + } + } + + /* the fine resolution level */ + blendfac = 0.25f * gridsize - floorf(0.25f * gridsize); + CLAMP(blendfac, 0.0f, 1.0f); + UI_ThemeColorShade(TH_BACK, (int)(20.0f * (1.0f - blendfac))); + + fac = 0.0f; + glBegin(GL_LINES); + while (fac < 1.0f) { + glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac); + glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac); + glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1); + glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2); + fac += gridstep; + } + + /* the large resolution level */ + UI_ThemeColor(TH_BACK); + + fac = 0.0f; + while (fac < 1.0f) { + glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac); + glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac); + glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1); + glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2); + fac += 4.0f * gridstep; + } + glEnd(); +} diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a553566ca69..418b72dc944 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1400,7 +1400,12 @@ void clip_draw_main(SpaceClip *sc, ARegion *ar, Scene *scene) if (ibuf) { draw_movieclip_buffer(sc, ar, ibuf, width, height, zoomx, zoomy); IMB_freeImBuf(ibuf); + } + else { + ED_region_grid_draw(ar, zoomx, zoomy); + } + if (width && height) { draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy); draw_distortion(sc, ar, clip, width, height, zoomx, zoomy); } diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 79569b82476..336ff07a1ad 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -92,6 +92,25 @@ static int space_clip_frame_poll(bContext *C) return FALSE; } +static int space_clip_size_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + MovieClip *clip = ED_space_clip(sc); + + if (clip) { + int width, height; + + BKE_movieclip_get_size(clip, &sc->user, &width, &height); + + return width > 0 && height > 0; + } + } + + return FALSE; +} + /********************** add marker operator *********************/ static void add_marker(SpaceClip *sc, float x, float y) @@ -156,7 +175,7 @@ void CLIP_OT_add_marker(wmOperatorType *ot) /* api callbacks */ ot->invoke = add_marker_invoke; ot->exec = add_marker_exec; - ot->poll = space_clip_frame_poll; + ot->poll = space_clip_size_poll; /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; @@ -643,7 +662,7 @@ void CLIP_OT_slide_marker(wmOperatorType *ot) ot->idname = "CLIP_OT_slide_marker"; /* api callbacks */ - ot->poll = space_clip_frame_poll; + ot->poll = space_clip_size_poll; ot->invoke = slide_marker_invoke; ot->modal = slide_marker_modal; @@ -1200,7 +1219,7 @@ void CLIP_OT_select_grouped(wmOperatorType *ot) /* api callbacks */ ot->exec = select_groped_exec; - ot->poll = space_clip_frame_poll; + ot->poll = space_clip_size_poll; /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; @@ -2016,7 +2035,7 @@ static Object *get_orientation_object(bContext *C) static int set_orientation_poll(bContext *C) { - if (space_clip_frame_poll(C)) { + if (space_clip_size_poll(C)) { Scene *scene = CTX_data_scene(C); SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip(sc); @@ -2626,7 +2645,7 @@ void CLIP_OT_set_scale(wmOperatorType *ot) static int set_solution_scale_poll(bContext *C) { - if (space_clip_frame_poll(C)) { + if (space_clip_size_poll(C)) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip(sc); MovieTracking *tracking = &clip->tracking; @@ -2974,7 +2993,7 @@ void CLIP_OT_frame_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = frame_jump_exec; - ot->poll = space_clip_frame_poll; + ot->poll = ED_space_clip_poll; /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; @@ -3031,7 +3050,7 @@ void CLIP_OT_join_tracks(wmOperatorType *ot) /* api callbacks */ ot->exec = join_tracks_exec; - ot->poll = space_clip_frame_poll; + ot->poll = space_clip_size_poll; /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 29bd5f5117d..793e5712c8c 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -334,65 +334,6 @@ void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int /* image drawing */ -static void draw_image_grid(ARegion *ar, float zoomx, float zoomy) -{ - float gridsize, gridstep = 1.0f / 32.0f; - float fac, blendfac; - int x1, y1, x2, y2; - - /* the image is located inside (0,0),(1, 1) as set by view2d */ - UI_ThemeColorShade(TH_BACK, 20); - - UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x1, &y1); - UI_view2d_to_region_no_clip(&ar->v2d, 1.0f, 1.0f, &x2, &y2); - glRectf(x1, y1, x2, y2); - - /* gridsize adapted to zoom level */ - gridsize = 0.5f * (zoomx + zoomy); - if (gridsize <= 0.0f) return; - - if (gridsize < 1.0f) { - while (gridsize < 1.0f) { - gridsize *= 4.0f; - gridstep *= 4.0f; - } - } - else { - while (gridsize >= 4.0f) { - gridsize /= 4.0f; - gridstep /= 4.0f; - } - } - - /* the fine resolution level */ - blendfac = 0.25f * gridsize - floorf(0.25f * gridsize); - CLAMP(blendfac, 0.0f, 1.0f); - UI_ThemeColorShade(TH_BACK, (int)(20.0f * (1.0f - blendfac))); - - fac = 0.0f; - glBegin(GL_LINES); - while (fac < 1.0f) { - glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2); - fac += gridstep; - } - - /* the large resolution level */ - UI_ThemeColor(TH_BACK); - - fac = 0.0f; - while (fac < 1.0f) { - glVertex2f(x1, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x2, y1 * (1.0f - fac) + y2 * fac); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y1); - glVertex2f(x1 * (1.0f - fac) + x2 * fac, y2); - fac += 4.0f * gridstep; - } - glEnd(); -} - static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti) { @@ -781,7 +722,7 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene) /* draw the image or grid */ if (ibuf == NULL) - draw_image_grid(ar, zoomx, zoomy); + ED_region_grid_draw(ar, zoomx, zoomy); else if (sima->flag & SI_DRAW_TILE) draw_image_buffer_repeated(sima, ar, scene, ima, ibuf, zoomx, zoomy); else if (ima && (ima->tpageflag & IMA_TILES)) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index c273d6a5b4c..7b9e3adbc7b 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5753,10 +5753,13 @@ static void createTransTrackingData(bContext *C, TransInfo *t) ARegion *ar = CTX_wm_region(C); SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip(sc); + int width, height; t->total = 0; - if (!clip || !BKE_movieclip_has_frame(clip, &sc->user)) + BKE_movieclip_get_size(clip, &sc->user, &width, &height); + + if (!clip || width == 0 || height == 0) return; if (!ELEM(t->mode, TFM_RESIZE, TFM_TRANSLATION))