From eccccd7b092929d3159dee4d3a48a0c1dd3caaee Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 13 Jul 2011 15:09:45 +0000 Subject: [PATCH] Camera tracking integration =========================== Basic implementation of scene orientation tools. Most probably they'll eb re-exposed in UI soon. - Implemented "Set Floor" operator. It takes three selected tracks which has got bundles and makes them parallel to scene floor. One of selected bundles (active bundle if presents) becomes scene origin, the other becomes X-axis. Guessing of this bundles could fail. Camera tries to be on positive Z half-space. - Implemented "Set X-axis" operator. This operator takes selected track with bundle and aligns it along X-axis. This means rotation to make Y-coord of this bundle 0 is applied. - If camera has got a parent, then transformation would be applient ot this parent, not to camera. Useful for configuration when Empty is used to orient camera and some related stuff in 3D space. --- release/scripts/startup/bl_ui/space_clip.py | 2 + .../blender/editors/space_clip/clip_intern.h | 2 + .../blender/editors/space_clip/space_clip.c | 3 + .../blender/editors/space_clip/tracking_ops.c | 247 ++++++++++++++++-- 4 files changed, 229 insertions(+), 25 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index e68bfbe421d..7a5250b16e5 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -177,7 +177,9 @@ class CLIP_PT_tools(bpy.types.Panel): col = layout.column(align=True) col.label(text="Scene Orientation:") + col.operator("clip.set_floor") col.operator("clip.set_origin") + col.operator("clip.set_x_axis") else: layout.operator('clip.open') diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 1b007feb8ed..52c7d4583cb 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -78,6 +78,8 @@ void CLIP_OT_hide_tracks(struct wmOperatorType *ot); void CLIP_OT_hide_tracks_clear(struct wmOperatorType *ot); void CLIP_OT_set_origin(struct wmOperatorType *ot); +void CLIP_OT_set_floor(struct wmOperatorType *ot); +void CLIP_OT_set_x_axis(struct wmOperatorType *ot); void CLIP_OT_slide_marker(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index cbce61ec9fe..0a770740b03 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -212,7 +212,10 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_disable_markers); WM_operatortype_append(CLIP_OT_hide_tracks); WM_operatortype_append(CLIP_OT_hide_tracks_clear); + WM_operatortype_append(CLIP_OT_set_origin); + WM_operatortype_append(CLIP_OT_set_floor); + WM_operatortype_append(CLIP_OT_set_x_axis); WM_operatortype_append(CLIP_OT_clear_track_path); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index a8094b067c2..a684afde851 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -46,6 +46,7 @@ #include "BKE_tracking.h" #include "BKE_global.h" #include "BKE_depsgraph.h" +#include "BKE_object.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -97,24 +98,24 @@ static int space_clip_frame_poll(bContext *C) return 0; } -static int space_clip_frame_act_bundle_poll(bContext *C) +static int space_clip_frame_camera_poll(bContext *C) +{ + Scene *scene= CTX_data_scene(C); + + if(space_clip_frame_poll(C)) { + return scene->camera != NULL; + } + + return 0; +} + +static int space_clip_camera_poll(bContext *C) { SpaceClip *sc= CTX_wm_space_clip(C); + Scene *scene= CTX_data_scene(C); - if(sc) { - MovieClip *clip= ED_space_clip(sc); - - if(clip) { - if (BKE_movieclip_has_frame(clip, &sc->user)) { - int sel_type; - MovieTrackingTrack *sel; - BKE_movieclip_last_selection(clip, &sel_type, (void**)&sel); - - if(sel_type == MCLIP_SEL_TRACK) - return sel->flag&TRACK_HAS_BUNDLE; - } - } - } + if(sc && sc->clip && scene->camera) + return 1; return 0; } @@ -1216,29 +1217,38 @@ void CLIP_OT_disable_markers(wmOperatorType *ot) /********************** set origin operator *********************/ -static int set_origin_exec(bContext *C, wmOperator *UNUSED(op)) +static int set_origin_exec(bContext *C, wmOperator *op) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); - MovieTrackingTrack *sel; + MovieTrackingTrack *track; Scene *scene= CTX_data_scene(C); - int sel_type; + Object *parent= scene->camera; float mat[4][4], vec[3]; - BKE_movieclip_last_selection(clip, &sel_type, (void**)&sel); + if(scene->camera->parent) + parent= scene->camera->parent; - if(scene->camera == NULL) - scene->camera= scene_find_camera(scene); + track= clip->tracking.tracks.first; + while(track) { + if(TRACK_SELECTED(track)) + break; - if(!scene->camera) + track= track->next; + } + + if(!track) { + BKE_report(op->reports, RPT_ERROR, "Track with bundle should be selected to define origin position"); return OPERATOR_CANCELLED; + } BKE_get_tracking_mat(scene, mat); - mul_v3_m4v3(vec, mat, sel->bundle_pos); + mul_v3_m4v3(vec, mat, track->bundle_pos); - sub_v3_v3(scene->camera->loc, vec); + sub_v3_v3(parent->loc, vec); DAG_id_tag_update(&clip->id, 0); + DAG_id_tag_update(&parent->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, NULL); @@ -1255,7 +1265,194 @@ void CLIP_OT_set_origin(wmOperatorType *ot) /* api callbacks */ ot->exec= set_origin_exec; - ot->poll= space_clip_frame_act_bundle_poll; + ot->poll= space_clip_frame_camera_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************** set floor operator *********************/ + +static void set_x_axis(Scene *scene, Object *ob, MovieTrackingTrack *track) +{ + float mat[4][4], vec[3], obmat[4][4]; + + BKE_get_tracking_mat(scene, mat); + mul_v3_m4v3(vec, mat, track->bundle_pos); + + if(len_v2(vec)<1e-3) + return; + + unit_m4(mat); + + copy_v3_v3(mat[0], vec); + mat[0][2]= 0.f; + mat[2][0]= 0.f; mat[2][1]= 0.f; mat[2][2]= 1.0f; + cross_v3_v3v3(mat[1], mat[2], mat[0]); + + normalize_v3(mat[0]); + normalize_v3(mat[1]); + normalize_v3(mat[2]); + + invert_m4(mat); + + object_to_mat4(ob, obmat); + mul_m4_m4m4(mat, obmat, mat); + object_apply_mat4(ob, mat, 0, 0); +} + +static int set_floor_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + Scene *scene= CTX_data_scene(C); + MovieTrackingTrack *track, *sel, *xtrack= NULL; + Object *camera= scene->camera; + Object *parent= camera; + int tot= 0, sel_type; + float vec[3][3], mat[4][4], obmat[4][4], newmat[4][4], orig[3]; + float rot[4][4]={{0.f, 0.f, -1.f, 0.f}, + {0.f, 1.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f}, + {0.f, 0.f, 0.f, 1.f}}; /* 90 degrees Y-axis rotation matrix */ + + if(scene->camera->parent) + parent= scene->camera->parent; + + BKE_get_tracking_mat(scene, mat); + + BKE_movieclip_last_selection(clip, &sel_type, (void**)&sel); + + /* get 3 bundles to use as reference */ + track= clip->tracking.tracks.first; + while(track && tot<3) { + if(track->flag&TRACK_HAS_BUNDLE && TRACK_SELECTED(track)) { + mul_v3_m4v3(vec[tot], mat, track->bundle_pos); + + if(tot==0 || (sel_type==MCLIP_SEL_TRACK && track==sel)) + copy_v3_v3(orig, vec[tot]); + else + xtrack= track; + + tot++; + } + + track= track->next; + } + + if(tot!=3) { + BKE_report(op->reports, RPT_ERROR, "Three tracks with bundles are needed to orient the floor"); + return OPERATOR_CANCELLED; + } + + sub_v3_v3(vec[1], vec[0]); + sub_v3_v3(vec[2], vec[0]); + + /* construct ortho-normal basis */ + unit_m4(mat); + + cross_v3_v3v3(mat[0], vec[1], vec[2]); + copy_v3_v3(mat[1], vec[1]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + + normalize_v3(mat[0]); + normalize_v3(mat[1]); + normalize_v3(mat[2]); + + /* move to origin point */ + mat[3][0]= orig[0]; + mat[3][1]= orig[1]; + mat[3][2]= orig[2]; + + invert_m4(mat); + + object_to_mat4(parent, obmat); + mul_m4_m4m4(mat, obmat, mat); + mul_m4_m4m4(newmat, mat, rot); + object_apply_mat4(parent, newmat, 0, 0); + + /* make camera have positive z-coordinate */ + mul_v3_m4v3(vec[0], mat, camera->loc); + if(camera->loc[2]<0) { + invert_m4(rot); + mul_m4_m4m4(newmat, mat, rot); + object_apply_mat4(camera, newmat, 0, 0); + } + + where_is_object(scene, parent); + set_x_axis(scene, parent, xtrack); + + DAG_id_tag_update(&clip->id, 0); + DAG_id_tag_update(&parent->id, OB_RECALC_OB); + + WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); + WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, NULL); + + return OPERATOR_FINISHED; +} + +void CLIP_OT_set_floor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Set Floor"; + ot->description= "Set floor using 3 selected bundles"; + ot->idname= "CLIP_OT_set_floor"; + + /* api callbacks */ + ot->exec= set_floor_exec; + ot->poll= space_clip_camera_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************** set origin operator *********************/ + +static int set_x_axis_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + MovieTrackingTrack *track; + Scene *scene= CTX_data_scene(C); + Object *parent= scene->camera; + + if(scene->camera->parent) + parent= scene->camera->parent; + + track= clip->tracking.tracks.first; + while(track) { + if(TRACK_SELECTED(track)) + break; + + track= track->next; + } + + if(!track) { + BKE_report(op->reports, RPT_ERROR, "Track with bundle should be selected to define X-axis"); + return OPERATOR_CANCELLED; + } + + set_x_axis(scene, parent, track); + + DAG_id_tag_update(&clip->id, 0); + DAG_id_tag_update(&parent->id, OB_RECALC_OB); + + WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); + WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, NULL); + + return OPERATOR_FINISHED; +} + +void CLIP_OT_set_x_axis(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Set X-axis"; + ot->description= "Set direction of scene X-axis"; + ot->idname= "CLIP_OT_set_x_axis"; + + /* api callbacks */ + ot->exec= set_x_axis_exec; + ot->poll= space_clip_frame_camera_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;