diff options
33 files changed, 2198 insertions, 498 deletions
diff --git a/release/scripts/presets/tracking_track_color/object.py b/release/scripts/presets/tracking_track_color/object.py new file mode 100644 index 00000000000..5cb663d3f97 --- /dev/null +++ b/release/scripts/presets/tracking_track_color/object.py @@ -0,0 +1,5 @@ +import bpy +track = bpy.context.edit_movieclip.tracking.tracks.active + +track.color = (1.0, 0.0, 1.0) +track.use_custom_color = True diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index 038d7a38fd6..32ed1c3f1b1 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -755,7 +755,16 @@ class ConstraintButtonsPanel(): col = layout.column() col.prop(con, "rotation_range", text="Pivot When") + @staticmethod + def _getConstraintClip(context, con): + if not con.use_active_clip: + return con.clip + else: + return context.scene.active_clip + def FOLLOW_TRACK(self, context, layout, con): + clip = self._getConstraintClip(context, con) + row = layout.row() row.prop(con, "use_active_clip") row.prop(con, "use_3d_position") @@ -763,7 +772,11 @@ class ConstraintButtonsPanel(): if not con.use_active_clip: layout.prop(con, "clip") - layout.prop(con, "track") + if clip: + layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA') + layout.prop_search(con, "track", clip.tracking, "tracks", icon='ANIMATION_DATA') + + layout.prop(con, "camera") layout.operator("clip.constraint_to_fcurve") @@ -775,6 +788,26 @@ class ConstraintButtonsPanel(): layout.operator("clip.constraint_to_fcurve") + def OBJECT_SOLVER(self, context, layout, con): + scene = context.scene + clip = self._getConstraintClip(context, con) + + layout.prop(con, "use_active_clip") + + if not con.use_active_clip: + layout.prop(con, "clip") + + if clip: + layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA') + + layout.prop(con, "camera") + + row = layout.row() + row.operator("constraint.objectsolver_set_inverse") + row.operator("constraint.objectsolver_clear_inverse") + + layout.operator("clip.constraint_to_fcurve") + def SCRIPT(self, context, layout, con): layout.label("Blender 2.5 has no py-constraints") diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index e4f1a12f60b..5234ffbcc32 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -70,7 +70,13 @@ class CLIP_HT_header(Header): row.template_ID(sc, "clip", open='clip.open') if clip: - r = clip.tracking.reconstruction + tracking = clip.tracking + active = tracking.objects.active + + if active and not active.is_camera: + r = active.reconstruction + else: + r = tracking.reconstruction if r.is_valid: layout.label(text="Average solve error: %.4f" % @@ -197,10 +203,18 @@ class CLIP_PT_tools_solve(Panel): def draw(self, context): layout = self.layout clip = context.space_data.clip - settings = clip.tracking.settings + tracking = clip.tracking + settings = tracking.settings + tracking_object = tracking.objects.active col = layout.column(align=True) - col.operator("clip.solve_camera", text="Camera Motion") + + if tracking_object.is_camera: + solve_text = "Camera Motion" + else: + solve_text = "Object Motion" + + col.operator("clip.solve_camera", text=solve_text) col.operator("clip.clear_solution") col = layout.column(align=True) @@ -208,6 +222,7 @@ class CLIP_PT_tools_solve(Panel): col.prop(settings, "keyframe_b") col = layout.column(align=True) + col.active = tracking_object.is_camera col.label(text="Refine:") col.prop(settings, "refine_intrinsics", text="") @@ -287,6 +302,39 @@ class CLIP_PT_tools_orientation(Panel): col.prop(settings, "distance") +class CLIP_PT_tools_object(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'TOOLS' + bl_label = "Object" + + @classmethod + def poll(cls, context): + sc = context.space_data + clip = sc.clip + + if clip and sc.mode == 'RECONSTRUCTION': + tracking_object = clip.tracking.objects.active + return not tracking_object.is_camera + + return False + + def draw(self, context): + sc = context.space_data + clip = sc.clip + layout = self.layout + tracking_object = clip.tracking.objects.active + settings = sc.clip.tracking.settings + + col = layout.column() + + col.prop(tracking_object, "scale") + + col.separator() + + col.operator("clip.set_solution_scale", text="Set Scale") + col.prop(settings, "object_distance") + + class CLIP_PT_tools_grease_pencil(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'TOOLS' @@ -316,6 +364,37 @@ class CLIP_PT_tools_grease_pencil(Panel): row.prop(context.tool_settings, "use_grease_pencil_sessions") +class CLIP_PT_objects(Panel): + bl_space_type = 'CLIP_EDITOR' + bl_region_type = 'UI' + bl_label = "Objects" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + sc = context.space_data + + return sc.clip + + def draw(self, context): + layout = self.layout + sc = context.space_data + clip = context.space_data.clip + tracking = clip.tracking + + row = layout.row() + row.template_list(tracking, "objects", tracking, "active_object_index", rows=3) + + sub = row.column(align=True) + + sub.operator("clip.tracking_object_new", icon='ZOOMIN', text="") + sub.operator("clip.tracking_object_remove", icon='ZOOMOUT', text="") + + active = tracking.objects.active + if active: + layout.prop(active, "name") + + class CLIP_PT_track(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' @@ -428,7 +507,7 @@ class CLIP_PT_tracking_camera(Panel): col.operator("clip.set_center_principal", text="Center") col = layout.column(align=True) - col.label(text="Undistortion:") + col.label(text="Lens Distortion:") col.prop(clip.tracking.camera, "k1") col.prop(clip.tracking.camera, "k2") col.prop(clip.tracking.camera, "k3") diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 973922d4223..a092ad42434 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -34,11 +34,13 @@ struct bGPDlayer; struct ImBuf; +struct ListBase; struct MovieReconstructContext; struct MovieTrackingTrack; struct MovieTrackingMarker; struct MovieTracking; struct MovieTrackingContext; +struct MovieTrackingObject; struct MovieClipUser; struct MovieDistortion; struct Camera; @@ -49,8 +51,8 @@ void BKE_tracking_init_settings(struct MovieTracking *tracking); void BKE_tracking_clamp_track(struct MovieTrackingTrack *track, int event); void BKE_tracking_track_flag(struct MovieTrackingTrack *track, int area, int flag, int clear); -struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, float x, float y, - int framenr, int width, int height); +struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, struct ListBase *tracksbase, + float x, float y, int framenr, int width, int height); void BKE_tracking_insert_marker(struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker); void BKE_tracking_delete_marker(struct MovieTrackingTrack *track, int framenr); @@ -72,16 +74,27 @@ struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTra struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int margin, int anchored, float pos[2], int origin[2]); -void BKE_track_unique_name(struct MovieTracking *tracking, struct MovieTrackingTrack *track); +void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); -struct MovieTrackingTrack *BKE_tracking_named_track(struct MovieTracking *tracking, const char *name); -struct MovieTrackingTrack *BKE_tracking_indexed_track(struct MovieTracking *tracking, int tracknr); +struct MovieTrackingTrack *BKE_tracking_named_track(struct MovieTracking *tracking, struct MovieTrackingObject *object, const char *name); +struct MovieTrackingTrack *BKE_tracking_indexed_track(struct MovieTracking *tracking, int tracknr, struct ListBase **tracksbase_r); void BKE_tracking_camera_shift(struct MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty); void BKE_tracking_camera_to_blender(struct MovieTracking *tracking, struct Scene *scene, struct Camera *camera, int width, int height); void BKE_get_tracking_mat(struct Scene *scene, struct Object *ob, 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_projection_matrix(struct MovieTracking *tracking, struct MovieTrackingObject *object, + int framenr, int winx, int winy, float mat[4][4]); + +struct ListBase *BKE_tracking_get_tracks(struct MovieTracking *tracking); +struct MovieTrackingReconstruction *BKE_tracking_get_reconstruction(struct MovieTracking *tracking); + +struct MovieTrackingTrack *BKE_tracking_active_track(struct MovieTracking *tracking); +struct MovieTrackingObject *BKE_tracking_active_object(struct MovieTracking *tracking); +struct MovieTrackingObject *BKE_tracking_get_camera_object(struct MovieTracking *tracking); +struct ListBase *BKE_tracking_object_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); +struct MovieTrackingReconstruction *BKE_tracking_object_reconstruction(struct MovieTracking *tracking, + struct MovieTrackingObject *object); /* 2D tracking */ struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user, @@ -92,20 +105,23 @@ void BKE_tracking_sync_user(struct MovieClipUser *user, struct MovieTrackingCont int BKE_tracking_next(struct MovieTrackingContext *context); /* Camera solving */ -int BKE_tracking_can_reconstruct(struct MovieTracking *tracking, char *error_msg, int error_size); +int BKE_tracking_can_reconstruct(struct MovieTracking *tracking, struct MovieTrackingObject *object, + char *error_msg, int error_size); struct MovieReconstructContext* BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking, - int keyframe1, int keyframe2, int width, int height); + struct MovieTrackingObject *object, 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, 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); -void BKE_tracking_get_interpolated_camera(struct MovieTracking *tracking, int framenr, float mat[4][4]); +struct MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(struct MovieTracking *tracking, + struct MovieTrackingObject *object, int framenr); +void BKE_tracking_get_interpolated_camera(struct MovieTracking *tracking, + struct MovieTrackingObject *object, int framenr, float mat[4][4]); /* Feature detection */ -void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ImBuf *imbuf, +void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ListBase *tracksbase, struct ImBuf *imbuf, int framenr, int margin, int min_trackness, int min_distance, struct bGPDlayer *layer, int place_outside_layer); @@ -127,8 +143,14 @@ void BKE_tracking_distortion_destroy(struct MovieDistortion *distortion); struct ImBuf *BKE_tracking_undistort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan); struct ImBuf *BKE_tracking_distort(struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan); +/* Object tracking */ +struct MovieTrackingObject *BKE_tracking_new_object(struct MovieTracking *tracking, const char *name); +void BKE_tracking_remove_object(struct MovieTracking *tracking, struct MovieTrackingObject *object); +void BKE_tracking_object_unique_name(struct MovieTracking *tracking, struct MovieTrackingObject *object); +struct MovieTrackingObject *BKE_tracking_named_object(struct MovieTracking *tracking, const char *name); + /* Select */ -void BKE_tracking_select_track(struct MovieTracking *tracking, struct MovieTrackingTrack *track, int area, int extend); +void BKE_tracking_select_track(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend); void BKE_tracking_deselect_track(struct MovieTrackingTrack *track, int area); #define TRACK_SELECTED(track) ((((track)->flag&TRACK_HIDDEN)==0) && ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT)) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 79986525e2e..878db6b3ed1 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -825,7 +825,7 @@ static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta { bChildOfConstraint *data= con->data; bConstraintTarget *ct= targets->first; - + /* only evaluate if there is a target */ if (VALID_CONS_TARGET(ct)) { float parmat[4][4]; @@ -3949,6 +3949,7 @@ static void followtrack_id_looper (bConstraint *con, ConstraintIDFunc func, void bFollowTrackConstraint *data= con->data; func(con, (ID**)&data->clip, userdata); + func(con, (ID**)&data->camera, userdata); } static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) @@ -3956,105 +3957,126 @@ static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase Scene *scene= cob->scene; bFollowTrackConstraint *data= con->data; MovieClip *clip= data->clip; + MovieTracking *tracking; MovieTrackingTrack *track; - + MovieTrackingObject *tracking_object; + Object *camob= data->camera ? data->camera : scene->camera; + if (data->flag & FOLLOWTRACK_ACTIVECLIP) clip= scene->clip; - - if (!clip || !data->track[0]) + + if (!clip || !data->track[0] || !camob) return; - - track= BKE_tracking_named_track(&clip->tracking, data->track); - + + tracking= &clip->tracking; + + if(data->object[0]) + tracking_object= BKE_tracking_named_object(tracking, data->object); + else + tracking_object= BKE_tracking_get_camera_object(tracking); + + if(!tracking_object) + return; + + track= BKE_tracking_named_track(tracking, tracking_object, data->track); + if (!track) return; - + if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { if (track->flag & TRACK_HAS_BUNDLE) { - float pos[3], mat[4][4], obmat[4][4]; - + MovieTracking *tracking= &clip->tracking; + float obmat[4][4], mat[4][4]; + copy_m4_m4(obmat, cob->matrix); - - BKE_get_tracking_mat(cob->scene, NULL, mat); - mul_v3_m4v3(pos, mat, track->bundle_pos); - - cob->matrix[3][0] += pos[0]; - cob->matrix[3][1] += pos[1]; - cob->matrix[3][2] += pos[2]; + + if((tracking_object->flag&TRACKING_OBJECT_CAMERA)==0) { + float imat[4][4]; + + copy_m4_m4(mat, camob->obmat); + + BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, imat); + invert_m4(imat); + + mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL); + translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); + } + else { + BKE_get_tracking_mat(cob->scene, camob, mat); + + mult_m4_m4m4(cob->matrix, obmat, mat); + translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); + } } } else { - Object *camob= cob->scene->camera; - - if (camob) { - MovieClipUser user; - MovieTrackingMarker *marker; - float vec[3], disp[3], axis[3], mat[4][4]; - float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp); - float len, d; - - where_is_object_mat(scene, camob, mat); - - /* camera axis */ - vec[0]= 0.0f; - vec[1]= 0.0f; - vec[2]= 1.0f; - mul_v3_m4v3(axis, mat, vec); - - /* distance to projection plane */ - copy_v3_v3(vec, cob->matrix[3]); - sub_v3_v3(vec, mat[3]); - project_v3_v3v3(disp, vec, axis); - - len= len_v3(disp); - - if (len > FLT_EPSILON) { - CameraParams params; - float pos[2], rmat[4][4]; - - user.framenr= scene->r.cfra; - marker= BKE_tracking_get_marker(track, user.framenr); - - add_v2_v2v2(pos, marker->pos, track->offset); - - camera_params_init(¶ms); - camera_params_from_object(¶ms, camob); + MovieClipUser user; + MovieTrackingMarker *marker; + float vec[3], disp[3], axis[3], mat[4][4]; + float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp); + float len, d; - if (params.is_ortho) { - vec[0]= params.ortho_scale * (pos[0]-0.5f+params.shiftx); - vec[1]= params.ortho_scale * (pos[1]-0.5f+params.shifty); - vec[2]= -len; - - if (aspect > 1.0f) vec[1] /= aspect; - else vec[0] *= aspect; - - mul_v3_m4v3(disp, camob->obmat, vec); - - copy_m4_m4(rmat, camob->obmat); - zero_v3(rmat[3]); - mult_m4_m4m4(cob->matrix, cob->matrix, rmat); - - copy_v3_v3(cob->matrix[3], disp); - } - else { - d= (len*params.sensor_x) / (2.0f*params.lens); - - vec[0]= d*(2.0f*(pos[0]+params.shiftx)-1.0f); - vec[1]= d*(2.0f*(pos[1]+params.shifty)-1.0f); - vec[2]= -len; - - if (aspect > 1.0f) vec[1] /= aspect; - else vec[0] *= aspect; - - mul_v3_m4v3(disp, camob->obmat, vec); - - /* apply camera rotation so Z-axis would be co-linear */ - copy_m4_m4(rmat, camob->obmat); - zero_v3(rmat[3]); - mult_m4_m4m4(cob->matrix, cob->matrix, rmat); - - copy_v3_v3(cob->matrix[3], disp); - } + where_is_object_mat(scene, camob, mat); + + /* camera axis */ + vec[0]= 0.0f; + vec[1]= 0.0f; + vec[2]= 1.0f; + mul_v3_m4v3(axis, mat, vec); + + /* distance to projection plane */ + copy_v3_v3(vec, cob->matrix[3]); + sub_v3_v3(vec, mat[3]); + project_v3_v3v3(disp, vec, axis); + + len= len_v3(disp); + + if (len > FLT_EPSILON) { + CameraParams params; + float pos[2], rmat[4][4]; + + user.framenr= scene->r.cfra; + marker= BKE_tracking_get_marker(track, user.framenr); + + add_v2_v2v2(pos, marker->pos, track->offset); + + camera_params_init(¶ms); + camera_params_from_object(¶ms, camob); + + if (params.is_ortho) { + vec[0]= params.ortho_scale * (pos[0]-0.5f+params.shiftx); + vec[1]= params.ortho_scale * (pos[1]-0.5f+params.shifty); + vec[2]= -len; + + if (aspect > 1.0f) vec[1] /= aspect; + else vec[0] *= aspect; + + mul_v3_m4v3(disp, camob->obmat, vec); + + copy_m4_m4(rmat, camob->obmat); + zero_v3(rmat[3]); + mult_m4_m4m4(cob->matrix, cob->matrix, rmat); + + copy_v3_v3(cob->matrix[3], disp); + } + else { + d= (len*params.sensor_x) / (2.0f*params.lens); + + vec[0]= d*(2.0f*(pos[0]+params.shiftx)-1.0f); + vec[1]= d*(2.0f*(pos[1]+params.shifty)-1.0f); + vec[2]= -len; + + if (aspect > 1.0f) vec[1] /= aspect; + else vec[0] *= aspect; + + mul_v3_m4v3(disp, camob->obmat, vec); + + /* apply camera rotation so Z-axis would be co-linear */ + copy_m4_m4(rmat, camob->obmat); + zero_v3(rmat[3]); + mult_m4_m4m4(cob->matrix, cob->matrix, rmat); + + copy_v3_v3(cob->matrix[3], disp); } } } @@ -4098,16 +4120,19 @@ static void camerasolver_evaluate (bConstraint *con, bConstraintOb *cob, ListBas Scene *scene= cob->scene; bCameraSolverConstraint *data= con->data; MovieClip *clip= data->clip; - + if (data->flag & CAMERASOLVER_ACTIVECLIP) clip= scene->clip; - + if (clip) { float mat[4][4], obmat[4][4]; - - BKE_tracking_get_interpolated_camera(&clip->tracking, scene->r.cfra, mat); - + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *object= BKE_tracking_get_camera_object(tracking); + + BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat); + copy_m4_m4(obmat, cob->matrix); + mult_m4_m4m4(cob->matrix, obmat, mat); } } @@ -4128,6 +4153,80 @@ static bConstraintTypeInfo CTI_CAMERASOLVER = { camerasolver_evaluate /* evaluate */ }; +/* ----------- Object Solver ------------- */ + +static void objectsolver_new_data (void *cdata) +{ + bObjectSolverConstraint *data= (bObjectSolverConstraint *)cdata; + + data->clip = NULL; + data->flag |= OBJECTSOLVER_ACTIVECLIP; + unit_m4(data->invmat); +} + +static void objectsolver_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) +{ + bObjectSolverConstraint *data= con->data; + + func(con, (ID**)&data->clip, userdata); + func(con, (ID**)&data->camera, userdata); +} + +static void objectsolver_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) +{ + Scene *scene= cob->scene; + bObjectSolverConstraint *data= con->data; + MovieClip *clip= data->clip; + Object *camob= data->camera ? data->camera : scene->camera; + + if (data->flag & OBJECTSOLVER_ACTIVECLIP) + clip= scene->clip; + + if(!camob || !clip) + return; + + if (clip) { + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *object; + + object= BKE_tracking_named_object(tracking, data->object); + + if(object) { + float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4]; + + where_is_object_mat(scene, camob, cammat); + + BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, mat); + + invert_m4_m4(camimat, cammat); + mult_m4_m4m4(parmat, cammat, data->invmat); + + copy_m4_m4(cammat, camob->obmat); + copy_m4_m4(obmat, cob->matrix); + + invert_m4_m4(imat, mat); + + mul_serie_m4(cob->matrix, cammat, imat, camimat, parmat, obmat, NULL, NULL, NULL); + } + } +} + +static bConstraintTypeInfo CTI_OBJECTSOLVER = { + CONSTRAINT_TYPE_OBJECTSOLVER, /* type */ + sizeof(bObjectSolverConstraint), /* size */ + "Object Solver", /* name */ + "bObjectSolverConstraint", /* struct name */ + NULL, /* free data */ + NULL, /* relink data */ + objectsolver_id_looper, /* id looper */ + NULL, /* copy data */ + objectsolver_new_data, /* new data */ + NULL, /* get constraint targets */ + NULL, /* flush constraint targets */ + NULL, /* get target matrix */ + objectsolver_evaluate /* evaluate */ +}; + /* ************************* Constraints Type-Info *************************** */ /* All of the constraints api functions use bConstraintTypeInfo structs to carry out * and operations that involve constraint specific code. @@ -4168,6 +4267,7 @@ static void constraints_init_typeinfo (void) constraintsTypeInfo[25]= &CTI_PIVOT; /* Pivot Constraint */ constraintsTypeInfo[26]= &CTI_FOLLOWTRACK; /* Follow Track Constraint */ constraintsTypeInfo[27]= &CTI_CAMERASOLVER; /* Camera Solver Constraint */ + constraintsTypeInfo[28]= &CTI_OBJECTSOLVER; /* Object Solver Constraint */ } /* This function should be used for getting the appropriate type-info when only diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index a76fa8e8579..e56a8034b21 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -649,16 +649,21 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O continue; /* special case for camera tracking -- it doesn't use targets to define relations */ - if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER)) { + if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { + int depends_on_camera= 0; + if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) { bFollowTrackConstraint *data= (bFollowTrackConstraint *)con->data; - if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0]) { - if(scene->camera) { - node2 = dag_get_node(dag, scene->camera); - dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name); - } - } + if((data->clip || data->flag&FOLLOWTRACK_ACTIVECLIP) && data->track[0]) + depends_on_camera= 1; + } + else if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER) + depends_on_camera= 1; + + if(depends_on_camera && scene->camera) { + node2 = dag_get_node(dag, scene->camera); + dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB, cti->name); } dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation"); @@ -2165,7 +2170,7 @@ static void dag_object_time_update_flags(Object *ob) if (cti) { /* special case for camera tracking -- it doesn't use targets to define relations */ - if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER)) { + if(ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) { ob->recalc |= OB_RECALC_OB; } else if (cti->get_constraint_targets) { diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 10c060e0aab..ab963f1e78c 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -816,7 +816,8 @@ void BKE_movieclip_reload(MovieClip *clip) void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes) { - if(scopes->ok) return; + if(scopes->ok) + return; if(scopes->track_preview) { IMB_freeImBuf(scopes->track_preview); @@ -827,8 +828,10 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->track= NULL; if(clip) { - if(clip->tracking.act_track) { - MovieTrackingTrack *track= clip->tracking.act_track; + MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking); + + if(act_track) { + MovieTrackingTrack *track= act_track; MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); if(marker->flag&MARKER_DISABLED) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 3fa7355767a..6bf9b646c35 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -55,6 +55,7 @@ #include "BKE_movieclip.h" #include "BKE_object.h" #include "BKE_scene.h" +#include "BKE_main.h" // XXX: ... #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -85,11 +86,14 @@ void BKE_tracking_init_settings(MovieTracking *tracking) tracking->settings.keyframe1= 1; tracking->settings.keyframe2= 30; tracking->settings.dist= 1; + tracking->settings.object_distance= 1; tracking->stabilization.scaleinf= 1.0f; tracking->stabilization.locinf= 1.0f; tracking->stabilization.rotinf= 1.0f; tracking->stabilization.maxscale= 2.0f; + + BKE_tracking_new_object(tracking, "Camera"); } void BKE_tracking_clamp_track(MovieTrackingTrack *track, int event) @@ -208,7 +212,7 @@ void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int } } -MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, float y, +MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y, int framenr, int width, int height) { MovieTrackingTrack *track; @@ -251,8 +255,8 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, float x, flo if(track->tracker == TRACKER_KLT) BKE_tracking_clamp_track(track, CLAMP_PYRAMID_LEVELS); - BLI_addtail(&tracking->tracks, track); - BKE_track_unique_name(tracking, track); + BLI_addtail(tracksbase, track); + BKE_track_unique_name(tracksbase, track); return track; } @@ -524,18 +528,44 @@ void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack dst_track->markersnr= tot; } -void BKE_tracking_free(MovieTracking *tracking) +static void tracking_tracks_free(ListBase *tracks) { MovieTrackingTrack *track; - for(track= tracking->tracks.first; track; track= track->next) { + for(track= tracks->first; track; track= track->next) { BKE_tracking_free_track(track); } - BLI_freelistN(&tracking->tracks); + BLI_freelistN(tracks); +} + +static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction) +{ + if(reconstruction->cameras) + MEM_freeN(reconstruction->cameras); +} + +static void tracking_object_free(MovieTrackingObject *object) +{ + tracking_tracks_free(&object->tracks); + tracking_reconstruction_free(&object->reconstruction); +} + +static void tracking_objects_free(ListBase *objects) +{ + MovieTrackingObject *object; + + for(object= objects->first; object; object= object->next) + tracking_object_free(object); + + BLI_freelistN(objects); +} - if(tracking->reconstruction.cameras) - MEM_freeN(tracking->reconstruction.cameras); +void BKE_tracking_free(MovieTracking *tracking) +{ + tracking_tracks_free(&tracking->tracks); + tracking_reconstruction_free(&tracking->reconstruction); + tracking_objects_free(&tracking->objects); if(tracking->stabilization.scaleibuf) IMB_freeImBuf(tracking->stabilization.scaleibuf); @@ -547,6 +577,9 @@ void BKE_tracking_free(MovieTracking *tracking) /*********************** tracks map *************************/ typedef struct TracksMap { + char object_name[32]; + int is_camera; + int num_tracks; int customdata_size; @@ -558,10 +591,13 @@ typedef struct TracksMap { int ptr; } TracksMap; -static TracksMap *tracks_map_new(int num_tracks, int customdata_size) +static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size) { TracksMap *map= MEM_callocN(sizeof(TracksMap), "TrackingsMap"); + strcpy(map->object_name, object_name); + map->is_camera= is_camera; + map->num_tracks= num_tracks; map->customdata_size= customdata_size; @@ -607,10 +643,24 @@ static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *c static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) { MovieTrackingTrack *track; + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); ListBase tracks= {NULL, NULL}, new_tracks= {NULL, NULL}; - ListBase *old_tracks= &tracking->tracks; + ListBase *old_tracks; int a; + if(map->is_camera) { + old_tracks= &tracking->tracks; + } else { + MovieTrackingObject *object= BKE_tracking_named_object(tracking, map->object_name); + + if(!object) { + /* object was deleted by user, create new one */ + object= BKE_tracking_new_object(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) */ @@ -634,7 +684,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) /* original track was found, re-use flags and remove this track */ if(cur) { - if(cur==tracking->act_track) + if(act_track) replace_sel= 1; track->flag= cur->flag; @@ -685,7 +735,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) track= next; } - tracking->tracks= new_tracks; + *old_tracks= new_tracks; } static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata)) @@ -746,7 +796,9 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u MovieTrackingContext *context= MEM_callocN(sizeof(MovieTrackingContext), "trackingContext"); MovieTracking *tracking= &clip->tracking; MovieTrackingSettings *settings= &tracking->settings; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; + MovieTrackingObject *object= BKE_tracking_active_object(tracking); int num_tracks= 0; context->settings= *settings; @@ -757,7 +809,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u context->sequence= sequence; /* count */ - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) { MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); @@ -772,12 +824,13 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u if(num_tracks) { int width, height; - context->tracks_map= tracks_map_new(num_tracks, sizeof(TrackContext)); + context->tracks_map= tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA, + num_tracks, sizeof(TrackContext)); BKE_movieclip_get_size(clip, user, &width, &height); /* create tracking data */ - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(TRACK_SELECTED(track) && (track->flag&TRACK_LOCKED)==0) { MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr); @@ -1393,6 +1446,8 @@ typedef struct MovieReconstructContext { struct libmv_Reconstruction *reconstruction; #endif + char object_name[32]; + int is_camera; float focal_length; float principal_point[2]; @@ -1414,13 +1469,13 @@ typedef struct ReconstructProgressData { } ReconstructProgressData; #if WITH_LIBMV -static struct libmv_Tracks *create_libmv_tracks(MovieTracking *tracking, int width, int height) +static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height) { int tracknr= 0; MovieTrackingTrack *track; struct libmv_Tracks *tracks= libmv_tracksNew(); - track= tracking->tracks.first; + track= tracksbase->first; while(track) { int a= 0; @@ -1464,16 +1519,28 @@ static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *conte static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking) { struct libmv_Reconstruction *libmv_reconstruction= context->reconstruction; - MovieTrackingReconstruction *reconstruction= &tracking->reconstruction; + MovieTrackingReconstruction *reconstruction= NULL; MovieReconstructedCamera *reconstructed; MovieTrackingTrack *track; + ListBase *tracksbase= NULL; int ok= 1, tracknr= 0, a, origin_set= 0; int sfra= context->sfra, efra= context->efra; float imat[4][4]; + if(context->is_camera) { + tracksbase= &tracking->tracks; + reconstruction= &tracking->reconstruction; + } + else { + MovieTrackingObject *object= BKE_tracking_named_object(tracking, context->object_name); + + tracksbase= &object->tracks; + reconstruction= &object->reconstruction; + } + unit_m4(imat); - track= tracking->tracks.first; + track= tracksbase->first; while(track) { double pos[3]; @@ -1539,7 +1606,7 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M } if(origin_set) { - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(track->flag&TRACK_HAS_BUNDLE) mul_v3_m4v3(track->bundle_pos, imat, track->bundle_pos); @@ -1555,19 +1622,20 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking) { - tracks_map_merge(context->tracks_map, tracking); - /* take the intrinscis back from libmv */ retrieve_libmv_reconstruct_intrinscis(context, tracking); return retrieve_libmv_reconstruct_tracks(context, tracking); } -static int get_refine_intrinsics_flags(MovieTracking *tracking) +static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object) { int refine= tracking->settings.refine_camera_intrinsics; int flags= 0; + if((object->flag&TRACKING_OBJECT_CAMERA)==0) + return 0; + if(refine&REFINE_FOCAL_LENGTH) flags|= LIBMV_REFINE_FOCAL_LENGTH; @@ -1583,13 +1651,13 @@ static int get_refine_intrinsics_flags(MovieTracking *tracking) return flags; } -static int count_tracks_on_both_keyframes(MovieTracking *tracking) +static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase) { int tot= 0; int frame1= tracking->settings.keyframe1, frame2= tracking->settings.keyframe2; MovieTrackingTrack *track; - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(BKE_tracking_has_marker(track, frame1)) if(BKE_tracking_has_marker(track, frame2)) @@ -1602,10 +1670,12 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking) } #endif -int BKE_tracking_can_reconstruct(MovieTracking *tracking, char *error_msg, int error_size) +int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) { #if WITH_LIBMV - if(count_tracks_on_both_keyframes(tracking)<8) { + ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); + + if(count_tracks_on_both_keyframes(tracking, tracksbase)<8) { BLI_strncpy(error_msg, "At least 8 tracks on both of keyframes are needed for reconstruction", error_size); return 0; } @@ -1620,17 +1690,22 @@ int BKE_tracking_can_reconstruct(MovieTracking *tracking, char *error_msg, int e } MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking, - int keyframe1, int keyframe2, int width, int height) + MovieTrackingObject *object, int keyframe1, int keyframe2, int width, int height) { MovieReconstructContext *context= MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data"); MovieTrackingCamera *camera= &tracking->camera; + ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); float aspy= 1.0f/tracking->camera.pixel_aspect; - int num_tracks= BLI_countlist(&tracking->tracks); + int num_tracks= BLI_countlist(tracksbase); int sfra= INT_MAX, efra= INT_MIN; MovieTrackingTrack *track; - context->tracks_map= tracks_map_new(num_tracks, 0); - track= tracking->tracks.first; + strcpy(context->object_name, object->name); + context->is_camera = object->flag&TRACKING_OBJECT_CAMERA; + + context->tracks_map= tracks_map_new(context->object_name, context->is_camera, num_tracks, 0); + + track= tracksbase->first; while(track) { int first= 0, last= track->markersnr-1; MovieTrackingMarker *first_marker= &track->markers[0]; @@ -1663,10 +1738,10 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking * context->efra= efra; #ifdef WITH_LIBMV - context->tracks= create_libmv_tracks(tracking, width, height*aspy); + context->tracks= create_libmv_tracks(tracksbase, width, height*aspy); context->keyframe1= keyframe1; context->keyframe2= keyframe2; - context->refine_flags= get_refine_intrinsics_flags(tracking); + context->refine_flags= get_refine_intrinsics_flags(tracking, object); #else (void) width; (void) height; @@ -1763,8 +1838,22 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking) { - tracking->reconstruction.error= context->reprojection_error; - tracking->reconstruction.flag|= TRACKING_RECONSTRUCTED; + MovieTrackingReconstruction *reconstruction; + + tracks_map_merge(context->tracks_map, tracking); + + if(context->is_camera) { + reconstruction= &tracking->reconstruction; + } + else { + MovieTrackingObject *object; + + object= BKE_tracking_named_object(tracking, context->object_name); + reconstruction= &object->reconstruction; + } + + reconstruction->error= context->reprojection_error; + reconstruction->flag|= TRACKING_RECONSTRUCTED; #ifdef WITH_LIBMV if(!retrieve_libmv_reconstruct(context, tracking)) @@ -1774,14 +1863,15 @@ int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTr return 1; } -void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track) +void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track) { - BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); + BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); } -MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char *name) +MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name) { - MovieTrackingTrack *track= tracking->tracks.first; + ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); + MovieTrackingTrack *track= tracksbase->first; while(track) { if(!strcmp(track->name, name)) @@ -1793,9 +1883,8 @@ MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, const char return NULL; } -static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int nearest) +static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest) { - MovieTrackingReconstruction *reconstruction= &tracking->reconstruction; MovieReconstructedCamera *cameras= reconstruction->cameras; int a= 0, d= 1; @@ -1847,21 +1936,41 @@ static int reconstruction_camera_index(MovieTracking *tracking, int framenr, int return -1; } -MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, int framenr) +static void scale_reconstructed_camera(MovieTrackingObject *object, float mat[4][4]) +{ + if((object->flag&TRACKING_OBJECT_CAMERA)==0) { + float smat[4][4]; + + scale_m4_fl(smat, 1.0f/object->scale); + mult_m4_m4m4(mat, mat, smat); + } +} + +MovieReconstructedCamera *BKE_tracking_get_reconstructed_camera(MovieTracking *tracking, + MovieTrackingObject *object, int framenr) { - int a= reconstruction_camera_index(tracking, framenr, 0); + MovieTrackingReconstruction *reconstruction; + int a; + + reconstruction= BKE_tracking_object_reconstruction(tracking, object); + a= reconstruction_camera_index(reconstruction, framenr, 0); if(a==-1) return NULL; - return &tracking->reconstruction.cameras[a]; + return &reconstruction->cameras[a]; } -void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, float mat[4][4]) +void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object, + int framenr, float mat[4][4]) { - MovieTrackingReconstruction *reconstruction= &tracking->reconstruction; - MovieReconstructedCamera *cameras= reconstruction->cameras; - int a= reconstruction_camera_index(tracking, framenr, 1); + MovieTrackingReconstruction *reconstruction; + MovieReconstructedCamera *cameras; + int a; + + reconstruction= BKE_tracking_object_reconstruction(tracking, object); + cameras= reconstruction->cameras; + a= reconstruction_camera_index(reconstruction, framenr, 1); if(a==-1) { unit_m4(mat); @@ -1875,6 +1984,8 @@ void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, int framenr, } else { copy_m4_m4(mat, cameras[a].mat); } + + scale_reconstructed_camera(object, mat); } void BKE_get_tracking_mat(Scene *scene, Object *ob, float mat[4][4]) @@ -1913,7 +2024,8 @@ void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camer BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty); } -void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int winx, int winy, float mat[4][4]) +void BKE_tracking_projection_matrix(MovieTracking *tracking, MovieTrackingObject *object, + int framenr, int winx, int winy, float mat[4][4]) { MovieReconstructedCamera *camera; float lens= tracking->camera.focal*tracking->camera.sensor_width/(float)winx; @@ -1946,7 +2058,8 @@ void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int wi perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); - camera= BKE_tracking_get_reconstructed_camera(tracking, framenr); + camera= BKE_tracking_get_reconstructed_camera(tracking, object, framenr); + if(camera) { float imat[4][4]; @@ -1955,6 +2068,77 @@ void BKE_tracking_projection_matrix(MovieTracking *tracking, int framenr, int wi } else copy_m4_m4(mat, winmat); } +ListBase *BKE_tracking_get_tracks(MovieTracking *tracking) +{ + MovieTrackingObject *object= BKE_tracking_active_object(tracking); + + if(object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) { + return &object->tracks; + } + + return &tracking->tracks; +} + +MovieTrackingTrack *BKE_tracking_active_track(MovieTracking *tracking) +{ + ListBase *tracksbase; + + if(!tracking->act_track) + return NULL; + + tracksbase= BKE_tracking_get_tracks(tracking); + + /* check that active track is in current tracks list */ + if(BLI_findindex(tracksbase, tracking->act_track) >= 0) + return tracking->act_track; + + return NULL; +} + +MovieTrackingObject *BKE_tracking_active_object(MovieTracking *tracking) +{ + return BLI_findlink(&tracking->objects, tracking->objectnr); +} + +MovieTrackingObject *BKE_tracking_get_camera_object(MovieTracking *tracking) +{ + MovieTrackingObject *object= tracking->objects.first; + + while(object) { + if(object->flag & TRACKING_OBJECT_CAMERA) + return object; + + object= object->next; + } + + return NULL; +} + +ListBase *BKE_tracking_object_tracks(MovieTracking *tracking, MovieTrackingObject *object) +{ + if(object->flag & TRACKING_OBJECT_CAMERA) { + return &tracking->tracks; + } + + return &object->tracks; +} + +MovieTrackingReconstruction *BKE_tracking_object_reconstruction(MovieTracking *tracking, MovieTrackingObject *object) +{ + if(object->flag & TRACKING_OBJECT_CAMERA) { + return &tracking->reconstruction; + } + + return &object->reconstruction; +} + +MovieTrackingReconstruction *BKE_tracking_get_reconstruction(MovieTracking *tracking) +{ + MovieTrackingObject *object= BKE_tracking_active_object(tracking); + + return BKE_tracking_object_reconstruction(tracking, object); +} + void BKE_tracking_apply_intrinsics(MovieTracking *tracking, float co[2], float nco[2]) { MovieTrackingCamera *camera= &tracking->camera; @@ -2041,8 +2225,9 @@ static int point_in_layer(bGPDlayer *layer, float x, float y) return 0; } -static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Features *features, - int framenr, int width, int height, bGPDlayer *layer, int place_outside_layer) +static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbase, + struct libmv_Features *features, int framenr, int width, int height, + bGPDlayer *layer, int place_outside_layer) { int a; @@ -2062,7 +2247,7 @@ static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Featur ok= point_in_layer(layer, xu, yu)!=place_outside_layer; if(ok) { - track= BKE_tracking_add_track(tracking, xu, yu, framenr, width, height); + track= BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height); track->flag|= SELECT; track->pat_flag|= SELECT; track->search_flag|= SELECT; @@ -2071,7 +2256,7 @@ static void retrieve_libmv_features(MovieTracking *tracking, struct libmv_Featur } #endif -void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf, +void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf, int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer, int place_outside_layer) { @@ -2079,11 +2264,13 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf, struct libmv_Features *features; unsigned char *pixels= get_ucharbuf(ibuf); - features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, margin, min_trackness, min_distance); + features= libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, + margin, min_trackness, min_distance); MEM_freeN(pixels); - retrieve_libmv_features(tracking, features, framenr, ibuf->x, ibuf->y, layer, place_outside_layer); + retrieve_libmv_features(tracking, tracksbase, features, framenr, + ibuf->x, ibuf->y, layer, place_outside_layer); libmv_destroyFeatures(features); #else @@ -2098,22 +2285,34 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ImBuf *ibuf, #endif } -MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr) +MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r) { - MovieTrackingTrack *track= tracking->tracks.first; + MovieTrackingObject *object; int cur= 1; - while(track) { - if(track->flag&TRACK_HAS_BUNDLE) { - if(cur==tracknr) - return track; + object= tracking->objects.first; + while(object) { + ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); + MovieTrackingTrack *track= tracksbase->first; + + while(track) { + if(track->flag&TRACK_HAS_BUNDLE) { + if(cur==tracknr) { + *tracksbase_r= tracksbase; + return track; + } - cur++; + cur++; + } + + track= track->next; } - track= track->next; + object= object->next; } + *tracksbase_r= NULL; + return NULL; } @@ -2125,6 +2324,8 @@ static int stabilization_median_point(MovieTracking *tracking, int framenr, floa INIT_MINMAX2(min, max); + (void) tracking; + track= tracking->tracks.first; while(track) { if(track->flag&TRACK_USE_2D_STAB) { @@ -2562,12 +2763,12 @@ ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int } /* area - which part of marker should be selected. see TRACK_AREA_* constants */ -void BKE_tracking_select_track(MovieTracking *tracking, MovieTrackingTrack *track, int area, int extend) +void BKE_tracking_select_track(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend) { if(extend) { BKE_tracking_track_flag(track, area, SELECT, 0); } else { - MovieTrackingTrack *cur= tracking->tracks.first; + MovieTrackingTrack *cur= tracksbase->first; while(cur) { if(cur==track) { @@ -2587,3 +2788,78 @@ void BKE_tracking_deselect_track(MovieTrackingTrack *track, int area) { BKE_tracking_track_flag(track, area, SELECT, 1); } + +MovieTrackingObject *BKE_tracking_new_object(MovieTracking *tracking, const char *name) +{ + MovieTrackingObject *object= MEM_callocN(sizeof(MovieTrackingObject), "tracking object"); + + if(tracking->tot_object==0) { + /* first object is always camera */ + BLI_strncpy(object->name, "Camera", sizeof(object->name)); + + object->flag|= TRACKING_OBJECT_CAMERA; + } + else { + BLI_strncpy(object->name, name, sizeof(object->name)); + } + + BLI_addtail(&tracking->objects, object); + + tracking->tot_object++; + tracking->objectnr= BLI_countlist(&tracking->objects) - 1; + + BKE_tracking_object_unique_name(tracking, object); + + return object; +} + +void BKE_tracking_remove_object(MovieTracking *tracking, MovieTrackingObject *object) +{ + MovieTrackingTrack *track; + int index= BLI_findindex(&tracking->objects, object); + + if(index<0) + return; + + if(object->flag & TRACKING_OBJECT_CAMERA) { + /* object used for camera solving can't be deleted */ + return; + } + + track= object->tracks.first; + while(track) { + if(track==tracking->act_track) + tracking->act_track= NULL; + + track= track->next; + } + + tracking_object_free(object); + BLI_freelinkN(&tracking->objects, object); + + tracking->tot_object--; + + if(index>0) + tracking->objectnr= index-1; + else + tracking->objectnr= 0; +} + +void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object) +{ + BLI_uniquename(&tracking->objects, object, "Object", '.', offsetof(MovieTrackingObject, name), sizeof(object->name)); +} + +MovieTrackingObject *BKE_tracking_named_object(MovieTracking *tracking, const char *name) +{ + MovieTrackingObject *object= tracking->objects.first; + + while(object) { + if(!strcmp(object->name, name)) + return object; + + object= object->next; + } + + return NULL; +} diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index ee9cbaf1f81..cd54c944ba9 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -195,8 +195,14 @@ void mul_m3_m3m3(float m1[][3], float m3_[][3], float m2_[][3]) m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2]; } -void mul_m4_m4m3(float (*m1)[4], float (*m3)[4], float (*m2)[3]) +void mul_m4_m4m3(float (*m1)[4], float (*m3_)[4], float (*m2_)[3]) { + float m2[3][3], m3[4][4]; + + /* copy so it works when m1 is the same pointer as m2 or m3 */ + copy_m3_m3(m2, m2_); + copy_m4_m4(m3, m3_); + m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0]; m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1]; m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2]; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8a14e9416df..59a34a706ee 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5969,10 +5969,29 @@ static void lib_link_group(FileData *fd, Main *main) /* ***************** READ MOVIECLIP *************** */ +static void direct_link_movieReconstruction(FileData *fd, MovieTrackingReconstruction *reconstruction) +{ + reconstruction->cameras= newdataadr(fd, reconstruction->cameras); +} + +static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase) +{ + MovieTrackingTrack *track; + + link_list(fd, tracksbase); + + track= tracksbase->first; + while(track) { + track->markers= newdataadr(fd, track->markers); + + track= track->next; + } +} + static void direct_link_movieclip(FileData *fd, MovieClip *clip) { MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *track; + MovieTrackingObject *object; if(fd->movieclipmap) clip->cache= newmclipadr(fd, clip->cache); else clip->cache= NULL; @@ -5980,16 +5999,8 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) if(fd->movieclipmap) clip->tracking.camera.intrinsics= newmclipadr(fd, clip->tracking.camera.intrinsics); else clip->tracking.camera.intrinsics= NULL; - tracking->reconstruction.cameras= newdataadr(fd, tracking->reconstruction.cameras); - - link_list(fd, &tracking->tracks); - - track= tracking->tracks.first; - while(track) { - track->markers= newdataadr(fd, track->markers); - - track= track->next; - } + direct_link_movieTracks(fd, &tracking->tracks); + direct_link_movieReconstruction(fd, &tracking->reconstruction); clip->tracking.act_track= newdataadr(fd, clip->tracking.act_track); @@ -6000,6 +6011,16 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) clip->tracking.stabilization.ok= 0; clip->tracking.stabilization.scaleibuf= NULL; clip->tracking.stabilization.rot_track= newdataadr(fd, clip->tracking.stabilization.rot_track); + + link_list(fd, &tracking->objects); + + object= tracking->objects.first; + while(object) { + direct_link_movieTracks(fd, &object->tracks); + direct_link_movieReconstruction(fd, &object->reconstruction); + + object= object->next; + } } static void lib_link_movieclip(FileData *fd, Main *main) @@ -12773,8 +12794,43 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } { MovieClip *clip; - for(clip= main->movieclip.first; clip; clip= clip->id.next) { + Object *ob; + + for (clip= main->movieclip.first; clip; clip= clip->id.next) { + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object= tracking->objects.first; + clip->proxy.build_tc_flag|= IMB_TC_RECORD_RUN_NO_GAPS; + + if(!tracking->settings.object_distance) + tracking->settings.object_distance= 1.0f; + + if(tracking->objects.first == NULL) + BKE_tracking_new_object(tracking, "Camera"); + + while(tracking_object) { + if(!tracking_object->scale) + tracking_object->scale= 1.0f; + + tracking_object= tracking_object->next; + } + } + + for (ob= main->object.first; ob; ob= ob->id.next) { + bConstraint *con; + for (con= ob->constraints.first; con; con=con->next) { + bConstraintTypeInfo *cti= constraint_get_typeinfo(con); + + if(!cti) + continue; + + if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER) { + bObjectSolverConstraint *data= (bObjectSolverConstraint *)con->data; + + if(data->invmat[3][3]==0.0f) + unit_m4(data->invmat); + } + } } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index e9c14404057..7cde4c8a1e2 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2526,6 +2526,27 @@ static void write_scripts(WriteData *wd, ListBase *idbase) } } +static void write_movieTracks(WriteData *wd, ListBase *tracks) +{ + MovieTrackingTrack *track; + + track= tracks->first; + while(track) { + writestruct(wd, DATA, "MovieTrackingTrack", 1, track); + + if(track->markers) + writestruct(wd, DATA, "MovieTrackingMarker", track->markersnr, track->markers); + + track= track->next; + } +} + +static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction) +{ + if(reconstruction->camnr) + writestruct(wd, DATA, "MovieReconstructedCamera", reconstruction->camnr, reconstruction->cameras); +} + static void write_movieclips(WriteData *wd, ListBase *idbase) { MovieClip *clip; @@ -2534,20 +2555,20 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) while(clip) { if(clip->id.us>0 || wd->current) { MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *track; + MovieTrackingObject *object; writestruct(wd, ID_MC, "MovieClip", 1, clip); - if(tracking->reconstruction.camnr) - writestruct(wd, DATA, "MovieReconstructedCamera", tracking->reconstruction.camnr, tracking->reconstruction.cameras); + write_movieTracks(wd, &tracking->tracks); + write_movieReconstruction(wd, &tracking->reconstruction); - track= tracking->tracks.first; - while(track) { - writestruct(wd, DATA, "MovieTrackingTrack", 1, track); + object= tracking->objects.first; + while(object) { + writestruct(wd, DATA, "MovieTrackingObject", 1, object); - if(track->markers) - writestruct(wd, DATA, "MovieTrackingMarker", track->markersnr, track->markers); + write_movieTracks(wd, &object->tracks); + write_movieReconstruction(wd, &object->reconstruction); - track= track->next; + object= object->next; } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a55c4f2aa0a..fca1591c2ea 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2201,6 +2201,17 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe } uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0, NULL); } + else if(itemptr->type == &RNA_MovieTrackingObject) { + MovieTrackingObject *tracking_object= (MovieTrackingObject*)itemptr->data; + + split= uiLayoutSplit(sub, 0.75f, 0); + if(tracking_object->flag&TRACKING_OBJECT_CAMERA) { + uiItemL(split, name, ICON_CAMERA_DATA); + } + else { + uiItemL(split, name, ICON_OBJECT_DATA); + } + } /* There is a last chance to display custom controls (in addition to the name/label): * If the given item property group features a string property named as prop_list, diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 796ca01a6a9..8266f3501c5 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -408,8 +408,21 @@ static void test_constraints (Object *owner, bPoseChannel *pchan) if((data->flag&CAMERASOLVER_ACTIVECLIP)==0) { if(data->clip != NULL && data->track[0]) { - if (!BKE_tracking_named_track(&data->clip->tracking, data->track)) + MovieTracking *tracking= &data->clip->tracking; + MovieTrackingObject *tracking_object; + + if(data->object[0]) + tracking_object= BKE_tracking_named_object(tracking, data->object); + else + tracking_object= BKE_tracking_get_camera_object(tracking); + + if(!tracking_object) { curcon->flag |= CONSTRAINT_DISABLE; + } + else { + if (!BKE_tracking_named_track(tracking, tracking_object, data->track)) + curcon->flag |= CONSTRAINT_DISABLE; + } } else curcon->flag |= CONSTRAINT_DISABLE; } @@ -420,6 +433,12 @@ static void test_constraints (Object *owner, bPoseChannel *pchan) if((data->flag&CAMERASOLVER_ACTIVECLIP)==0 && data->clip == NULL) curcon->flag |= CONSTRAINT_DISABLE; } + else if (curcon->type == CONSTRAINT_TYPE_OBJECTSOLVER) { + bObjectSolverConstraint *data = curcon->data; + + if((data->flag&CAMERASOLVER_ACTIVECLIP)==0 && data->clip == NULL) + curcon->flag |= CONSTRAINT_DISABLE; + } /* Check targets for constraints */ if (cti && cti->get_constraint_targets) { @@ -684,25 +703,13 @@ void CONSTRAINT_OT_limitdistance_reset (wmOperatorType *ot) /* ------------- Child-Of Constraint ------------------ */ -/* ChildOf Constraint - set inverse callback */ -static int childof_set_inverse_exec (bContext *C, wmOperator *op) +static void child_get_inverse_matrix (Scene *scene, Object *ob, bConstraint *con, float invmat[4][4]) { - Scene *scene= CTX_data_scene(C); - Object *ob = ED_object_active_context(C); - bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF); - bChildOfConstraint *data= (con) ? (bChildOfConstraint *)con->data : NULL; bConstraint *lastcon = NULL; bPoseChannel *pchan= NULL; - /* despite 3 layers of checks, we may still not be able to find a constraint */ - if (data == NULL) { - printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob)? ob->id.name+2 : "<None>"); - BKE_report(op->reports, RPT_ERROR, "Couldn't find constraint data for Child-Of Set Inverse"); - return OPERATOR_CANCELLED; - } - /* nullify inverse matrix first */ - unit_m4(data->invmat); + unit_m4(invmat); /* try to find a pose channel - assume that this is the constraint owner */ // TODO: get from context instead? @@ -748,7 +755,7 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op) */ invert_m4_m4(imat, pchan->pose_mat); mult_m4_m4m4(tmat, pmat, imat); - invert_m4_m4(data->invmat, tmat); + invert_m4_m4(invmat, tmat); /* 5. restore constraints */ pchan->constraints.last = lastcon; @@ -770,9 +777,27 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op) /* use what_does_parent to find inverse - just like for normal parenting */ what_does_parent(scene, ob, &workob); - invert_m4_m4(data->invmat, workob.obmat); + invert_m4_m4(invmat, workob.obmat); + } +} + +/* ChildOf Constraint - set inverse callback */ +static int childof_set_inverse_exec (bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob = ED_object_active_context(C); + bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF); + bChildOfConstraint *data= (con) ? (bChildOfConstraint *)con->data : NULL; + + /* despite 3 layers of checks, we may still not be able to find a constraint */ + if (data == NULL) { + printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob)? ob->id.name+2 : "<None>"); + BKE_report(op->reports, RPT_ERROR, "Couldn't find constraint data for Child-Of Set Inverse"); + return OPERATOR_CANCELLED; } + child_get_inverse_matrix(scene, ob, con, data->invmat); + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); return OPERATOR_FINISHED; @@ -846,6 +871,96 @@ void CONSTRAINT_OT_childof_clear_inverse (wmOperatorType *ot) edit_constraint_properties(ot); } +/* ------------- Object Solver Constraint ------------------ */ + +static int objectsolver_set_inverse_exec (bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + Object *ob = ED_object_active_context(C); + bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER); + bObjectSolverConstraint *data= (con) ? (bObjectSolverConstraint *)con->data : NULL; + + /* despite 3 layers of checks, we may still not be able to find a constraint */ + if (data == NULL) { + printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob)? ob->id.name+2 : "<None>"); + BKE_report(op->reports, RPT_ERROR, "Couldn't find constraint data for Child-Of Set Inverse"); + return OPERATOR_CANCELLED; + } + + child_get_inverse_matrix(scene, ob, con, data->invmat); + + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); + + return OPERATOR_FINISHED; +} + +static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + if (edit_constraint_invoke_properties(C, op)) + return objectsolver_set_inverse_exec(C, op); + else + return OPERATOR_CANCELLED; +} + +void CONSTRAINT_OT_objectsolver_set_inverse (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Set Inverse"; + ot->idname= "CONSTRAINT_OT_objectsolver_set_inverse"; + ot->description= "Set inverse correction for ObjectSolver constraint"; + + ot->exec= objectsolver_set_inverse_exec; + ot->invoke= objectsolver_set_inverse_invoke; + ot->poll= edit_constraint_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + edit_constraint_properties(ot); +} + +static int objectsolver_clear_inverse_exec (bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER); + bObjectSolverConstraint *data= (con) ? (bObjectSolverConstraint *)con->data : NULL; + + if(data==NULL) { + BKE_report(op->reports, RPT_ERROR, "Childof constraint not found"); + return OPERATOR_CANCELLED; + } + + /* simply clear the matrix */ + unit_m4(data->invmat); + + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); + + return OPERATOR_FINISHED; +} + +static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + if (edit_constraint_invoke_properties(C, op)) + return objectsolver_clear_inverse_exec(C, op); + else + return OPERATOR_CANCELLED; +} + +void CONSTRAINT_OT_objectsolver_clear_inverse (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Clear Inverse"; + ot->idname= "CONSTRAINT_OT_objectsolver_clear_inverse"; + ot->description= "Clear inverse correction for ObjectSolver constraint"; + + ot->exec= objectsolver_clear_inverse_exec; + ot->invoke= objectsolver_clear_inverse_invoke; + ot->poll= edit_constraint_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + edit_constraint_properties(ot); +} + /***************************** BUTTONS ****************************/ void ED_object_constraint_set_active(Object *ob, bConstraint *con) diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 35e802e3e11..8973fb88c85 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -186,6 +186,8 @@ void CONSTRAINT_OT_stretchto_reset(struct wmOperatorType *ot); void CONSTRAINT_OT_limitdistance_reset(struct wmOperatorType *ot); void CONSTRAINT_OT_childof_set_inverse(struct wmOperatorType *ot); void CONSTRAINT_OT_childof_clear_inverse(struct wmOperatorType *ot); +void CONSTRAINT_OT_objectsolver_set_inverse(struct wmOperatorType *ot); +void CONSTRAINT_OT_objectsolver_clear_inverse (struct wmOperatorType *ot); /* object_vgroup.c */ void OBJECT_OT_vertex_group_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index a899d60c2ab..acc318723d8 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -161,6 +161,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset); WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse); WM_operatortype_append(CONSTRAINT_OT_childof_clear_inverse); + WM_operatortype_append(CONSTRAINT_OT_objectsolver_set_inverse); + WM_operatortype_append(CONSTRAINT_OT_objectsolver_clear_inverse); WM_operatortype_append(OBJECT_OT_vertex_group_add); WM_operatortype_append(OBJECT_OT_vertex_group_remove); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 3f9ec3f3c82..ca2646e9967 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -96,6 +96,8 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc float x; int *points, totseg, i, a; float sfra= SFRA, efra= EFRA, framelen= ar->winx/(efra-sfra+1); + MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking); + MovieTrackingReconstruction *reconstruction= BKE_tracking_get_reconstruction(&clip->tracking); glEnable(GL_BLEND); @@ -119,8 +121,8 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc } /* track */ - if(clip->tracking.act_track) { - MovieTrackingTrack *track= clip->tracking.act_track; + if(act_track) { + MovieTrackingTrack *track= act_track; for(i= sfra, a= 0; i <= efra; i++) { int framenr; @@ -152,9 +154,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc } /* failed frames */ - if(clip->tracking.reconstruction.flag&TRACKING_RECONSTRUCTED) { - int n= clip->tracking.reconstruction.camnr; - MovieReconstructedCamera *cameras= clip->tracking.reconstruction.cameras; + if(reconstruction->flag&TRACKING_RECONSTRUCTED) { + int n= reconstruction->camnr; + MovieReconstructedCamera *cameras= reconstruction->cameras; glColor4ub(255, 0, 0, 96); @@ -835,8 +837,9 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, { float x, y; MovieTracking* tracking= &clip->tracking; - MovieTrackingMarker *marker; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track, *act_track; + MovieTrackingMarker *marker; int framenr= sc->user.framenr; int undistort= sc->user.render_flag&MCLIP_PROXY_RENDER_UNDISTORT; float *marker_pos= NULL, *fp, *active_pos= NULL, cur_pos[2]; @@ -858,13 +861,13 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, glMultMatrixf(sc->stabmat); glScalef(width, height, 0); - act_track= clip->tracking.act_track; + act_track= BKE_tracking_active_track(tracking); if(sc->user.render_flag&MCLIP_PROXY_RENDER_UNDISTORT) { int count= 0; /* count */ - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if((track->flag&TRACK_HIDDEN)==0) { marker= BKE_tracking_get_marker(track, framenr); @@ -880,7 +883,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, if(count) { marker_pos= MEM_callocN(2*sizeof(float)*count, "draw_tracking_tracks marker_pos"); - track= tracking->tracks.first; + track= tracksbase->first; fp= marker_pos; while(track) { if((track->flag&TRACK_HIDDEN)==0) { @@ -902,7 +905,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, } if(sc->flag&SC_SHOW_TRACK_PATH) { - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if((track->flag&TRACK_HIDDEN)==0) draw_track_path(sc, clip, track); @@ -912,7 +915,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, } /* markers outline and non-selected areas */ - track= tracking->tracks.first; + track= tracksbase->first; fp= marker_pos; while(track) { if((track->flag&TRACK_HIDDEN)==0) { @@ -936,7 +939,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, /* selected areas only, so selection wouldn't be overlapped by non-selected areas */ - track= tracking->tracks.first; + track= tracksbase->first; fp= marker_pos; while(track) { if((track->flag&TRACK_HIDDEN)==0) { @@ -974,15 +977,16 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, } if(sc->flag&SC_SHOW_BUNDLES) { + MovieTrackingObject *object= BKE_tracking_active_object(tracking); float pos[4], vec[4], mat[4][4], aspy; glEnable(GL_POINT_SMOOTH); glPointSize(3.0f); aspy= 1.0f/clip->tracking.camera.pixel_aspect; - BKE_tracking_projection_matrix(tracking, framenr, width, height, mat); + BKE_tracking_projection_matrix(tracking, object, framenr, width, height, mat); - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if((track->flag&TRACK_HIDDEN)==0 && track->flag&TRACK_HAS_BUNDLE) { marker= BKE_tracking_get_marker(track, framenr); @@ -1027,7 +1031,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, if(sc->flag&SC_SHOW_NAMES) { /* scaling should be cleared before drawing texts, otherwise font would also be scaled */ - track= tracking->tracks.first; + track= tracksbase->first; fp= marker_pos; while(track) { if((track->flag&TRACK_HIDDEN)==0) { diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index c5036145792..d75df0ab51e 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -171,12 +171,13 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) MovieClip *clip= ED_space_clip(sc); MovieTrackingTrack *track; int width, height, ok= 0; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); INIT_MINMAX2(min, max); ED_space_clip_size(sc, &width, &height); - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) { MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr); diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 5a904e0e9b6..9aba6db0c80 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -177,6 +177,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc) { MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); int width, height; struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } userdata; @@ -188,13 +189,13 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc) /* non-selected knot handles */ userdata.hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); userdata.sel= 0; - userdata.act_track= clip->tracking.act_track; + userdata.act_track= act_track; UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale); clip_graph_tracking_values_iterate(sc, &userdata, tracking_segment_knot_cb, NULL, NULL); /* draw graph lines */ glEnable(GL_BLEND); - clip_graph_tracking_values_iterate(sc, tracking->act_track, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb); + clip_graph_tracking_values_iterate(sc, act_track, tracking_segment_point_cb, tracking_segment_start_cb, tracking_segment_end_cb); glDisable(GL_BLEND); /* selected knot handles on top of curves */ @@ -206,7 +207,7 @@ static void draw_frame_curves(SpaceClip *sc) { MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; - MovieTrackingReconstruction *reconstruction= &tracking->reconstruction; + MovieTrackingReconstruction *reconstruction= BKE_tracking_get_reconstruction(tracking); int i, lines= 0, prevfra= 0; glColor3f(0.0f, 0.0f, 1.0f); diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 56ca1632bae..08d6bcf47bc 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -155,13 +155,14 @@ static int mouse_select_knot(bContext *C, float co[2], int extend) ARegion *ar= CTX_wm_region(C); View2D *v2d= &ar->v2d; MovieTracking *tracking= &clip->tracking; + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); static const int delta= 6; - if(tracking->act_track) { + if(act_track) { MouseSelectUserData userdata; mouse_select_init_data(&userdata, co); - clip_graph_tracking_values_iterate_track(sc, tracking->act_track, + clip_graph_tracking_values_iterate_track(sc, act_track, &userdata, find_nearest_tracking_knot_cb, NULL, NULL); if(userdata.marker) { @@ -191,6 +192,7 @@ static int mouse_select_curve(bContext *C, float co[2], int extend) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); MouseSelectUserData userdata; mouse_select_init_data(&userdata, co); @@ -198,12 +200,12 @@ static int mouse_select_curve(bContext *C, float co[2], int extend) if(userdata.track) { if(extend) { - if(tracking->act_track==userdata.track) { + if(act_track==userdata.track) { /* currently only single curve can be selected (selected curve represents active track) */ - tracking->act_track= NULL; + act_track= NULL; } } - else if(tracking->act_track!=userdata.track) { + else if(act_track!=userdata.track) { MovieTrackingMarker *marker; SelectUserData selectdata = {SEL_DESELECT}; @@ -292,9 +294,11 @@ static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op)) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); - if(tracking->act_track) - clip_delete_track(C, clip, tracking->act_track); + if(act_track) + clip_delete_track(C, clip, tracksbase, act_track); return OPERATOR_FINISHED; } @@ -322,16 +326,17 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op)) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); - if(tracking->act_track) { + if(act_track) { int a= 0; - MovieTrackingTrack *track= tracking->act_track; - while(a<track->markersnr) { - MovieTrackingMarker *marker= &track->markers[a]; + while(a<act_track->markersnr) { + MovieTrackingMarker *marker= &act_track->markers[a]; if(marker->flag&MARKER_GRAPH_SEL) - clip_delete_marker(C, clip, track, marker); + clip_delete_marker(C, clip, tracksbase, act_track, marker); else a++; } diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index da0b589652e..64881499a31 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -92,8 +92,8 @@ void clip_graph_tracking_values_iterate(struct SpaceClip *sc, void *userdata, void clip_graph_tracking_iterate(struct SpaceClip *sc, void *userdata, void (*func) (void *userdata, struct MovieTrackingMarker *marker)); -void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track); -void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker); +void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track); +void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker); void clip_view_center_to_point(struct SpaceClip *sc, float x, float y); @@ -124,6 +124,7 @@ void CLIP_OT_set_origin(struct wmOperatorType *ot); void CLIP_OT_set_floor(struct wmOperatorType *ot); void CLIP_OT_set_axis(struct wmOperatorType *ot); void CLIP_OT_set_scale(struct wmOperatorType *ot); +void CLIP_OT_set_solution_scale(struct wmOperatorType *ot); void CLIP_OT_set_center_principal(struct wmOperatorType *ot); @@ -139,6 +140,9 @@ void CLIP_OT_stabilize_2d_remove(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_select(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_set_rotation(struct wmOperatorType *ot); -void CLIP_OT_clean_tracks(wmOperatorType *ot); +void CLIP_OT_clean_tracks(struct wmOperatorType *ot); + +void CLIP_OT_tracking_object_new(struct wmOperatorType *ot); +void CLIP_OT_tracking_object_remove(struct wmOperatorType *ot); #endif /* ED_CLIP_INTERN_H */ diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 649b278ab3d..3ca8fc35c7f 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -119,9 +119,10 @@ void clip_graph_tracking_values_iterate(SpaceClip *sc, void *userdata, { MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) { clip_graph_tracking_values_iterate_track(sc, track, userdata, func, segment_start, segment_end); @@ -136,9 +137,10 @@ void clip_graph_tracking_iterate(SpaceClip *sc, void *userdata, { MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) { int i; @@ -158,14 +160,15 @@ void clip_graph_tracking_iterate(SpaceClip *sc, void *userdata, } } -void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) +void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, MovieTrackingTrack *track) { MovieTracking *tracking= &clip->tracking; MovieTrackingStabilization *stab= &tracking->stabilization; + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); int has_bundle= 0, update_stab= 0; - if(track==tracking->act_track) + if(track==act_track) tracking->act_track= NULL; if(track==stab->rot_track) { @@ -179,7 +182,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) has_bundle= 1; BKE_tracking_free_track(track); - BLI_freelinkN(&tracking->tracks, track); + BLI_freelinkN(tracksbase, track); WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); @@ -194,10 +197,10 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, NULL); } -void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker) +void clip_delete_marker(bContext *C, MovieClip *clip, ListBase *tracksbase, MovieTrackingTrack *track, MovieTrackingMarker *marker) { if(track->markersnr==1) { - clip_delete_track(C, clip, track); + clip_delete_track(C, clip, tracksbase, track); } else { BKE_tracking_delete_marker(track, marker->framenr); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index c8577f7760e..5291121571c 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -351,6 +351,7 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_set_floor); WM_operatortype_append(CLIP_OT_set_axis); WM_operatortype_append(CLIP_OT_set_scale); + WM_operatortype_append(CLIP_OT_set_solution_scale); /* detect */ WM_operatortype_append(CLIP_OT_detect_features); @@ -372,6 +373,10 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_graph_select); WM_operatortype_append(CLIP_OT_graph_delete_curve); WM_operatortype_append(CLIP_OT_graph_delete_knot); + + /* object tracking */ + WM_operatortype_append(CLIP_OT_tracking_object_new); + WM_operatortype_append(CLIP_OT_tracking_object_remove); } static void clip_keymap(struct wmKeyConfig *keyconf) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index d911e68236b..3f20ab9ea30 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -32,6 +32,7 @@ #include "MEM_guardedalloc.h" #include "DNA_camera_types.h" +#include "DNA_constraint_types.h" #include "DNA_gpencil_types.h" #include "DNA_movieclip_types.h" #include "DNA_object_types.h" /* SELECT */ @@ -45,6 +46,7 @@ #include "BKE_main.h" #include "BKE_context.h" +#include "BKE_constraint.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" #include "BKE_global.h" @@ -90,41 +92,21 @@ static int space_clip_frame_poll(bContext *C) return 0; } -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 && sc->clip && scene->camera) - return 1; - - return 0; -} - /********************** add marker operator *********************/ static void add_marker(SpaceClip *sc, float x, float y) { MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; int width, height; ED_space_clip_size(sc, &width, &height); - track= BKE_tracking_add_track(&clip->tracking, x, y, sc->user.framenr, width, height); + track= BKE_tracking_add_track(tracking, tracksbase, x, y, sc->user.framenr, width, height); - BKE_tracking_select_track(&clip->tracking, track, TRACK_AREA_ALL, 0); + BKE_tracking_select_track(tracksbase, track, TRACK_AREA_ALL, 0); clip->tracking.act_track= track; } @@ -191,13 +173,14 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op)) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *track= tracking->tracks.first, *next; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *track= tracksbase->first, *next; while(track) { next= track->next; if(TRACK_VIEW_SELECTED(sc, track)) - clip_delete_track(C, clip, track); + clip_delete_track(C, clip, tracksbase, track); track= next; } @@ -230,7 +213,8 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); - MovieTrackingTrack *track= clip->tracking.tracks.first, *next; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); + MovieTrackingTrack *track= tracksbase->first, *next; int framenr= sc->user.framenr; int has_selection= 0; @@ -243,7 +227,7 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op)) if(marker) { has_selection|= track->markersnr>1; - clip_delete_marker(C, clip, track, marker); + clip_delete_marker(C, clip, tracksbase, track, marker); } } @@ -429,6 +413,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) int width, height; float co[2]; void *customdata= NULL; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); ED_space_clip_size(sc, &width, &height); @@ -437,7 +422,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) ED_clip_mouse_pos(C, event, co); - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) { MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr); @@ -721,12 +706,12 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2]) return MIN4(d1, d2, d3, d4); } -static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, MovieClip *clip, float co[2]) +static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2]) { MovieTrackingTrack *track= NULL, *cur; float mindist= 0.0f; - cur= clip->tracking.tracks.first; + cur= tracksbase->first; while(cur) { MovieTrackingMarker *marker= BKE_tracking_get_marker(cur, sc->user.framenr); @@ -764,10 +749,11 @@ static int mouse_select(bContext *C, float co[2], int extend) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *act_track= tracking->act_track; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); MovieTrackingTrack *track= NULL; /* selected marker */ - track= find_nearest_track(sc, clip, co); + track= find_nearest_track(sc, tracksbase, co); if(track) { int area= track_mouse_area(sc, co, track); @@ -784,7 +770,7 @@ static int mouse_select(bContext *C, float co[2], int extend) if(area==TRACK_AREA_POINT) area= TRACK_AREA_ALL; - BKE_tracking_select_track(tracking, track, area, extend); + BKE_tracking_select_track(tracksbase, track, area, extend); clip->tracking.act_track= track; } } @@ -867,6 +853,7 @@ static int border_select_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTrackingTrack *track; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); rcti rect; rctf rectf; int change= 0, mode, extend; @@ -884,7 +871,7 @@ static int border_select_exec(bContext *C, wmOperator *op) extend= RNA_boolean_get(op->ptr, "extend"); /* do actual selection */ - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if((track->flag&TRACK_HIDDEN)==0) { MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr); @@ -952,6 +939,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) MovieClip *clip= ED_space_clip(sc); ARegion *ar= CTX_wm_region(C); MovieTrackingTrack *track; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); int x, y, radius, width, height, mode, change= 0; float zoomx, zoomy, offset[2], ellipse[2]; @@ -972,7 +960,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) ED_clip_point_stable_pos(C, x, y, &offset[0], &offset[1]); /* do selection */ - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if((track->flag&TRACK_HIDDEN)==0) { MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr); @@ -1026,13 +1014,14 @@ static int select_all_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTrackingTrack *track= NULL; /* selected track */ + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); int action= RNA_enum_get(op->ptr, "action"); int framenr= sc->user.framenr; int has_selection= 0; if(action == SEL_TOGGLE){ action= SEL_SELECT; - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) { action= SEL_DESELECT; @@ -1043,7 +1032,7 @@ static int select_all_exec(bContext *C, wmOperator *op) } } - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if((track->flag&TRACK_HIDDEN)==0) { MovieTrackingMarker *marker= BKE_tracking_get_marker(track, framenr); @@ -1108,9 +1097,11 @@ static int select_groped_exec(bContext *C, wmOperator *op) MovieClip *clip= ED_space_clip(sc); MovieTrackingTrack *track; MovieTrackingMarker *marker; + MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); int group= RNA_enum_get(op->ptr, "group"); - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { int ok= 0; @@ -1132,11 +1123,13 @@ static int select_groped_exec(bContext *C, wmOperator *op) ok= marker->flag&MARKER_DISABLED; } else if(group==5) { /* color */ - if(clip->tracking.act_track) { - ok= (track->flag&TRACK_CUSTOMCOLOR) == (clip->tracking.act_track->flag&TRACK_CUSTOMCOLOR); + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); + + if(act_track) { + ok= (track->flag&TRACK_CUSTOMCOLOR) == (act_track->flag&TRACK_CUSTOMCOLOR); if(ok && track->flag&TRACK_CUSTOMCOLOR) - ok= equals_v3v3(track->color, clip->tracking.act_track->color); + ok= equals_v3v3(track->color, act_track->color); } } else if(group==6) { /* failed */ @@ -1208,10 +1201,11 @@ static int track_markers_testbreak(void) static int track_count_markers(SpaceClip *sc, MovieClip *clip) { int tot= 0; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; int framenr= sc->user.framenr; - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) { MovieTrackingMarker *marker= BKE_tracking_exact_marker(track, framenr); @@ -1228,6 +1222,7 @@ static int track_count_markers(SpaceClip *sc, MovieClip *clip) static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit_r) { + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; int framenr= sc->user.framenr, hidden= 0; int frames_limit= 0; @@ -1235,7 +1230,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit if((sc->flag&SC_SHOW_MARKER_PATTERN)==0) hidden|= TRACK_AREA_PAT; if((sc->flag&SC_SHOW_MARKER_SEARCH)==0) hidden|= TRACK_AREA_SEARCH; - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(hidden) BKE_tracking_track_flag(track, hidden, SELECT, 1); @@ -1448,6 +1443,11 @@ static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve int backwards= RNA_boolean_get(op->ptr, "backwards"); int sequence= RNA_boolean_get(op->ptr, "sequence"); + if(WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C))) { + /* only one tracking is allowed at a time */ + return OPERATOR_CANCELLED; + } + if(clip->tracking_context) return OPERATOR_CANCELLED; @@ -1546,9 +1546,10 @@ static int solve_camera_initjob(bContext *C, SolveCameraJob *scj, wmOperator *op Scene *scene= CTX_data_scene(C); MovieTracking *tracking= &clip->tracking; MovieTrackingSettings *settings= &clip->tracking.settings; + MovieTrackingObject *object= BKE_tracking_active_object(tracking); int width, height; - if(!BKE_tracking_can_reconstruct(tracking, error_msg, max_error)) + if(!BKE_tracking_can_reconstruct(tracking, object, error_msg, max_error)) return 0; /* could fail if footage uses images with different sizes */ @@ -1559,7 +1560,7 @@ static int solve_camera_initjob(bContext *C, SolveCameraJob *scj, wmOperator *op scj->reports= op->reports; scj->user= sc->user; - scj->context= BKE_tracking_reconstruction_context_new(tracking, + scj->context= BKE_tracking_reconstruction_context_new(tracking, object, settings->keyframe1, settings->keyframe2, width, height); tracking->stats= MEM_callocN(sizeof(MovieTrackingStats), "solve camera stats"); @@ -1670,9 +1671,15 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + MovieTrackingReconstruction *reconstruction= BKE_tracking_get_reconstruction(tracking); wmJob *steve; char error_msg[256]= "\0"; + if(WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C))) { + /* only one solve is allowed at a time */ + return OPERATOR_CANCELLED; + } + scj= MEM_callocN(sizeof(SolveCameraJob), "SolveCameraJob data"); if(!solve_camera_initjob(C, scj, op, error_msg, sizeof(error_msg))) { if(error_msg[0]) @@ -1686,7 +1693,7 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even BLI_strncpy(tracking->stats->message, "Solving camera | Preparing solve", sizeof(tracking->stats->message)); /* hide reconstruction statistics from previous solve */ - clip->tracking.reconstruction.flag&= ~TRACKING_RECONSTRUCTED; + reconstruction->flag&= ~TRACKING_RECONSTRUCTED; WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); /* setup job */ @@ -1746,7 +1753,9 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op)) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *track= tracking->tracks.first; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); + MovieTrackingReconstruction *reconstruction= BKE_tracking_get_reconstruction(tracking); + MovieTrackingTrack *track= tracksbase->first; while(track) { track->flag&= ~TRACK_HAS_BUNDLE; @@ -1754,13 +1763,13 @@ static int clear_solution_exec(bContext *C, wmOperator *UNUSED(op)) track= track->next; } - if(tracking->reconstruction.cameras) - MEM_freeN(tracking->reconstruction.cameras); + if(reconstruction->cameras) + MEM_freeN(reconstruction->cameras); - tracking->reconstruction.cameras= NULL; - tracking->reconstruction.camnr= 0; + reconstruction->cameras= NULL; + reconstruction->camnr= 0; - tracking->reconstruction.flag&= ~TRACKING_RECONSTRUCTED; + reconstruction->flag&= ~TRACKING_RECONSTRUCTED; DAG_id_tag_update(&clip->id, 0); @@ -1792,9 +1801,10 @@ static int clear_track_path_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTrackingTrack *track; + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); int action= RNA_enum_get(op->ptr, "action"); - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) BKE_tracking_clear_path(track, sc->user.framenr, action); @@ -1839,7 +1849,8 @@ static int disable_markers_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *track= tracking->tracks.first; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *track= tracksbase->first; int action= RNA_enum_get(op->ptr, "action"); while(track) { @@ -1888,14 +1899,80 @@ void CLIP_OT_disable_markers(wmOperatorType *ot) /********************** set origin operator *********************/ +static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip) +{ + Object *camera= scene->camera; + Base *base; + + if(camera && object_get_movieclip(scene, camera, 0)==clip) + return camera; + + base= scene->base.first; + while(base) { + if(base->object->type == OB_CAMERA) { + if(object_get_movieclip(scene, base->object, 0)==clip) { + camera= base->object; + break; + } + } + + base= base->next; + } + + return camera; +} + +static Object *get_orientation_object(bContext *C) +{ + Scene *scene= CTX_data_scene(C); + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object= BKE_tracking_active_object(tracking); + Object *object= NULL; + + if(tracking_object->flag&TRACKING_OBJECT_CAMERA) { + object= get_camera_with_movieclip(scene, clip); + } + else { + object= OBACT; + } + + if(object && object->parent) + object= object->parent; + + return object; +} + +static int set_orientation_poll(bContext *C) +{ + if(space_clip_frame_poll(C)) { + Scene *scene= CTX_data_scene(C); + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object= BKE_tracking_active_object(tracking); + + if(tracking_object->flag&TRACKING_OBJECT_CAMERA) { + return 1; + } + else { + return OBACT != NULL; + } + } + + return 0; +} + static int count_selected_bundles(bContext *C) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; int tot= 0; - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_HAS_BUNDLE)) tot++; @@ -1906,38 +1983,115 @@ static int count_selected_bundles(bContext *C) return tot; } +static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat[4][4]) +{ + bConstraint *con; + int found= 0; + + for (con= ob->constraints.first; con; con=con->next) { + bConstraintTypeInfo *cti= constraint_get_typeinfo(con); + + if(!cti) + continue; + + if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER) { + bObjectSolverConstraint *data= (bObjectSolverConstraint *)con->data; + + if(!found) { + Object *cam= data->camera ? data->camera : scene->camera; + + where_is_object_mat(scene, cam, invmat); + } + + mult_m4_m4m4(invmat, invmat, data->invmat); + + found= 1; + } + } + + if(found) + invert_m4(invmat); + else + unit_m4(invmat); +} + +static Object *object_solver_camera(Scene *scene, Object *ob) +{ + bConstraint *con; + + for (con= ob->constraints.first; con; con=con->next) { + bConstraintTypeInfo *cti= constraint_get_typeinfo(con); + + if(!cti) + continue; + + if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER) { + bObjectSolverConstraint *data= (bObjectSolverConstraint *)con->data; + + return data->camera ? data->camera : scene->camera; + } + } + + return NULL; +} + static int set_origin_exec(bContext *C, wmOperator *op) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; MovieTrackingTrack *track; + MovieTrackingObject *tracking_object; Scene *scene= CTX_data_scene(C); - Object *parent= scene->camera; - float mat[4][4], vec[3]; + Object *object; + Object *camera= get_camera_with_movieclip(scene, clip); + ListBase *tracksbase; + float mat[4][4], vec[3], median[3]; + int selected_count= count_selected_bundles(C); + + if(selected_count==0) { + BKE_report(op->reports, RPT_ERROR, "At least one track with bundle should be selected to define origin position"); + + return OPERATOR_CANCELLED; + } + + object= get_orientation_object(C); + if(!object) { + BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on"); - if(count_selected_bundles(C)!=1) { - BKE_report(op->reports, RPT_ERROR, "Track with bundle should be selected to define origin position"); return OPERATOR_CANCELLED; } - if(scene->camera->parent) - parent= scene->camera->parent; + tracking_object= BKE_tracking_active_object(tracking); + + tracksbase= BKE_tracking_object_tracks(tracking, tracking_object); - track= clip->tracking.tracks.first; + track= tracksbase->first; + zero_v3(median); while(track) { - if(TRACK_VIEW_SELECTED(sc, track)) - break; + if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_HAS_BUNDLE)) { + add_v3_v3(median, track->bundle_pos); + } track= track->next; } + mul_v3_fl(median, 1.0f/selected_count); - BKE_get_tracking_mat(scene, NULL, mat); - mul_v3_m4v3(vec, mat, track->bundle_pos); + BKE_get_tracking_mat(scene, camera, mat); - sub_v3_v3(parent->loc, vec); + mul_v3_m4v3(vec, mat, median); + + if(tracking_object->flag&TRACKING_OBJECT_CAMERA) { + sub_v3_v3(object->loc, vec); + } + else { + object_solver_inverted_matrix(scene, object, mat); + mul_v3_m4v3(vec, mat, vec); + copy_v3_v3(object->loc, vec); + } DAG_id_tag_update(&clip->id, 0); - DAG_id_tag_update(&parent->id, OB_RECALC_OB); + DAG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); @@ -1954,20 +2108,42 @@ void CLIP_OT_set_origin(wmOperatorType *ot) /* api callbacks */ ot->exec= set_origin_exec; - ot->poll= space_clip_frame_camera_poll; + ot->poll= set_orientation_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "use_median", 0, "Use Median", "Set origin to median point of selected bundles"); } /********************** set floor operator *********************/ -static void set_axis(Scene *scene, Object *ob, MovieTrackingTrack *track, char axis) +static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingObject *tracking_object, + MovieTrackingTrack *track, char axis) { - float mat[4][4], vec[3], obmat[4][4]; + Object *camera= get_camera_with_movieclip(scene, clip); + int is_camera= tracking_object->flag&TRACKING_OBJECT_CAMERA; + int flip= 0; + float mat[4][4], vec[3], obmat[4][4], dvec[3]; + + object_to_mat4(ob, obmat); - BKE_get_tracking_mat(scene, NULL, mat); + BKE_get_tracking_mat(scene, camera, mat); mul_v3_m4v3(vec, mat, track->bundle_pos); + copy_v3_v3(dvec, vec); + + if(!is_camera) { + float imat[4][4]; + + object_solver_inverted_matrix(scene, ob, imat); + mul_v3_m4v3(vec, imat, vec); + + invert_m4_m4(imat, obmat); + mul_v3_m4v3(dvec, imat, vec); + + sub_v3_v3(vec, obmat[3]); + } if(len_v2(vec) < 1e-3f) return; @@ -1975,26 +2151,48 @@ static void set_axis(Scene *scene, Object *ob, MovieTrackingTrack *track, char unit_m4(mat); if(axis=='X') { - if(fabsf(vec[1])<1e-3f) { + if(fabsf(dvec[1])<1e-3f) { + flip= 1; + mat[0][0]= -1.0f; mat[0][1]= 0.0f; mat[0][2]= 0.0f; mat[1][0]= 0.0f; mat[1][1]= -1.0f; mat[1][2]= 0.0f; mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f; } else { copy_v3_v3(mat[0], vec); - mat[0][2]= 0.0f; - mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f; - cross_v3_v3v3(mat[1], mat[2], mat[0]); + + if(is_camera || fabsf(vec[2])<1e-3f) { + mat[0][2]= 0.0f; + mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f; + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + else { + vec[2]= 0.0f; + + cross_v3_v3v3(mat[1], mat[0], vec); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } } } else { - if(fabsf(vec[0])<1e-3f) { + if(fabsf(dvec[0])<1e-3f) { + flip= 1; + mat[0][0]= -1.0f; mat[0][1]= 0.0f; mat[0][2]= 0.0f; mat[1][0]= 0.0f; mat[1][1]= -1.0f; mat[1][2]= 0.0f; mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f; } else { copy_v3_v3(mat[1], vec); - mat[1][2]= 0.0f; - mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f; - cross_v3_v3v3(mat[0], mat[1], mat[2]); + + if(is_camera || fabsf(vec[2])<1e-3f) { + mat[1][2]= 0.0f; + mat[2][0]= 0.0f; mat[2][1]= 0.0f; mat[2][2]= 1.0f; + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } + else { + vec[2]= 0.0f; + + cross_v3_v3v3(mat[0], vec, mat[1]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } } } @@ -2002,10 +2200,30 @@ static void set_axis(Scene *scene, Object *ob, MovieTrackingTrack *track, char normalize_v3(mat[1]); normalize_v3(mat[2]); - invert_m4(mat); + if(is_camera) { + invert_m4(mat); + + mult_m4_m4m4(mat, mat, obmat); + } + else { + if(!flip) { + float lmat[4][4], ilmat[4][4], rmat[3][3]; + + object_rot_to_mat3(ob, rmat); + invert_m3(rmat); + mul_m4_m4m3(mat, mat, rmat); + + unit_m4(lmat); + copy_v3_v3(lmat[3], obmat[3]); + invert_m4_m4(ilmat, lmat); + + mul_serie_m4(mat, lmat, mat, ilmat, obmat, NULL, NULL, NULL, NULL); + } + else { + mult_m4_m4m4(mat, obmat, mat); + } + } - object_to_mat4(ob, obmat); - mult_m4_m4m4(mat, mat, obmat); object_apply_mat4(ob, mat, 0, 0); } @@ -2014,9 +2232,12 @@ 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, *axis_track= NULL; - Object *camera= scene->camera; - Object *parent= camera; + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object; + MovieTrackingTrack *track, *axis_track= NULL, *act_track; + ListBase *tracksbase; + Object *object; + Object *camera= get_camera_with_movieclip(scene, clip); int tot= 0; float vec[3][3], mat[4][4], obmat[4][4], newmat[4][4], orig[3]= {0.0f, 0.0f, 0.0f}; float rot[4][4]={{0.0f, 0.0f, -1.0f, 0.0f}, @@ -2026,21 +2247,30 @@ static int set_floor_exec(bContext *C, wmOperator *op) if(count_selected_bundles(C)!=3) { BKE_report(op->reports, RPT_ERROR, "Three tracks with bundles are needed to orient the floor"); + return OPERATOR_CANCELLED; } - if(scene->camera->parent) - parent= scene->camera->parent; + tracking_object= BKE_tracking_active_object(tracking); + tracksbase= BKE_tracking_object_tracks(tracking, tracking_object); + act_track= BKE_tracking_active_track(tracking); + + object= get_orientation_object(C); + if(!object) { + BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on"); + + return OPERATOR_CANCELLED; + } - BKE_get_tracking_mat(scene, NULL, mat); + BKE_get_tracking_mat(scene, camera, mat); /* get 3 bundles to use as reference */ - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track && tot<3) { if(track->flag&TRACK_HAS_BUNDLE && TRACK_VIEW_SELECTED(sc, track)) { mul_v3_m4v3(vec[tot], mat, track->bundle_pos); - if(tot==0 || track==clip->tracking.act_track) + if(tot==0 || track==act_track) copy_v3_v3(orig, vec[tot]); else axis_track= track; @@ -2070,25 +2300,30 @@ static int set_floor_exec(bContext *C, wmOperator *op) mat[3][1]= orig[1]; mat[3][2]= orig[2]; - invert_m4(mat); + if(tracking_object->flag&TRACKING_OBJECT_CAMERA) { + invert_m4(mat); - object_to_mat4(parent, obmat); - mult_m4_m4m4(mat, mat, obmat); - mult_m4_m4m4(newmat, rot, mat); - object_apply_mat4(parent, newmat, 0, 0); - - /* make camera have positive z-coordinate */ - if(parent->loc[2]<0) { - invert_m4(rot); + object_to_mat4(object, obmat); + mult_m4_m4m4(mat, mat, obmat); mult_m4_m4m4(newmat, rot, mat); - object_apply_mat4(parent, newmat, 0, 0); + object_apply_mat4(object, newmat, 0, 0); + + /* make camera have positive z-coordinate */ + if(object->loc[2]<0) { + invert_m4(rot); + mult_m4_m4m4(newmat, rot, mat); + object_apply_mat4(object, newmat, 0, 0); + } + } + else { + object_apply_mat4(object, mat, 0, 0); } - where_is_object(scene, parent); - set_axis(scene, parent, axis_track, 'X'); + where_is_object(scene, object); + set_axis(scene, object, clip, tracking_object, axis_track, 'X'); DAG_id_tag_update(&clip->id, 0); - DAG_id_tag_update(&parent->id, OB_RECALC_OB); + DAG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); @@ -2105,7 +2340,7 @@ void CLIP_OT_set_floor(wmOperatorType *ot) /* api callbacks */ ot->exec= set_floor_exec; - ot->poll= space_clip_camera_poll; + ot->poll= set_orientation_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -2117,9 +2352,12 @@ static int set_axis_exec(bContext *C, wmOperator *op) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object= BKE_tracking_active_object(tracking); MovieTrackingTrack *track; Scene *scene= CTX_data_scene(C); - Object *parent= scene->camera; + Object *object; + ListBase *tracksbase; int axis= RNA_enum_get(op->ptr, "axis"); if(count_selected_bundles(C)!=1) { @@ -2128,10 +2366,16 @@ static int set_axis_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if(scene->camera->parent) - parent= scene->camera->parent; + object= get_orientation_object(C); + if(!object) { + BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on"); + + return OPERATOR_CANCELLED; + } + + tracksbase= BKE_tracking_object_tracks(tracking, tracking_object); - track= clip->tracking.tracks.first; + track=tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) break; @@ -2139,10 +2383,10 @@ static int set_axis_exec(bContext *C, wmOperator *op) track= track->next; } - set_axis(scene, parent, track, axis==0?'X':'Y'); + set_axis(scene, object, clip, tracking_object, track, axis==0?'X':'Y'); DAG_id_tag_update(&clip->id, 0); - DAG_id_tag_update(&parent->id, OB_RECALC_OB); + DAG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); @@ -2165,7 +2409,7 @@ void CLIP_OT_set_axis(wmOperatorType *ot) /* api callbacks */ ot->exec= set_axis_exec; - ot->poll= space_clip_frame_camera_poll; + ot->poll= set_orientation_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -2176,29 +2420,37 @@ void CLIP_OT_set_axis(wmOperatorType *ot) /********************** set scale operator *********************/ -static int set_scale_exec(bContext *C, wmOperator *op) +static int do_set_scale(bContext *C, wmOperator *op, int scale_solution) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object= BKE_tracking_active_object(tracking); MovieTrackingTrack *track; Scene *scene= CTX_data_scene(C); - Object *parent= scene->camera; + Object *object= NULL; + Object *camera= get_camera_with_movieclip(scene, clip); + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); int tot= 0; float vec[2][3], mat[4][4], scale; float dist= RNA_float_get(op->ptr, "distance"); if(count_selected_bundles(C)!=2) { - BKE_report(op->reports, RPT_ERROR, "Two tracks with bundles should be selected to scale scene"); + BKE_report(op->reports, RPT_ERROR, "Two tracks with bundles should be selected to set scale"); return OPERATOR_CANCELLED; } - if(scene->camera->parent) - parent= scene->camera->parent; + object= get_orientation_object(C); + if(!object) { + BKE_report(op->reports, RPT_ERROR, "No object to apply orientation on"); + + return OPERATOR_CANCELLED; + } - BKE_get_tracking_mat(scene, NULL, mat); + BKE_get_tracking_mat(scene, camera, mat); - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) { mul_v3_m4v3(vec[tot], mat, track->bundle_pos); @@ -2213,11 +2465,29 @@ static int set_scale_exec(bContext *C, wmOperator *op) if(len_v3(vec[0])>1e-5f) { scale= dist / len_v3(vec[0]); - mul_v3_fl(parent->size, scale); - mul_v3_fl(parent->loc, scale); + if(tracking_object->flag&TRACKING_OBJECT_CAMERA) { + mul_v3_fl(object->size, scale); + mul_v3_fl(object->loc, scale); + } else + if(!scale_solution){ + Object *camera= object_solver_camera(scene, object); + + object->size[0]= object->size[1]= object->size[2]= 1.0f/scale; + + if(camera) { + object->size[0]/= camera->size[0]; + object->size[1]/= camera->size[1]; + object->size[2]/= camera->size[2]; + } + } + else { + tracking_object->scale= scale; + } DAG_id_tag_update(&clip->id, 0); - DAG_id_tag_update(&parent->id, OB_RECALC_OB); + + if(object) + DAG_id_tag_update(&object->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_MOVIECLIP|NA_EVALUATED, clip); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); @@ -2226,6 +2496,11 @@ static int set_scale_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int set_scale_exec(bContext *C, wmOperator *op) +{ + return do_set_scale(C, op, 0); +} + static int set_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { SpaceClip *sc= CTX_wm_space_clip(C); @@ -2248,7 +2523,60 @@ void CLIP_OT_set_scale(wmOperatorType *ot) /* api callbacks */ ot->exec= set_scale_exec; ot->invoke= set_scale_invoke; - ot->poll= space_clip_frame_camera_poll; + ot->poll= set_orientation_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_float(ot->srna, "distance", 0.0f, -FLT_MAX, FLT_MAX, + "Distance", "Distance between selected tracks", -100.0f, 100.0f); +} + +/********************** set solution scale operator *********************/ + +static int set_solution_scale_poll(bContext *C) +{ + if(space_clip_frame_poll(C)) { + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object= BKE_tracking_active_object(tracking); + + return (tracking_object->flag&TRACKING_OBJECT_CAMERA) == 0; + } + + return 0; +} + +static int set_solution_scale_exec(bContext *C, wmOperator *op) +{ + return do_set_scale(C, op, 1); +} + +static int set_solution_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + float dist= RNA_float_get(op->ptr, "distance"); + + if(dist==0.0f) + RNA_float_set(op->ptr, "distance", clip->tracking.settings.object_distance); + + return set_solution_scale_exec(C, op); +} + +void CLIP_OT_set_solution_scale(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Set Solution Scale"; + ot->description= "Set object solution scale using distance between two selected tracks"; + ot->idname= "CLIP_OT_set_solution_scale"; + + /* api callbacks */ + ot->exec= set_solution_scale_exec; + ot->invoke= set_solution_scale_invoke; + ot->poll= set_solution_scale_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -2301,11 +2629,14 @@ static int hide_tracks_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTrackingTrack *track; + MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); int unselected; unselected= RNA_boolean_get(op->ptr, "unselected"); - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(unselected==0 && TRACK_VIEW_SELECTED(sc, track)) { track->flag|= TRACK_HIDDEN; @@ -2316,7 +2647,7 @@ static int hide_tracks_exec(bContext *C, wmOperator *op) track= track->next; } - if(clip->tracking.act_track && clip->tracking.act_track->flag&TRACK_HIDDEN) + if(act_track && act_track->flag&TRACK_HIDDEN) clip->tracking.act_track= NULL; if(unselected==0) { @@ -2353,9 +2684,10 @@ static int hide_tracks_clear_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { track->flag&= ~TRACK_HIDDEN; @@ -2408,7 +2740,9 @@ static int detect_features_exec(bContext *C, wmOperator *op) MovieClip *clip= ED_space_clip(sc); int clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS; ImBuf *ibuf= BKE_movieclip_get_ibuf_flag(clip, &sc->user, clip_flag); - MovieTrackingTrack *track= clip->tracking.tracks.first; + MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *track= tracksbase->first; int placement= RNA_enum_get(op->ptr, "placement"); int margin= RNA_int_get(op->ptr, "margin"); int min_trackability= RNA_int_get(op->ptr, "min_trackability"); @@ -2430,7 +2764,8 @@ static int detect_features_exec(bContext *C, wmOperator *op) track= track->next; } - BKE_tracking_detect_fast(&clip->tracking, ibuf, sc->user.framenr, margin, min_trackability, min_distance, layer, place_outside_layer); + BKE_tracking_detect_fast(tracking, tracksbase, ibuf, sc->user.framenr, margin, + min_trackability, min_distance, layer, place_outside_layer); IMB_freeImBuf(ibuf); @@ -2479,7 +2814,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) int delta; if(pos<=1) { /* jump to path */ - track= clip->tracking.act_track; + track= BKE_tracking_active_track(&clip->tracking); if(!track) return OPERATOR_CANCELLED; @@ -2499,13 +2834,16 @@ static int frame_jump_exec(bContext *C, wmOperator *op) if(clip->tracking.reconstruction.flag&TRACKING_RECONSTRUCTED) { int a= sc->user.framenr; MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *object= BKE_tracking_active_object(tracking); delta= pos == 3 ? 1 : -1; a+= delta; while(a+delta >= SFRA && a+delta <= EFRA) { - MovieReconstructedCamera *cam= BKE_tracking_get_reconstructed_camera(tracking, a); + MovieReconstructedCamera *cam; + + cam= BKE_tracking_get_reconstructed_camera(tracking, object, a); if(!cam) { sc->user.framenr= a; @@ -2562,16 +2900,18 @@ static int join_tracks_exec(bContext *C, wmOperator *op) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *act_track, *track, *next; - act_track= clip->tracking.act_track; + act_track= BKE_tracking_active_track(tracking); if(!act_track) { BKE_report(op->reports, RPT_ERROR, "No active track to join to"); return OPERATOR_CANCELLED; } - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && track!=act_track) { if(!BKE_tracking_test_join_tracks(act_track, track)) { @@ -2583,7 +2923,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op) track= track->next; } - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { next= track->next; @@ -2591,7 +2931,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op) BKE_tracking_join_tracks(act_track, track); BKE_tracking_free_track(track); - BLI_freelinkN(&clip->tracking.tracks, track); + BLI_freelinkN(tracksbase, track); } track= next; @@ -2624,7 +2964,8 @@ static int lock_tracks_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *track= tracking->tracks.first; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *track= tracksbase->first; int action= RNA_enum_get(op->ptr, "action"); while(track) { @@ -2673,12 +3014,14 @@ static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); - MovieTrackingTrack *track, *act_track= clip->tracking.act_track; + MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *track, *act_track= BKE_tracking_active_track(tracking); if(!act_track) return OPERATOR_CANCELLED; - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && track!=act_track) { track->flag&= ~TRACK_CUSTOMCOLOR; @@ -2719,11 +3062,12 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op)) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; MovieTrackingStabilization *stab= &tracking->stabilization; int update= 0; - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_USE_2D_STAB)==0) { track->flag|= TRACK_USE_2D_STAB; @@ -2768,10 +3112,11 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op)) MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; MovieTrackingStabilization *stab= &tracking->stabilization; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; int a= 0, update= 0; - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(track->flag&TRACK_USE_2D_STAB) { if(a==stab->act_track) { @@ -2826,10 +3171,11 @@ static int stabilize_2d_select_exec(bContext *C, wmOperator *UNUSED(op)) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track; int update= 0; - track= tracking->tracks.first; + track= tracksbase->first; while(track) { if(track->flag&TRACK_USE_2D_STAB) { BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, 0); @@ -2868,11 +3214,12 @@ static int stabilize_2d_set_rotation_exec(bContext *C, wmOperator *UNUSED(op)) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; + MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking); - if(tracking->act_track) { + if(act_track) { MovieTrackingStabilization *stab= &tracking->stabilization; - stab->rot_track= tracking->act_track; + stab->rot_track= act_track; stab->ok= 0; DAG_id_tag_update(&clip->id, 0); @@ -2997,7 +3344,8 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); MovieTracking *tracking= &clip->tracking; - MovieTrackingTrack *track, *next, *act_track= clip->tracking.act_track; + ListBase *tracksbase= BKE_tracking_get_tracks(tracking); + MovieTrackingTrack *track, *next, *act_track= BKE_tracking_active_track(tracking); int frames= RNA_int_get(op->ptr, "frames"); int action= RNA_enum_get(op->ptr, "action"); float error= RNA_float_get(op->ptr, "error"); @@ -3005,7 +3353,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) if(error && action==TRACKING_CLEAN_DELETE_SEGMENT) action= TRACKING_CLEAN_DELETE_TRACK; - track= tracking->tracks.first; + track= tracksbase->first; while(track) { next= track->next; @@ -3024,7 +3372,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) clip->tracking.act_track= NULL; BKE_tracking_free_track(track); - BLI_freelinkN(&clip->tracking.tracks, track); + BLI_freelinkN(tracksbase, track); track= NULL; } @@ -3034,7 +3382,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) clip->tracking.act_track= NULL; BKE_tracking_free_track(track); - BLI_freelinkN(&clip->tracking.tracks, track); + BLI_freelinkN(tracksbase, track); } } } @@ -3091,3 +3439,71 @@ void CLIP_OT_clean_tracks(wmOperatorType *ot) RNA_def_float(ot->srna, "error", 0.0f, 0.0f, FLT_MAX, "Reprojection Error", "Effect on tracks with have got larger reprojection error", 0.0f, 100.0f); RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Cleanup action to execute"); } + +/********************** add tracking object *********************/ + +static int tracking_object_new_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + + BKE_tracking_new_object(tracking, "Object"); + + WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); + + return OPERATOR_FINISHED; +} + +void CLIP_OT_tracking_object_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Tracking Object"; + ot->description= "Add new object for tracking"; + ot->idname= "CLIP_OT_tracking_object_new"; + + /* api callbacks */ + ot->exec= tracking_object_new_exec; + ot->poll= ED_space_clip_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************** remove tracking object *********************/ + +static int tracking_object_remove_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sc= CTX_wm_space_clip(C); + MovieClip *clip= ED_space_clip(sc); + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *object; + + object= BKE_tracking_active_object(tracking); + + if(object->flag&TRACKING_OBJECT_CAMERA) { + BKE_report(op->reports, RPT_WARNING, "Object used for camera tracking can't be deleted"); + return OPERATOR_CANCELLED; + } + + BKE_tracking_remove_object(tracking, object); + + WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip); + + return OPERATOR_FINISHED; +} + +void CLIP_OT_tracking_object_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Movie Tracking Object"; + ot->description= "Remove object for tracking"; + ot->idname= "CLIP_OT_tracking_object_remove"; + + /* api callbacks */ + ot->exec= tracking_object_remove_exec; + ot->poll= ED_space_clip_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index c6775873fab..7f54821c98d 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1500,48 +1500,49 @@ static void draw_bundle_sphere(void) glCallList(displist); } -static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, int flag) +static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d, + MovieClip *clip, MovieTrackingObject *tracking_object, int flag, int *global_track_index) { MovieTracking *tracking= &clip->tracking; MovieTrackingTrack *track; - float mat[4][4], imat[4][4], curcol[4]; + float mat[4][4], imat[4][4]; unsigned char col[4], scol[4]; - int bundlenr= 1; - - if((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0) - return; - - if(v3d->flag2&V3D_RENDER_OVERRIDE) - return; - - glGetFloatv(GL_CURRENT_COLOR, curcol); + int tracknr= *global_track_index; + ListBase *tracksbase= BKE_tracking_object_tracks(tracking, tracking_object); UI_GetThemeColor4ubv(TH_TEXT, col); UI_GetThemeColor4ubv(TH_SELECT, scol); BKE_get_tracking_mat(scene, base->object, mat); - glEnable(GL_LIGHTING); - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - glEnable(GL_COLOR_MATERIAL); - glShadeModel(GL_SMOOTH); + glPushMatrix(); - /* current ogl matrix is translated in camera space, bundles should - be rendered in world space, so camera matrix should be "removed" - from current ogl matrix */ - invert_m4_m4(imat, base->object->obmat); + if(tracking_object->flag & TRACKING_OBJECT_CAMERA) { + /* current ogl matrix is translated in camera space, bundles should + be rendered in world space, so camera matrix should be "removed" + from current ogl matrix */ + invert_m4_m4(imat, base->object->obmat); - glPushMatrix(); - glMultMatrixf(imat); - glMultMatrixf(mat); + glMultMatrixf(imat); + glMultMatrixf(mat); + } + else { + float obmat[4][4]; + + BKE_tracking_get_interpolated_camera(tracking, tracking_object, scene->r.cfra, obmat); + + invert_m4_m4(imat, obmat); + glMultMatrixf(imat); + } + + for (track= tracksbase->first; track; track= track->next) { + int selected= TRACK_SELECTED(track); - for ( track= tracking->tracks.first; track; track= track->next) { - int selected= track->flag&SELECT || track->pat_flag&SELECT || track->search_flag&SELECT; if((track->flag&TRACK_HAS_BUNDLE)==0) continue; if(flag&DRAW_PICKING) - glLoadName(base->selcol + (bundlenr<<16)); + glLoadName(base->selcol + (tracknr<<16)); glPushMatrix(); glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); @@ -1549,7 +1550,6 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, if(v3d->drawtype==OB_WIRE) { glDisable(GL_LIGHTING); - glDepthMask(0); if(selected) { if(base==BASACT) UI_ThemeColor(TH_ACTIVE); @@ -1561,7 +1561,6 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, drawaxes(0.05f, v3d->bundle_drawtype); - glDepthMask(1); glEnable(GL_LIGHTING); } else if(v3d->drawtype>OB_WIRE) { if(v3d->bundle_drawtype==OB_EMPTY_SPHERE) { @@ -1570,7 +1569,6 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, if(base==BASACT) UI_ThemeColor(TH_ACTIVE); else UI_ThemeColor(TH_SELECT); - glDepthMask(0); glLineWidth(2.f); glDisable(GL_LIGHTING); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -1580,7 +1578,6 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_LIGHTING); glLineWidth(1.f); - glDepthMask(1); } if(track->flag&TRACK_CUSTOMCOLOR) glColor3fv(track->color); @@ -1589,7 +1586,6 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, draw_bundle_sphere(); } else { glDisable(GL_LIGHTING); - glDepthMask(0); if(selected) { if(base==BASACT) UI_ThemeColor(TH_ACTIVE); @@ -1601,7 +1597,6 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, drawaxes(0.05f, v3d->bundle_drawtype); - glDepthMask(1); glEnable(GL_LIGHTING); } } @@ -1619,32 +1614,67 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, view3d_cached_text_draw_add(pos, track->name, 10, V3D_CACHE_TEXT_GLOBALSPACE, tcol); } - bundlenr++; + tracknr++; } if((flag & DRAW_PICKING)==0) { - if(v3d->flag2&V3D_SHOW_CAMERAPATH && clip->tracking.reconstruction.camnr) { - int a= 0; - MovieTrackingReconstruction *reconstruction= &tracking->reconstruction; - MovieReconstructedCamera *camera= tracking->reconstruction.cameras; + if((v3d->flag2&V3D_SHOW_CAMERAPATH) && (tracking_object->flag&TRACKING_OBJECT_CAMERA)) { + MovieTrackingReconstruction *reconstruction; + reconstruction= BKE_tracking_object_reconstruction(tracking, tracking_object); - glDisable(GL_LIGHTING); - UI_ThemeColor(TH_CAMERA_PATH); - glLineWidth(2.0f); + if(reconstruction->camnr) { + MovieReconstructedCamera *camera= reconstruction->cameras; + int a= 0; - glBegin(GL_LINE_STRIP); - for(a= 0; a<reconstruction->camnr; a++, camera++) { - glVertex3fv(camera->mat[3]); - } - glEnd(); + glDisable(GL_LIGHTING); + UI_ThemeColor(TH_CAMERA_PATH); + glLineWidth(2.0f); - glLineWidth(1.0f); - glEnable(GL_LIGHTING); + glBegin(GL_LINE_STRIP); + for(a= 0; a<reconstruction->camnr; a++, camera++) { + glVertex3fv(camera->mat[3]); + } + glEnd(); + + glLineWidth(1.0f); + glEnable(GL_LIGHTING); + } } } glPopMatrix(); + *global_track_index= tracknr; +} + +static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip, int flag) +{ + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *tracking_object; + float curcol[4]; + int global_track_index= 1; + + if((v3d->flag2&V3D_SHOW_RECONSTRUCTION)==0) + return; + + if(v3d->flag2&V3D_RENDER_OVERRIDE) + return; + + glGetFloatv(GL_CURRENT_COLOR, curcol); + + glEnable(GL_LIGHTING); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + glShadeModel(GL_SMOOTH); + + tracking_object= tracking->objects.first; + while(tracking_object) { + draw_viewport_object_reconstruction(scene, base, v3d, clip, tracking_object, + flag, &global_track_index); + + tracking_object= tracking_object->next; + } + /* restore */ glShadeModel(GL_FLAT); glDisable(GL_COLOR_MATERIAL); @@ -6849,7 +6879,34 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) ListBase targets = {NULL, NULL}; bConstraintTarget *ct; - if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) { + if(ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) { + /* special case for object solver and follow track constraints because they don't fill + constraint targets properly (design limitation -- scene is needed for their target + but it can't be accessed from get_targets callvack) */ + + Object *camob= NULL; + + if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) { + bFollowTrackConstraint *data= (bFollowTrackConstraint *)curcon->data; + + camob= data->camera ? data->camera : scene->camera; + } + else if(cti->type==CONSTRAINT_TYPE_OBJECTSOLVER) { + bObjectSolverConstraint *data= (bObjectSolverConstraint *)curcon->data; + + camob= data->camera ? data->camera : scene->camera; + } + + if(camob) { + setlinestyle(3); + glBegin(GL_LINES); + glVertex3fv(camob->obmat[3]); + glVertex3fv(ob->obmat[3]); + glEnd(); + setlinestyle(0); + } + } + else if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) { cti->get_constraint_targets(curcon, &targets); for (ct= targets.first; ct; ct= ct->next) { diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 886db3a5f0e..551eb3cd6b5 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1320,6 +1320,25 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) return basact; } +static void deselect_all_tracks(MovieTracking *tracking) +{ + MovieTrackingObject *object; + + object= tracking->objects.first; + while(object) { + ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); + MovieTrackingTrack *track= tracksbase->first; + + while(track) { + BKE_tracking_deselect_track(track, TRACK_AREA_ALL); + + track= track->next; + } + + object= object->next; + } +} + /* mval is region coords */ static int mouse_select(bContext *C, const int mval[2], short extend, short obcenter, short enumerate) { @@ -1391,27 +1410,41 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short obce if(basact->object->type==OB_CAMERA) { if(BASACT==basact) { int i, hitresult; - MovieTrackingTrack *track; + int changed= 0; for (i=0; i< hits; i++) { hitresult= buffer[3+(i*4)]; /* if there's bundles in buffer select bundles first, so non-camera elements should be ignored in buffer */ - if(basact->selcol != (hitresult & 0xFFFF)) + if(basact->selcol != (hitresult & 0xFFFF)) { continue; + } /* index of bundle is 1<<16-based. if there's no "bone" index in hight word, this buffer value belongs to camera,. not to bundle */ if(buffer[4*i+3] & 0xFFFF0000) { MovieClip *clip= object_get_movieclip(scene, basact->object, 0); - int selected; - track= BKE_tracking_indexed_track(&clip->tracking, hitresult >> 16); + MovieTracking *tracking= &clip->tracking; + ListBase *tracksbase; + MovieTrackingTrack *track; + + track= BKE_tracking_indexed_track(&clip->tracking, hitresult >> 16, &tracksbase); + + if(TRACK_SELECTED(track) && extend) { + changed= 0; + BKE_tracking_deselect_track(track, TRACK_AREA_ALL); + } + else { + int oldsel= TRACK_SELECTED(track) ? 1 : 0; + if(!extend) + deselect_all_tracks(tracking); - selected= (track->flag&SELECT) || (track->pat_flag&SELECT) || (track->search_flag&SELECT); + BKE_tracking_select_track(tracksbase, track, TRACK_AREA_ALL, extend); - if(selected && extend) BKE_tracking_deselect_track(track, TRACK_AREA_ALL); - else BKE_tracking_select_track(&clip->tracking, track, TRACK_AREA_ALL, extend); + if(oldsel!=(TRACK_SELECTED(track) ? 1 : 0)) + changed= 1; + } basact->flag|= SELECT; basact->object->flag= basact->flag; @@ -1424,6 +1457,12 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short obce break; } } + + if(!changed) { + /* fallback to regular object selection if no new bundles were selected, + allows to select object parented to reconstruction object */ + basact= mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, 0); + } } } else if(ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend) ) { /* then bone is found */ diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index ecb54c77e0c..a2173537c8c 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -55,6 +55,7 @@ #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_object.h" +#include "BKE_scene.h" #include "BKE_tracking.h" #include "WM_api.h" @@ -756,28 +757,55 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot) static void bundle_midpoint(Scene *scene, Object *ob, float vec[3]) { - MovieTrackingTrack *track; MovieClip *clip= object_get_movieclip(scene, ob, 0); + MovieTracking *tracking= &clip->tracking; + MovieTrackingObject *object= tracking->objects.first; int ok= 0; - float min[3], max[3], mat[4][4], pos[3]; + float min[3], max[3], mat[4][4], pos[3], cammat[4][4]; if(!clip) return; + unit_m4(cammat); + + if(!scene->camera) + scene->camera= scene_find_camera(scene); + + if(scene->camera) + copy_m4_m4(cammat, scene->camera->obmat); + BKE_get_tracking_mat(scene, ob, mat); INIT_MINMAX(min, max); - track= clip->tracking.tracks.first; - while(track) { - int selected= (track->flag&SELECT) || (track->pat_flag&SELECT) || (track->search_flag&SELECT); - if((track->flag&TRACK_HAS_BUNDLE) && selected) { - ok= 1; - mul_v3_m4v3(pos, mat, track->bundle_pos); - DO_MINMAX(pos, min, max); + while(object) { + ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object); + MovieTrackingTrack *track= tracksbase->first; + float obmat[4][4]; + + if(object->flag & TRACKING_OBJECT_CAMERA) { + copy_m4_m4(obmat, mat); + } + else { + float imat[4][4]; + + BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, imat); + invert_m4(imat); + + mult_m4_m4m4(obmat, cammat, imat); + } + + while(track) { + if((track->flag&TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) { + ok= 1; + mul_v3_m4v3(pos, obmat, track->bundle_pos); + DO_MINMAX(pos, min, max); + } + + track= track->next; } - track= track->next; + object= object->next; } if(ok) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0f93ff12f95..bc7514b4c9a 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4208,6 +4208,7 @@ static short constraints_list_needinv(TransInfo *t, ListBase *list) if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1; if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1; if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1; + if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) return 1; /* constraints that require this only under special conditions */ if (con->type == CONSTRAINT_TYPE_ROTLIKE) { @@ -5385,6 +5386,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t) TransData2D *td2d; SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip(sc); + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; MovieTrackingMarker *marker; TransDataTracking *tdt; @@ -5398,7 +5400,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t) /* count */ t->total = 0; - track = clip->tracking.tracks.first; + track = tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) { marker= BKE_tracking_get_marker(track, framenr); @@ -5425,7 +5427,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t) t->customFree= transDataTrackingFree; /* create actual data */ - track = clip->tracking.tracks.first; + track = tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track) && (track->flag&TRACK_LOCKED)==0) { marker= BKE_tracking_get_marker(track, framenr); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index e7e1ee43c5d..f6aca0336be 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -641,10 +641,11 @@ static void recalcData_clip(TransInfo *t) { SpaceClip *sc= t->sa->spacedata.first; MovieClip *clip= ED_space_clip(sc); + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); MovieTrackingTrack *track; if(t->state == TRANS_CANCEL) { - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) { MovieTrackingMarker *marker= BKE_tracking_ensure_marker(track, sc->user.framenr); @@ -658,7 +659,7 @@ static void recalcData_clip(TransInfo *t) flushTransTracking(t); - track= clip->tracking.tracks.first; + track= tracksbase->first; while(track) { if(TRACK_VIEW_SELECTED(sc, track)) { if (t->mode == TFM_TRANSLATION) { diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index dd18ba903f6..8fdbde60bab 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -415,6 +415,8 @@ typedef struct bFollowTrackConstraint { struct MovieClip *clip; char track[24]; int flag, pad; + char object[24]; + struct Object *camera; } bFollowTrackConstraint; /* Camera Solver constraints */ @@ -423,6 +425,15 @@ typedef struct bCameraSolverConstraint { int flag, pad; } bCameraSolverConstraint; +/* Camera Solver constraints */ +typedef struct bObjectSolverConstraint { + struct MovieClip *clip; + int flag, pad; + char object[24]; + float invmat[4][4]; /* parent-inverse matrix to use */ + struct Object *camera; +} bObjectSolverConstraint; + /* ------------------------------------------ */ /* bConstraint->type @@ -458,6 +469,7 @@ typedef enum eBConstraint_Types { CONSTRAINT_TYPE_PIVOT, /* Pivot Constraint */ CONSTRAINT_TYPE_FOLLOWTRACK, /* Follow Track Constraint */ CONSTRAINT_TYPE_CAMERASOLVER, /* Camera Solver Constraint */ + CONSTRAINT_TYPE_OBJECTSOLVER, /* Object Solver Constraint */ /* NOTE: no constraints are allowed to be added after this */ NUM_CONSTRAINT_TYPES @@ -765,6 +777,11 @@ typedef enum eCameraSolver_Flags { CAMERASOLVER_ACTIVECLIP = (1<<0) } eCameraSolver_Flags; +/* ObjectSolver Constraint -> flag */ +typedef enum eObjectSolver_Flags { + OBJECTSOLVER_ACTIVECLIP = (1<<0) +} eObjectSolver_Flags; + /* Rigid-Body Constraint */ #define CONSTRAINT_DRAW_PIVOT 0x40 #define CONSTRAINT_DISABLE_LINKED_COLLISION 0x80 diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 445bca94c8c..131c540ac47 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -142,7 +142,10 @@ typedef struct MovieTrackingSettings { /* cleanup */ int clean_frames, clean_action; - float clean_error, pad; + float clean_error; + + /* set object scale */ + float object_distance; /* distance between two bundles used for object scaling */ } MovieTrackingSettings; typedef struct MovieTrackingStabilization { @@ -172,6 +175,17 @@ typedef struct MovieTrackingReconstruction { struct MovieReconstructedCamera *cameras; /* reconstructed cameras */ } MovieTrackingReconstruction; +typedef struct MovieTrackingObject { + struct MovieTrackingObject *next, *prev; + + char name[24]; /* Name of tracking object */ + int flag; + float scale; /* scale of object solution in amera space */ + + ListBase tracks; /* list of tracks use to tracking this object */ + MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */ +} MovieTrackingObject; + typedef struct MovieTrackingStats { char message[256]; } MovieTrackingStats; @@ -179,11 +193,14 @@ typedef struct MovieTrackingStats { typedef struct MovieTracking { MovieTrackingSettings settings; /* different tracking-related settings */ MovieTrackingCamera camera; /* camera intrinsics */ - ListBase tracks; /* all tracks */ - MovieTrackingReconstruction reconstruction; /* reconstruction data */ + ListBase tracks; /* list of tracks used for camera object */ + MovieTrackingReconstruction reconstruction; /* reconstruction data for camera object */ MovieTrackingStabilization stabilization; /* stabilization data */ MovieTrackingTrack *act_track; /* active track */ + ListBase objects; + int objectnr, tot_object; /* index of active object and total number of objects */ + MovieTrackingStats *stats; /* statistics displaying in clip editor */ } MovieTracking; @@ -242,6 +259,9 @@ enum { /* MovieTrackingReconstruction->flag */ #define TRACKING_RECONSTRUCTED (1<<0) +/* MovieTrackingObject->flag */ +#define TRACKING_OBJECT_CAMERA (1<<0) + #define TRACKING_CLEAN_SELECT 0 #define TRACKING_CLEAN_DELETE_TRACK 1 #define TRACKING_CLEAN_DELETE_SEGMENT 2 diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 37a5b5643b8..215c7992ff3 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -329,6 +329,7 @@ extern StructRNA RNA_MotionPath; extern StructRNA RNA_MotionPathVert; extern StructRNA RNA_MouseSensor; extern StructRNA RNA_MovieSequence; +extern StructRNA RNA_MovieTrackingObject; extern StructRNA RNA_MulticamSequence; extern StructRNA RNA_MultiresModifier; extern StructRNA RNA_MusgraveTexture; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 4ab14550fd1..6439d22e808 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -45,6 +45,7 @@ EnumPropertyItem constraint_type_items[] ={ {0, "", 0, "Motion Tracking", ""}, {CONSTRAINT_TYPE_CAMERASOLVER, "CAMERA_SOLVER", ICON_CONSTRAINT_DATA, "Camera Solver", ""}, + {CONSTRAINT_TYPE_OBJECTSOLVER, "OBJECT_SOLVER", ICON_CONSTRAINT_DATA, "Object Solver", ""}, {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""}, {0, "", 0, "Transform", ""}, {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", ""}, @@ -163,6 +164,8 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr) return &RNA_FollowTrackConstraint; case CONSTRAINT_TYPE_CAMERASOLVER: return &RNA_CameraSolverConstraint; + case CONSTRAINT_TYPE_OBJECTSOLVER: + return &RNA_ObjectSolverConstraint; default: return &RNA_UnknownType; } @@ -327,6 +330,49 @@ static void rna_SplineIKConstraint_joint_bindings_set(PointerRNA *ptr, const flo memcpy(ikData->points, values, ikData->numpoints * sizeof(float)); } +static int rna_Constraint_cameraObject_poll(PointerRNA *ptr, PointerRNA value) +{ + Object *ob= (Object*)value.data; + + if (ob) { + if (ob->type == OB_CAMERA && ob != (Object*)ptr->id.data) { + return 1; + } + } + + return 0; +} + +static void rna_Constraint_followTrack_camera_set(PointerRNA *ptr, PointerRNA value) +{ + bConstraint *con= (bConstraint*)ptr->data; + bFollowTrackConstraint *data= (bFollowTrackConstraint*)con->data; + Object *ob= (Object*)value.data; + + if (ob) { + if (ob->type == OB_CAMERA && ob != (Object*)ptr->id.data) { + data->camera= ob; + } + } else { + data->camera= NULL; + } +} + +static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, PointerRNA value) +{ + bConstraint *con= (bConstraint*)ptr->data; + bObjectSolverConstraint *data= (bObjectSolverConstraint*)con->data; + Object *ob= (Object*)value.data; + + if (ob) { + if (ob->type == OB_CAMERA && ob != (Object*)ptr->id.data) { + data->camera= ob; + } + } else { + data->camera= NULL; + } +} + #else EnumPropertyItem constraint_distance_items[] = { @@ -2066,6 +2112,20 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", FOLLOWTRACK_USE_3D_POSITION); RNA_def_property_ui_text(prop, "3D Position", "Use 3D position of track to parent to"); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + /* object */ + prop= RNA_def_property(srna, "object", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "object"); + RNA_def_property_ui_text(prop, "Object", "Movie tracking object to follow (if empty, camera object is used)"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + /* camera */ + prop= RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "camera"); + RNA_def_property_ui_text(prop, "Camera", "Camera to which motion is parented (if empty active scene camera is used)"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + RNA_def_property_pointer_funcs(prop, NULL, "rna_Constraint_followTrack_camera_set", NULL, "rna_Constraint_cameraObject_poll"); } static void rna_def_constraint_camera_solver(BlenderRNA *brna) @@ -2074,7 +2134,7 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna) PropertyRNA *prop; srna= RNA_def_struct(brna, "CameraSolverConstraint", "Constraint"); - RNA_def_struct_ui_text(srna, "Follow Track Constraint", "Lock motion to the reconstructed camera movement"); + RNA_def_struct_ui_text(srna, "Camera Solver Constraint", "Lock motion to the reconstructed camera movement"); RNA_def_struct_sdna_from(srna, "bCameraSolverConstraint", "data"); /* movie clip */ @@ -2091,6 +2151,43 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } +static void rna_def_constraint_object_solver(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "ObjectSolverConstraint", "Constraint"); + RNA_def_struct_ui_text(srna, "Object Solver Constraint", "Lock motion to the reconstructed object movement"); + RNA_def_struct_sdna_from(srna, "bObjectSolverConstraint", "data"); + + /* movie clip */ + prop= RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "clip"); + RNA_def_property_ui_text(prop, "Movie Clip", "Movie Clip to get tracking data from"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + /* use default clip */ + prop= RNA_def_property(srna, "use_active_clip", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CAMERASOLVER_ACTIVECLIP); + RNA_def_property_ui_text(prop, "Active Clip", "Use active clip defined in scene"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + + /* object */ + prop= RNA_def_property(srna, "object", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "object"); + RNA_def_property_ui_text(prop, "Object", "Movie tracking object to follow"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + /* camera */ + prop= RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "camera"); + RNA_def_property_ui_text(prop, "Camera", "Camera to which motion is parented (if empty active scene camera is used)"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + RNA_def_property_pointer_funcs(prop, NULL, "rna_Constraint_objectSolver_camera_set", NULL, "rna_Constraint_cameraObject_poll"); +} + /* base struct for constraints */ void RNA_def_constraint(BlenderRNA *brna) { @@ -2203,6 +2300,7 @@ void RNA_def_constraint(BlenderRNA *brna) rna_def_constraint_pivot(brna); rna_def_constraint_follow_track(brna); rna_def_constraint_camera_solver(brna); + rna_def_constraint_object_solver(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 9b7e8be68be..bbec6484c5f 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -90,43 +90,87 @@ static void rna_tracking_defaultSettings_searchUpdate(Main *UNUSED(bmain), Scene static void rna_tracking_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { MovieClip *clip= (MovieClip*)ptr->id.data; + rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL); } -static void rna_tracking_tracks_add(MovieTracking *tracking, int frame, int number) +static void rna_tracking_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { - int a; + MovieClip *clip= (MovieClip*)ptr->id.data; - for(a= 0; a<number; a++) - BKE_tracking_add_track(tracking, 0, 0, frame, 1, 1); + rna_iterator_listbase_begin(iter, &clip->tracking.objects, NULL); +} - WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL); +static int rna_tracking_active_object_index_get(PointerRNA *ptr) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; + + return clip->tracking.objectnr; +} + +static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; + + clip->tracking.objectnr= value; +} + +static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, int *max) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; + + *min= 0; + *max= clip->tracking.tot_object-1; + *max= MAX2(0, *max); } static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr) { MovieClip *clip= (MovieClip*)ptr->id.data; + MovieTrackingTrack *act_track= BKE_tracking_active_track(&clip->tracking); - return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, clip->tracking.act_track); + return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, act_track); } static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value) { MovieClip *clip= (MovieClip*)ptr->id.data; MovieTrackingTrack *track= (MovieTrackingTrack *)value.data; - int index= BLI_findindex(&clip->tracking.tracks, track); + ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking); + int index= BLI_findindex(tracksbase, track); - if(index>=0) clip->tracking.act_track= track; - else clip->tracking.act_track= NULL; + if(index>=0) + clip->tracking.act_track= track; + else + clip->tracking.act_track= NULL; } void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value) { MovieClip *clip= (MovieClip *)ptr->id.data; + MovieTracking *tracking= &clip->tracking; MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data; + ListBase *tracksbase= &tracking->tracks; + BLI_strncpy(track->name, value, sizeof(track->name)); - BKE_track_unique_name(&clip->tracking, track); + /* TODO: it's a bit difficult to find list track came from knowing just + movie clip ID and MovieTracking structure, so keep this naive + search for a while */ + if(BLI_findindex(tracksbase, track) < 0) { + MovieTrackingObject *object= tracking->objects.first; + + while(object) { + if(BLI_findindex(&object->tracks, track)) { + tracksbase= &object->tracks; + break; + } + + object= object->next; + } + } + + BKE_track_unique_name(tracksbase, track); } static int rna_trackingTrack_select_get(PointerRNA *ptr) @@ -257,8 +301,102 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR DAG_id_tag_update(&clip->id, 0); } +static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + MovieTrackingObject *object= (MovieTrackingObject* )ptr->data; + + rna_iterator_listbase_begin(iter, &object->tracks, NULL); +} + +static PointerRNA rna_tracking_active_object_get(PointerRNA *ptr) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; + MovieTrackingObject *object= BLI_findlink(&clip->tracking.objects, clip->tracking.objectnr); + + return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingObject, object); +} + +static void rna_tracking_active_object_set(PointerRNA *ptr, PointerRNA value) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; + MovieTrackingObject *object= (MovieTrackingObject *)value.data; + int index= BLI_findindex(&clip->tracking.objects, object); + + if(index>=0) clip->tracking.objectnr= index; + else clip->tracking.objectnr= 0; +} + +void rna_trackingObject_name_set(PointerRNA *ptr, const char *value) +{ + MovieClip *clip= (MovieClip *)ptr->id.data; + MovieTrackingObject *object= (MovieTrackingObject *)ptr->data; + + BLI_strncpy(object->name, value, sizeof(object->name)); + + BKE_tracking_object_unique_name(&clip->tracking, object); +} + +static void rna_trackingObject_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +{ + MovieClip *clip= (MovieClip*)ptr->id.data; + + WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, NULL); + DAG_id_tag_update(&clip->id, 0); +} + /* API */ +static void add_tracks_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, int frame, int number) +{ + int a, width, height; + MovieClipUser user= {0}; + + user.framenr= 1; + + BKE_movieclip_get_size(clip, &user, &width, &height); + + for(a= 0; a<number; a++) + BKE_tracking_add_track(tracking, tracksbase, 0, 0, frame, width, height); +} + +static void rna_tracking_tracks_add(ID *id, MovieTracking *tracking, int frame, int number) +{ + MovieClip *clip= (MovieClip *) id; + + add_tracks_to_base(clip, tracking, &tracking->tracks, frame, number); + + WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL); +} + +static void rna_trackingObject_tracks_add(ID *id, MovieTrackingObject *object, int frame, int number) +{ + MovieClip *clip= (MovieClip *) id; + ListBase *tracksbase= &object->tracks; + + if(object->flag&TRACKING_OBJECT_CAMERA) + tracksbase= &clip->tracking.tracks; + + add_tracks_to_base(clip, &clip->tracking, tracksbase, frame, number); + + WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL); +} + +static MovieTrackingObject *rna_tracking_object_new(MovieTracking *tracking, const char *name) +{ + MovieTrackingObject *object= BKE_tracking_new_object(tracking, name); + + WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL); + + return object; +} + +void rna_tracking_object_remove(MovieTracking *tracking, MovieTrackingObject *object) +{ + BKE_tracking_remove_object(tracking, object); + + WM_main_add_notifier(NC_MOVIECLIP|NA_EDITED, NULL); +} + static MovieTrackingMarker *rna_trackingTrack_marker_find_frame(MovieTrackingTrack *track, int framenr) { return BKE_tracking_get_marker(track, framenr); @@ -442,6 +580,14 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_range(prop, 5, 1000); RNA_def_property_update(prop, 0, "rna_tracking_defaultSettings_searchUpdate"); RNA_def_property_ui_text(prop, "Search Size", "Size of search area for newly created tracks"); + + /* object distance */ + prop= RNA_def_property(srna, "object_distance", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_float_sdna(prop, NULL, "object_distance"); + RNA_def_property_ui_text(prop, "Distance", "Distance between two bundles used for object scaling"); + RNA_def_property_range(prop, 0.001, 10000); + RNA_def_property_ui_range(prop, 0.001, 10000.0, 1, 3); } static void rna_def_trackingCamera(BlenderRNA *brna) @@ -889,18 +1035,18 @@ static void rna_def_trackingReconstruction(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Cameras", "Collection of solved cameras"); } -static void rna_def_trackingTracks(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_trackingTracks(BlenderRNA *brna) { StructRNA *srna; FunctionRNA *func; PropertyRNA *prop; - RNA_def_property_srna(cprop, "MovieTrackingTracks"); srna= RNA_def_struct(brna, "MovieTrackingTracks", NULL); RNA_def_struct_sdna(srna, "MovieTracking"); RNA_def_struct_ui_text(srna, "Movie Tracks", "Collection of movie tracking tracks"); func= RNA_def_function(srna, "add", "rna_tracking_tracks_add"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip"); RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add tracks on", MINFRAME, MAXFRAME); RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of tracks to add to the movie clip", 0, INT_MAX); @@ -913,6 +1059,105 @@ static void rna_def_trackingTracks(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object"); } +static void rna_def_trackingObjectTracks(BlenderRNA *brna) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "MovieTrackingObjectTracks", NULL); + RNA_def_struct_sdna(srna, "MovieTrackingObject"); + RNA_def_struct_ui_text(srna, "Movie Tracks", "Collection of movie tracking tracks"); + + func= RNA_def_function(srna, "add", "rna_trackingObject_tracks_add"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip"); + RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add tracks on", MINFRAME, MAXFRAME); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of tracks to add to the movie clip", 0, INT_MAX); + + /* active track */ + prop= RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MovieTrackingTrack"); + RNA_def_property_pointer_funcs(prop, "rna_tracking_active_track_get", "rna_tracking_active_track_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object"); +} + +static void rna_def_trackingObject(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "MovieTrackingObject", NULL); + RNA_def_struct_ui_text(srna, "Movie tracking object data", "Match-moving object tracking and reconstruction data"); + + /* name */ + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Unique name of object"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_trackingObject_name_set"); + RNA_def_property_string_maxlength(prop, MAX_ID_NAME); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL); + RNA_def_struct_name_property(srna, prop); + + /* is_camera */ + prop= RNA_def_property(srna, "is_camera", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_OBJECT_CAMERA); + RNA_def_property_ui_text(prop, "Camera", "Object is used for camera tracking"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); + + /* tracks */ + prop= RNA_def_property(srna, "tracks", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_trackingObject_tracks_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MovieTrackingTrack"); + RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object"); + RNA_def_property_srna(prop, "MovieTrackingObjectTracks"); + + /* reconstruction */ + prop= RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MovieTrackingReconstruction"); + + /* scale */ + prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_range(prop, 0.0001f, 10000.0f); + RNA_def_property_ui_range(prop, 0.0001f, 10000.0, 1, 4); + RNA_def_property_ui_text(prop, "Scale", "Scale of object solution in camera space"); + RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, "rna_trackingObject_flushUpdate"); +} + +static void rna_def_trackingObjects(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + PropertyRNA *prop; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "MovieTrackingObjects"); + srna= RNA_def_struct(brna, "MovieTrackingObjects", NULL); + RNA_def_struct_sdna(srna, "MovieTracking"); + RNA_def_struct_ui_text(srna, "Movie Objects", "Collection of movie trackingobjects"); + + func= RNA_def_function(srna, "new", "rna_tracking_object_new"); + RNA_def_function_ui_description(func, "Add tracking object to this movie clip"); + RNA_def_string(func, "name", "", 0, "", "Name of new object"); + parm= RNA_def_pointer(func, "object", "MovieTrackingObject", "", "New motion tracking object"); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "rna_tracking_object_remove"); + RNA_def_function_ui_description(func, "Remove tracking object from this movie clip"); + parm= RNA_def_pointer(func, "object", "MovieTrackingObject", "", "Motion tracking object to be removed"); + + /* active object */ + prop= RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "MovieTrackingObject"); + RNA_def_property_pointer_funcs(prop, "rna_tracking_active_object_get", "rna_tracking_active_object_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_UNLINK); + RNA_def_property_ui_text(prop, "Active Object", "Active object in this tracking data object"); +} + static void rna_def_tracking(BlenderRNA *brna) { StructRNA *srna; @@ -921,8 +1166,11 @@ static void rna_def_tracking(BlenderRNA *brna) rna_def_trackingSettings(brna); rna_def_trackingCamera(brna); rna_def_trackingTrack(brna); + rna_def_trackingTracks(brna); + rna_def_trackingObjectTracks(brna); rna_def_trackingStabilization(brna); rna_def_trackingReconstruction(brna); + rna_def_trackingObject(brna); srna= RNA_def_struct(brna, "MovieTracking", NULL); RNA_def_struct_ui_text(srna, "Movie tracking data", "Match-moving data for tracking"); @@ -940,7 +1188,7 @@ static void rna_def_tracking(BlenderRNA *brna) RNA_def_property_collection_funcs(prop, "rna_tracking_tracks_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); RNA_def_property_struct_type(prop, "MovieTrackingTrack"); RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object"); - rna_def_trackingTracks(brna, prop); + RNA_def_property_srna(prop, "MovieTrackingTracks"); /* stabilization */ prop= RNA_def_property(srna, "stabilization", PROP_POINTER, PROP_NONE); @@ -949,6 +1197,20 @@ static void rna_def_tracking(BlenderRNA *brna) /* reconstruction */ prop= RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MovieTrackingReconstruction"); + + /* objects */ + prop= RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_tracking_objects_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0); + RNA_def_property_struct_type(prop, "MovieTrackingObject"); + RNA_def_property_ui_text(prop, "Objects", "Collection of objects in this tracking data object"); + rna_def_trackingObjects(brna, prop); + + /* active object index */ + prop= RNA_def_property(srna, "active_object_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "objectnr"); + RNA_def_property_int_funcs(prop, "rna_tracking_active_object_index_get", "rna_tracking_active_object_index_set", "rna_tracking_active_object_index_range"); + RNA_def_property_ui_text(prop, "Active Object Index", "Index of active object"); + RNA_def_property_update(prop, NC_MOVIECLIP|ND_DISPLAY, NULL); } void RNA_def_tracking(BlenderRNA *brna) |