diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 8c453944e9d..6be8d838d37 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -31,6 +31,8 @@ #include "libmv-capi.h" #include "glog/logging.h" +#include "libmv/logging/logging.h" + #include "Math/v3d_optimization.h" #include "libmv/tracking/esm_region_tracker.h" @@ -356,7 +358,8 @@ int libmv_refineParametersAreValid(int parameters) { 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) + 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(); @@ -377,15 +380,17 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra libmv::Tracks normalized_tracks(markers); - // printf("frames to init from: %d, %d\n", keyframe1, keyframe2); + LG << "frames to init from: " << keyframe1 << " " << keyframe2; libmv::vector keyframe_markers = normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2); - // printf("number of markers for init: %d\n", keyframe_markers.size()); + LG << "number of markers for init: " << keyframe_markers.size(); + + progress_update_callback(callback_customdata, 0, "Initial reconstruction"); libmv::EuclideanReconstructTwoFrames(keyframe_markers, reconstruction); libmv::EuclideanBundle(normalized_tracks, reconstruction); - libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction); + libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction, progress_update_callback, callback_customdata); if (refine_intrinsics) { /* only a few combinations are supported but trust the caller */ @@ -402,9 +407,12 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) { libmv_refine_flags |= libmv::BUNDLE_RADIAL_K2; } + + progress_update_callback(callback_customdata, 0, "Refining solution"); libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags, reconstruction, intrinsics); } + progress_update_callback(callback_customdata, 0, "Finishing solution"); libmv_reconstruction->tracks = *(libmv::Tracks *)tracks; libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics); diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index 8252a11739b..536f8a5f14c 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -64,10 +64,14 @@ void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks); #define LIBMV_REFINE_PRINCIPAL_POINT (1<<1) #define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1<<2) #define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1<<4) + +typedef void (*reconstruct_progress_update_cb) (void *customdata, double progress, const char *message); + 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); + 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/extern/libmv/libmv/simple_pipeline/pipeline.cc b/extern/libmv/libmv/simple_pipeline/pipeline.cc index 9512a41c00f..93f41d237e8 100644 --- a/extern/libmv/libmv/simple_pipeline/pipeline.cc +++ b/extern/libmv/libmv/simple_pipeline/pipeline.cc @@ -21,6 +21,7 @@ #include #include "libmv/logging/logging.h" +#include "libmv/simple_pipeline/pipeline.h" #include "libmv/simple_pipeline/bundle.h" #include "libmv/simple_pipeline/intersect.h" #include "libmv/simple_pipeline/resect.h" @@ -120,11 +121,14 @@ struct ProjectivePipelineRoutines { template void InternalCompleteReconstruction( const Tracks &tracks, - typename PipelineRoutines::Reconstruction *reconstruction) { + typename PipelineRoutines::Reconstruction *reconstruction, + progress_update_callback update_callback, + void *update_customdata) { int max_track = tracks.MaxTrack(); int max_image = tracks.MaxImage(); int num_resects = -1; int num_intersects = -1; + int tot_resects = 0; LG << "Max track: " << max_track; LG << "Max image: " << max_image; LG << "Number of markers: " << tracks.NumMarkers(); @@ -180,6 +184,9 @@ void InternalCompleteReconstruction( if (reconstructed_markers.size() >= 5) { if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, false)) { num_resects++; + tot_resects++; + if(update_callback) + update_callback(update_customdata, (float)tot_resects/(max_image), "Completing solution"); LG << "Ran Resect() for image " << image; } else { LG << "Failed Resect() for image " << image; @@ -211,6 +218,8 @@ void InternalCompleteReconstruction( if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, true)) { num_resects++; LG << "Ran Resect() for image " << image; + if(update_callback) + update_callback(update_customdata, (float)tot_resects/(max_image), "Completing solution"); } else { LG << "Failed Resect() for image " << image; } @@ -289,15 +298,20 @@ double ProjectiveReprojectionError( } void EuclideanCompleteReconstruction(const Tracks &tracks, - EuclideanReconstruction *reconstruction) { + EuclideanReconstruction *reconstruction, + progress_update_callback update_callback, + void *update_customdata) { InternalCompleteReconstruction(tracks, - reconstruction); + reconstruction, + update_callback, + update_customdata); } void ProjectiveCompleteReconstruction(const Tracks &tracks, ProjectiveReconstruction *reconstruction) { InternalCompleteReconstruction(tracks, - reconstruction); + reconstruction, + NULL, NULL); } void InvertIntrinsicsForTracks(const Tracks &raw_tracks, diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.h b/extern/libmv/libmv/simple_pipeline/pipeline.h index b7dfcb7993a..dc1a79506f2 100644 --- a/extern/libmv/libmv/simple_pipeline/pipeline.h +++ b/extern/libmv/libmv/simple_pipeline/pipeline.h @@ -26,6 +26,8 @@ namespace libmv { +typedef void (*progress_update_callback) (void *customdata, double progress, const char *message); + /*! Estimate camera poses and scene 3D coordinates for all frames and tracks. @@ -46,7 +48,9 @@ namespace libmv { \sa EuclideanResect, EuclideanIntersect, EuclideanBundle */ void EuclideanCompleteReconstruction(const Tracks &tracks, - EuclideanReconstruction *reconstruction); + EuclideanReconstruction *reconstruction, + progress_update_callback update_callback, + void *update_customdata); /*! Estimate camera matrices and homogeneous 3D coordinates for all frames and diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index d844873ef89..4a3b5053345 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -97,7 +97,7 @@ struct MovieReconstructContext* BKE_tracking_reconstruction_context_new(struct M int keyframe1, int keyframe2, int width, int height); void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context); void BKE_tracking_solve_reconstruction(struct MovieReconstructContext *context, - short *stop, short *do_update, float *progress); + short *stop, short *do_update, float *progress, char *stats_message, int message_size); int BKE_tracking_finish_reconstruction(struct MovieReconstructContext *context, struct MovieTracking *tracking); struct MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(struct MovieTracking *tracking, int framenr); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 67edec3c21e..cb58abbfa24 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1328,6 +1328,8 @@ typedef struct ReconstructProgressData { short *stop; short *do_update; float *progress; + char *stats_message; + int message_size; } ReconstructProgressData; #if WITH_LIBMV @@ -1616,20 +1618,7 @@ void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context) MEM_freeN(context); } -#if 0 - -/* TODO: this two callbacks are supposed to be used to make solving more - interactive with the interface, so approximated progress would be - displayed and it's also can be nice to have option to break solving - (would fit other jobs design in blender) - - customdata is used to pass some context data to libmv which can be used - later for set progress came form libmv to job - - keir, it's not necessary that progress is linear and it's not necessary - that breaking happens immediately */ - -static void solve_reconstruction_update_cb(void *customdata, float progress) +static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message) { ReconstructProgressData *progressdata= customdata; @@ -1637,8 +1626,15 @@ static void solve_reconstruction_update_cb(void *customdata, float progress) *progressdata->progress= progress; *progressdata->do_update= 1; } + + if(progress) { + BLI_snprintf(progressdata->stats_message, progressdata->message_size, "%s | %d%%", message, (int)(progress*100)); + } else { + BLI_strncpy(progressdata->stats_message, message, progressdata->message_size); + } } +#if 0 static int solve_reconstruction_testbreak_cb(void *customdata) { ReconstructProgressData *progressdata= customdata; @@ -1650,7 +1646,8 @@ static int solve_reconstruction_testbreak_cb(void *customdata) } #endif -void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop, short *do_update, float *progress) +void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop, + short *do_update, float *progress, char *stats_message, int message_size) { #ifdef WITH_LIBMV float error; @@ -1660,13 +1657,16 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * progressdata.stop= stop; progressdata.do_update= do_update; progressdata.progress= progress; + 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); + context->k1, context->k2, context->k3, + solve_reconstruction_update_cb, &progressdata); error= libmv_reprojectionError(context->reconstruction); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a6aecac1c34..81732258458 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5966,6 +5966,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) clip->anim= NULL; clip->tracking_context= NULL; + clip->tracking.stats= NULL; clip->tracking.stabilization.ok= 0; clip->tracking.stabilization.scaleibuf= NULL; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 630038d4c6b..a53da4ce006 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -191,27 +191,38 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) { + MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; char str[256]= {0}; + int block= 0; - if(sc->flag&SC_LOCK_SELECTION) - strcpy(str, "Locked"); + if(tracking->stats) { + BLI_strncpy(str, tracking->stats->message, sizeof(str)); + block= 1; + } else { + if(sc->flag&SC_LOCK_SELECTION) + strcpy(str, "Locked"); + } if(str[0]) { uiStyle *style= UI_GetStyle(); - int fontsize, fontwidth; int fontid= style->widget.uifont_id; + int fontwidth; - BLF_size(fontid, 11.0f, U.dpi); - fontsize= BLF_height(fontid, str); - fontwidth= BLF_width(fontid, str); + BLF_size(fontid, 11.0f, 72); + + if(block) + fontwidth= ar->winx; + else + fontwidth= BLF_width(fontid, str); glEnable(GL_BLEND); glColor4f(0.0f, 0.0f, 0.0f, 0.6f); - glRecti(0, ar->winy-fontsize-9, fontwidth+12, ar->winy); + glRecti(0, ar->winy-17, fontwidth+12, ar->winy); glColor3f(1.0f, 1.0f, 1.0f); - BLF_position(fontid, 6.0f, ar->winy-fontsize-5.0f, 0.0f); + BLF_position(fontid, 6.0f, ar->winy-13.0f, 0.0f); BLF_draw(fontid, str, strlen(str)); glDisable(GL_BLEND); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index aa610fb4485..dc3a857c2c9 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1511,13 +1511,13 @@ void CLIP_OT_track_markers(wmOperatorType *ot) /********************** solve camera operator *********************/ typedef struct { - MovieClip *clip; Scene *scene; + MovieClip *clip; + MovieClipUser user; ReportList *reports; - MovieClipUser user; - + char stats_message[256]; struct MovieReconstructContext *context; } SolveCameraJob; @@ -1544,14 +1544,25 @@ static int solve_camera_initjob(bContext *C, SolveCameraJob *scj, wmOperator *op scj->context= BKE_tracking_reconstruction_context_new(tracking, settings->keyframe1, settings->keyframe2, width, height); + tracking->stats= MEM_callocN(sizeof(MovieTrackingStats), "solve camera stats"); + return 1; } +static void solve_camera_updatejob(void *scv) +{ + SolveCameraJob *scj= (SolveCameraJob *)scv; + MovieTracking *tracking= &scj->clip->tracking; + + BLI_strncpy(tracking->stats->message, scj->stats_message, sizeof(tracking->stats->message)); +} + static void solve_camera_startjob(void *scv, short *stop, short *do_update, float *progress) { SolveCameraJob *scj= (SolveCameraJob *)scv; - BKE_tracking_solve_reconstruction(scj->context, stop, do_update, progress); + BKE_tracking_solve_reconstruction(scj->context, stop, do_update, progress, + scj->stats_message, sizeof(scj->stats_message)); } static void solve_camera_freejob(void *scv) @@ -1597,6 +1608,9 @@ static void solve_camera_freejob(void *scv) WM_main_add_notifier(NC_OBJECT, camera); } + MEM_freeN(tracking->stats); + tracking->stats= NULL; + DAG_id_tag_update(&clip->id, 0); WM_main_add_notifier(NC_MOVIECLIP|NA_EVALUATED, clip); @@ -1637,6 +1651,7 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even ScrArea *sa= CTX_wm_area(C); SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; wmJob *steve; char error_msg[256]= "\0"; @@ -1650,6 +1665,8 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even return OPERATOR_CANCELLED; } + BLI_strncpy(tracking->stats->message, "Preparing solve", sizeof(tracking->stats->message)); + /* hide reconstruction statistics from previous solve */ clip->tracking.reconstruction.flag&= ~TRACKING_RECONSTRUCTED; WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); @@ -1658,7 +1675,7 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Solve Camera", WM_JOB_PROGRESS); WM_jobs_customdata(steve, scj, solve_camera_freejob); WM_jobs_timer(steve, 0.2, NC_MOVIECLIP|NA_EVALUATED, 0); - WM_jobs_callbacks(steve, solve_camera_startjob, NULL, NULL, NULL); + WM_jobs_callbacks(steve, solve_camera_startjob, NULL, solve_camera_updatejob, NULL); G.afbreek= 0; diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index cbac3721ac3..88173e6cac3 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -165,6 +165,11 @@ typedef struct MovieTrackingReconstruction { struct MovieReconstructedCamera *cameras; /* reconstructed cameras */ } MovieTrackingReconstruction; +typedef struct MovieTrackingStats { + float progress; + char message[256]; +} MovieTrackingStats; + typedef struct MovieTracking { MovieTrackingSettings settings; /* different tracking-related settings */ char pad2[4]; @@ -174,6 +179,8 @@ typedef struct MovieTracking { MovieTrackingReconstruction reconstruction; /* reconstruction data */ MovieTrackingStabilization stabilization; /* stabilization data */ MovieTrackingTrack *act_track; /* active track */ + + MovieTrackingStats *stats; /* statistics displaying in clip editor */ } MovieTracking; /* MovieTrackingCamera->units */