From 08bd300f0e73ea534ba2a2cc09eeff69cc4c23ee Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 11 Jul 2011 09:04:00 +0000 Subject: [PATCH] Camera tracking integration =========================== - Changed libmv api to use doubles instead of floats. No real benefit rather than keeping API uniform. - Optimized reconstructed camera search. It's optimized for playback, not random access. - Added option to show projection of bundles into footage. To see bundles "Show Bundles" from Display panel should be enabled. Used very rough limit of 3 px to consider projection is fine. Colors are still hard-coded. Not sure it could be useful to make them configurable. - Added option to mute footage. It could be useful to check if markers/bundles are moving smoothly. - Added selector for focal length units. --- extern/libmv/libmv-capi.cpp | 19 +++- extern/libmv/libmv-capi.h | 6 +- release/scripts/startup/bl_ui/space_clip.py | 8 +- source/blender/blenkernel/BKE_movieclip.h | 1 + source/blender/blenkernel/BKE_tracking.h | 2 + source/blender/blenkernel/intern/movieclip.c | 30 ++++++- source/blender/blenkernel/intern/tracking.c | 88 +++++++++++++++++-- source/blender/editors/space_clip/clip_draw.c | 74 +++++++++++++--- source/blender/makesdna/DNA_space_types.h | 2 + source/blender/makesdna/DNA_tracking_types.h | 11 ++- .../blender/makesrna/intern/rna_movieclip.c | 15 +--- source/blender/makesrna/intern/rna_space.c | 12 +++ source/blender/makesrna/intern/rna_tracking.c | 50 ++++++++++- 13 files changed, 282 insertions(+), 36 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index c0393ee99a2..e14285be55d 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -331,7 +331,7 @@ int libmv_reporojectionPointForTrack(libmv_Reconstruction *reconstruction, int t return 0; } -int libmv_reporojectionCameraForImage(libmv_Reconstruction *reconstruction, int image, float mat[4][4]) +int libmv_reporojectionCameraForImage(libmv_Reconstruction *reconstruction, int image, double mat[4][4]) { libmv::Camera *camera = ((libmv::Reconstruction *)reconstruction)->CameraForImage(image); @@ -368,3 +368,20 @@ void libmv_destroyReconstruction(libmv_Reconstruction *reconstruction) delete (libmv::Reconstruction *)reconstruction; } +/* ************ utils ************ */ + +void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, + double x, double y, double *x1, double *y1) +{ + libmv::CameraIntrinsics intrinsics; + + intrinsics.SetFocalLength(focal_length); + intrinsics.set_principal_point(principal_x, principal_y); + intrinsics.set_radial_distortion(k1, k2, k3); + + if(focal_length) { + /* do a lens undistortion if focal length is non-zero only */ + + intrinsics.ApplyIntrinsics(x, y, x1, y1); + } +} diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index 73bd705813d..927a68bc9dd 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -58,9 +58,13 @@ void libmv_tracksDestroy(struct libmv_Tracks *tracks); struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3); int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *reconstruction, int track, double pos[3]); -int libmv_reporojectionCameraForImage(struct libmv_Reconstruction *reconstruction, int image, float mat[4][4]); +int libmv_reporojectionCameraForImage(struct libmv_Reconstruction *reconstruction, int image, double mat[4][4]); void libmv_destroyReconstruction(struct libmv_Reconstruction *reconstruction); +/* utils */ +void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, + double x, double y, double *x1, double *y1); + #ifdef __cplusplus } #endif diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index a2a30130a7e..eb04ecae7ad 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -218,7 +218,11 @@ class CLIP_PT_tracking_camera(bpy.types.Panel): sc = context.space_data clip = sc.clip - layout.prop(clip.tracking.camera, "focal_length") + layout.prop(clip.tracking.camera, "sensor_width") + + row = layout.row() + row.prop(clip.tracking.camera, "focal_length") + row.prop(clip.tracking.camera, "units", text="") layout.label(text="Principal Point") layout.prop(clip.tracking.camera, "principal", text="") @@ -249,6 +253,8 @@ class CLIP_PT_display(bpy.types.Panel): row.prop(sc, "path_length") layout.prop(sc, "show_tiny_markers") + layout.prop(sc, "show_bundles") + layout.prop(sc, "use_mute_footage") class CLIP_PT_test(bpy.types.Panel): diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 975bd4fa075..e51c574b581 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -48,6 +48,7 @@ void BKE_movieclip_reload(struct MovieClip *clip); struct ImBuf *BKE_movieclip_acquire_ibuf(struct MovieClip *clip, struct MovieClipUser *user); void BKE_movieclip_acquire_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height); +void BKE_movieclip_approx_size(struct MovieClip *clip, int *width, int *height); int BKE_movieclip_has_frame(struct MovieClip *clip, struct MovieClipUser *user); void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index d6a74e9b211..1bd0111a513 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -75,6 +75,8 @@ struct MovieTrackingTrack *BKE_find_track_by_name(struct MovieTracking *tracking struct MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(struct MovieTracking *tracking, int framenr); void BKE_get_tracking_mat(struct Scene *scene, float mat[4][4]); +void BKE_tracking_projection_matrix(struct MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4]); +void BKE_tracking_apply_intrinsics(struct MovieTracking *tracking, float co[2], float width, float height, float nco[2]); #define TRACK_SELECTED(track) ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT) #define TRACK_AREA_SELECTED(track, area) ((area)==TRACK_AREA_POINT?(track)->flag&SELECT : ((area)==TRACK_AREA_PAT?(track)->pat_flag&SELECT:(track)->search_flag&SELECT)) diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index df897be100c..034d0f11f47 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -214,6 +214,9 @@ static MovieClip *movieclip_alloc(const char *name) clip= alloc_libblock(&G.main->movieclip, ID_MC, name); + clip->tracking.camera.sensor_width= 35.0f; + clip->tracking.camera.units= CAMERA_UNITS_MM; + clip->tracking.settings.frames_limit= 20; clip->tracking.settings.keyframe1= 1; clip->tracking.settings.keyframe2= 30; @@ -281,7 +284,6 @@ ImBuf *BKE_movieclip_acquire_ibuf(MovieClip *clip, MovieClipUser *user) ImBuf *ibuf= NULL; int framenr= user?user->framenr:clip->lastframe; - clip->lastframe= framenr; ibuf= get_imbuf_cache(clip, user); if(!ibuf) { @@ -294,6 +296,9 @@ ImBuf *BKE_movieclip_acquire_ibuf(MovieClip *clip, MovieClipUser *user) put_imbuf_cache(clip, user, ibuf); } + if(ibuf) + clip->lastframe= framenr; + return ibuf; } @@ -325,6 +330,29 @@ void BKE_movieclip_acquire_size(MovieClip *clip, MovieClipUser *user, int *width IMB_freeImBuf(ibuf); } +void BKE_movieclip_approx_size(MovieClip *clip, int *width, int *height) +{ + ImBuf *ibuf= BKE_movieclip_acquire_ibuf(clip, NULL); + + if(!ibuf) { + MovieClipUser user; + user.framenr= 0; + + ibuf= BKE_movieclip_acquire_ibuf(clip, &user); + } + + if(ibuf && ibuf->x && ibuf->y) { + *width= ibuf->x; + *height= ibuf->y; + } else { + *width= 0; + *height= 0; + } + + if(ibuf) + IMB_freeImBuf(ibuf); +} + /* get segments of cached frames. useful for debugging cache policies */ void BKE_movieclip_get_cache_segments(MovieClip *clip, int *totseg_r, int **points_r) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 6b96d493de4..08c600c5d3e 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -758,9 +758,16 @@ static void retrive_libmv_reconstruct(MovieClip *clip, struct libmv_Reconstructi reconstructed= MEM_callocN((efra-sfra+1)*sizeof(MovieReconstructedCamera), "temp reconstructed camera"); for(a= sfra; a<=efra; a++) { - float mat[4][4]; + double matd[4][4]; + + if(libmv_reporojectionCameraForImage(reconstruction, a, matd)) { + int i, j; + float mat[4][4]; + + for(i=0; i<4; i++) + for(j= 0; j<4; j++) + mat[i][j]= matd[i][j]; - if(libmv_reporojectionCameraForImage(reconstruction, a, mat)) { if(!origin_set) { copy_v3_v3(origin, mat[3]); origin_set= 1; @@ -838,11 +845,27 @@ MovieTrackingTrack *BKE_find_track_by_name(MovieTracking *tracking, const char * MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr) { - int a; + MovieTrackingCamera *camera= &tracking->camera; + int a= 0, d= 1; - for (a= 0; acamera.reconnr; a++ ) { - if(tracking->camera.reconstructed[a].framenr==framenr) - return &tracking->camera.reconstructed[a]; + if(!camera->reconnr) + return NULL; + + if(camera->last_camerareconnr) + a= camera->last_camera; + + if(camera->reconstructed[a].framenr>=framenr) + d= -1; + + while(a>=0 && areconnr) { + if(camera->reconstructed[a].framenr==framenr) { + camera->last_camera= a; + return &camera->reconstructed[a]; + + break; + } + + a+= d; } return NULL; @@ -862,3 +885,56 @@ void BKE_get_tracking_mat(Scene *scene, float mat[4][4]) copy_m4_m4(mat, obmat); } + +void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4]) +{ + MovieReconstructedCamera *camera; + float lens= tracking->camera.focal*32.0f/(float)winx; + float viewfac, pixsize, left, right, bottom, top, clipsta, clipend; + float winmat[4][4]; + + clipsta= 0.1f; + clipend= 1000.0f; + + if(winx >= winy) + viewfac= (lens*winx)/32.0f; + else + viewfac= (lens*winy)/32.0f; + + pixsize= clipsta/viewfac; + + left= -0.5f*(float)winx*pixsize; + bottom= -0.5f*(float)winy*pixsize; + right= 0.5f*(float)winx*pixsize; + top= 0.5f*(float)winy*pixsize; + + perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); + + camera= BKE_tracking_get_reconstructed_camera(tracking, framenr); + if(camera) { + float imat[4][4]; + + invert_m4_m4(imat, camera->mat); + mul_m4_m4m4(mat, imat, winmat); + } else copy_m4_m4(mat, winmat); +} + +void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float width, float height, float nco[2]) +{ + MovieTrackingCamera *camera= &tracking->camera; + +#ifdef WITH_LIBMV + double x= nco[0], y= nco[1]; + + /* normalize coords */ + x= (co[0]-camera->principal[0]) / camera->focal; + y= (co[1]-camera->principal[1]) / camera->focal; + + libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1], + camera->k1, camera->k2, camera->k3, x, y, &x, &y); + + /* result is in image coords already */ + nco[0]= x; + nco[1]= y; +#endif +} diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index daab601d45e..e004729f88b 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -141,7 +141,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc glRecti(x, 0, x+framelen, 8); } -static void draw_movieclip_buffer(ARegion *ar, ImBuf *ibuf, float zoomx, float zoomy) +static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf, float zoomx, float zoomy) { int x, y; @@ -151,11 +151,16 @@ static void draw_movieclip_buffer(ARegion *ar, ImBuf *ibuf, float zoomx, float z /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.f, 0.f, &x, &y); - if(ibuf->rect_float) - IMB_rect_from_float(ibuf); + if(sc->flag&SC_MUTE_FOOTAGE) { + glColor3f(0.0f, 0.0f, 0.0f); + glRectf(x, y, x+ibuf->x*sc->zoom, y+ibuf->y*sc->zoom); + } else { + if(ibuf->rect_float) + IMB_rect_from_float(ibuf); - if(ibuf->rect) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + if(ibuf->rect) + glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + } /* reset zoom */ glPixelZoom(1.f, 1.f); @@ -482,9 +487,10 @@ static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, float zoomx, float zoomy) { float x, y; + MovieTracking* tracking= &clip->tracking; MovieTrackingMarker *marker; MovieTrackingTrack *track; - int width, height, sel_type; + int width, height, sel_type, framenr= sc->user.framenr; void *sel; ED_space_clip_size(sc, &width, &height); @@ -509,7 +515,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, fl BKE_movieclip_last_selection(clip, &sel_type, &sel); if(sc->flag&SC_SHOW_MARKER_PATH) { - track= clip->tracking.tracks.first; + track= tracking->tracks.first; while(track) { if((track->flag&TRACK_HIDDEN)==0) draw_track_path(sc, clip, track); @@ -519,10 +525,10 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, fl } /* markers outline and non-selected areas */ - track= clip->tracking.tracks.first; + track= tracking->tracks.first; while(track) { if((track->flag&TRACK_HIDDEN)==0) { - marker= BKE_tracking_get_marker(track, sc->user.framenr); + marker= BKE_tracking_get_marker(track, framenr); draw_marker_outline(sc, track, marker); draw_marker_slide_zones(sc, track, marker, 1, 0, width, height); @@ -534,13 +540,13 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, fl /* selected areas only, so selection wouldn't be overlapped by non-selected areas */ - track= clip->tracking.tracks.first; + track= tracking->tracks.first; while(track) { if((track->flag&TRACK_HIDDEN)==0) { int act= sel_type==MCLIP_SEL_TRACK && sel==track; if(!act) { - marker= BKE_tracking_get_marker(track, sc->user.framenr); + marker= BKE_tracking_get_marker(track, framenr); draw_marker_areas(sc, track, marker, 0, 1); draw_marker_slide_zones(sc, track, marker, 0, 0, width, height); } @@ -552,12 +558,54 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, fl /* active marker would be displayed on top of everything else */ if(sel_type==MCLIP_SEL_TRACK) { if((((MovieTrackingTrack *)sel)->flag&TRACK_HIDDEN)==0) { - marker= BKE_tracking_get_marker(sel, sc->user.framenr); + marker= BKE_tracking_get_marker(sel, framenr); draw_marker_areas(sc, sel, marker, 1, 1); draw_marker_slide_zones(sc, sel, marker, 0, 1, width, height); } } + if(sc->flag&SC_SHOW_BUNDLES) { + float pos[4], vec[4], mat[4][4]; + + glEnable(GL_POINT_SMOOTH); + glPointSize(3.0f); + + BKE_tracking_projection_matrix(tracking, framenr, width, height, mat); + + track= tracking->tracks.first; + while(track) { + if(track->flag&TRACK_HAS_BUNDLE) { + marker= BKE_tracking_get_marker(track, framenr); + + copy_v4_v4(vec, track->bundle_pos); + vec[3]=1; + + mul_v4_m4v4(pos, mat, vec); + + pos[0]= (pos[0]/(pos[3]*2.0f)+0.5f)*width; + pos[1]= (pos[1]/(pos[3]*2.0f)+0.5f)*height; + + BKE_tracking_apply_intrinsics(tracking, pos, width, height, pos); + + vec[0]= marker->pos[0]*width; + vec[1]= marker->pos[1]*height; + sub_v2_v2(vec, pos); + + if(len_v2(vec)<3) glColor3f(0.0f, 1.0f, 0.0f); + else glColor3f(1.0f, 0.0f, 0.0f); + + glBegin(GL_POINTS); + glVertex3f(pos[0]/width, pos[1]/height, 0); + glEnd(); + } + + track= track->next; + } + + glPointSize(1.0f); + glDisable(GL_POINT_SMOOTH); + } + glPopMatrix(); } @@ -581,7 +629,7 @@ void draw_clip_main(SpaceClip *sc, ARegion *ar, Scene *scene) ibuf= ED_space_clip_acquire_buffer(sc); if(ibuf) { - draw_movieclip_buffer(ar, ibuf, zoomx, zoomy); + draw_movieclip_buffer(sc, ar, ibuf, zoomx, zoomy); IMB_freeImBuf(ibuf); draw_tracking(sc, ar, clip, zoomx, zoomy); diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index c272dbfde30..6e5e11be4b4 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -965,6 +965,8 @@ enum { #define SC_LOCK_SELECTION (1<<2) #define SC_SHOW_TINY_MARKER (1<<3) #define SC_SHOW_MARKER_PATH (1<<4) +#define SC_SHOW_BUNDLES (1<<5) +#define SC_MUTE_FOOTAGE (1<<6) /* space types, moved from DNA_screen_types.h */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 962f8d258ba..2ad11e360c8 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -54,10 +54,13 @@ typedef struct MovieReconstructedCamera { } MovieReconstructedCamera; typedef struct MovieTrackingCamera { + float sensor_width; /* width of CCD sensor */ float focal; /* focal length */ + short units; /* units of focal length user is working with */ + short pad; float principal[2]; /* principal point */ float k1, k2, k3; /* radial distortion */ - float pad; + int last_camera; /* most recently used camera */ int reconnr; /* number of reconstructed cameras */ struct MovieReconstructedCamera *reconstructed; /* reconstructed cameras */ } MovieTrackingCamera; @@ -105,6 +108,12 @@ typedef struct MovieTracking { ListBase tracks; } MovieTracking; +/* MovieTrackingCamera->units */ +enum { + CAMERA_UNITS_PX = 0, + CAMERA_UNITS_MM +}; + /* MovieTrackingMarker->flag */ #define MARKER_DISABLED 1 diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index e4e22922f0d..d27bcbfe1de 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -62,19 +62,12 @@ static void rna_MovieClip_reload_update(Main *bmain, Scene *scene, PointerRNA *p static void rna_MovieClip_size_get(PointerRNA *ptr, int *values) { MovieClip *clip= (MovieClip*)ptr->data; - ImBuf *ibuf; + int width, height; - ibuf= BKE_movieclip_acquire_ibuf(clip, NULL); - if (ibuf) { - values[0]= ibuf->x; - values[1]= ibuf->y; + BKE_movieclip_approx_size(clip, &width, &height); - IMB_freeImBuf(ibuf); - } - else { - values[0]= 0; - values[1]= 0; - } + values[0]= height; + values[1]= width; } static void rna_MovieClip_resolution_get(PointerRNA *ptr, float *values) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 9ade1bfa708..4a689f3716e 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2676,6 +2676,18 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Tiny Markers", "Show markers tiny"); RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_TINY_MARKER); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + + /* show bundles */ + prop= RNA_def_property(srna, "show_bundles", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Show Bundles", "Show projection of bundles into footage"); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_BUNDLES); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); + + /* mute footage */ + prop= RNA_def_property(srna, "use_mute_footage", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Mute Footage", "Mute footage and show black background instead"); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_MUTE_FOOTAGE); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_CLIP, NULL); } void RNA_def_space(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 2c9f747e46a..20495242002 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -116,6 +116,29 @@ static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_SceneRenderLayer, NULL); } +static float rna_trackingCamera_focal_get(PointerRNA *ptr) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; + MovieTrackingCamera *camera= &clip->tracking.camera; + float val= camera->focal; + + if(camera->units==CAMERA_UNITS_MM) { + int width, height; + + BKE_movieclip_approx_size(clip, &width, &height); + + if(width) + val= val*camera->sensor_width/(float)width; + } + + return val; +} + +static void rna_trackingCamera_focal_set(PointerRNA *ptr, float value) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; +} + #else static void rna_def_trackingSettings(BlenderRNA *brna) @@ -124,7 +147,7 @@ static void rna_def_trackingSettings(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem speed_items[] = { - {0, "FASTEST", 0, "Fastest", "track as fast as it's possible"}, + {0, "FASTEST", 0, "Fastest", "Track as fast as it's possible"}, {TRACKING_SPEED_REALTIME, "REALTIME", 0, "Realtime", "Track with realtime speed"}, {TRACKING_SPEED_HALF, "HALF", 0, "Half", "Track with half of realtime speed"}, {TRACKING_SPEED_HALF, "QUARTER", 0, "Quarter", "Track with quarter of realtime speed"}, @@ -170,33 +193,58 @@ static void rna_def_trackingCamera(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem camera_units_items[] = { + {CAMERA_UNITS_PX, "PIXELS", 0, "Pixels", "Use pixels for units of focal length"}, + {CAMERA_UNITS_MM, "MILLIMETERS", 0, "Millimeters", "Use millimeters for units of focal length"}, + {0, NULL, 0, NULL, NULL}}; + srna= RNA_def_struct(brna, "MovieTrackingCamera", NULL); RNA_def_struct_ui_text(srna, "Movie tracking camera data", "Match-moving camera data for tracking"); + /* Sensor Wdth */ + prop= RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "sensor_width"); + RNA_def_property_range(prop, 0.0f, 500.0f); + RNA_def_property_ui_text(prop, "Sensor Width", "Width of CCD sensor in millimeters"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); + /* Focal Length */ prop= RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "focal"); RNA_def_property_range(prop, 0.0f, 5000.0f); RNA_def_property_ui_text(prop, "Focal Length", "Camera's focal length in pixels"); + RNA_def_property_float_funcs(prop, "rna_trackingCamera_focal_get", "rna_trackingCamera_focal_set", NULL); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); + + /* Units */ + prop= RNA_def_property(srna, "units", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "units"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_enum_items(prop, camera_units_items); + RNA_def_property_ui_text(prop, "Units", "Units used for camera focal length"); /* Principal Point */ prop= RNA_def_property(srna, "principal", PROP_FLOAT, PROP_NONE); RNA_def_property_array(prop, 2); RNA_def_property_float_sdna(prop, NULL, "principal"); RNA_def_property_ui_text(prop, "Principal Point", "Optical center of lens"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); /* Radial distortion parameters */ prop= RNA_def_property(srna, "k1", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "k1"); RNA_def_property_ui_text(prop, "K1", ""); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); prop= RNA_def_property(srna, "k2", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "k2"); RNA_def_property_ui_text(prop, "K2", ""); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); prop= RNA_def_property(srna, "k3", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "k3"); RNA_def_property_ui_text(prop, "K3", ""); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); } static void rna_def_trackingMarker(BlenderRNA *brna)