diff options
Diffstat (limited to 'source/blender/blenkernel')
19 files changed, 2162 insertions, 1796 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index b833bc44201..faa996b9888 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -49,7 +49,7 @@ extern "C" { /* used by packaging tools */ /* can be left blank, otherwise a,b,c... etc with no quotes */ -#define BLENDER_VERSION_CHAR a +#define BLENDER_VERSION_CHAR a /* alpha/beta/rc/release, docs use this */ #define BLENDER_VERSION_CYCLE alpha diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index d67e1a9118e..f58af8f39a0 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -35,6 +35,7 @@ struct CurveMapping; struct CurveMap; struct CurveMapPoint; struct Scopes; +struct Histogram; struct ImBuf; struct rctf; @@ -74,7 +75,7 @@ void curvemapping_premultiply(struct CurveMapping *cumap, int res int curvemapping_RGBA_does_something(struct CurveMapping *cumap); void curvemapping_initialize(struct CurveMapping *cumap); void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size); - +void BKE_histogram_update_sample_line(struct Histogram *hist, struct ImBuf *ibuf, const short use_color_management); void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, int use_color_management); void scopes_free(struct Scopes *scopes); void scopes_new(struct Scopes *scopes); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index ec2eb82a9eb..0e93869a8b0 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -48,6 +48,7 @@ struct MaskLayer *BKE_mask_layer_active(struct Mask *mask); void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay); void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay); +void BKE_mask_layer_free_shapes(struct MaskLayer *masklay); void BKE_mask_layer_free(struct MaskLayer *masklay); void BKE_mask_spline_free(struct MaskSpline *spline); struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline); @@ -169,7 +170,7 @@ void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, i /* rasterization */ int BKE_mask_get_duration(struct Mask *mask); void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer, - const short do_aspect_correct, const short do_linear); + const short do_aspect_correct, int do_mask_aa); #define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) #define MASKPOINT_ISSEL_KNOT(p) ( (p)->bezt.f2 & SELECT) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b1e5fabc456..b3f17c06d5c 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -339,7 +339,7 @@ struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock); void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node); -void nodeAddToPreview(struct bNode *, float *, int, int, int); +void nodeAddToPreview(struct bNode *node, float col[4], int x, int y, int do_manage); struct bNode *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node); @@ -372,6 +372,7 @@ void nodeSetActive(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeGetActive(struct bNodeTree *ntree); struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype); int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id); +void nodeClearActive(struct bNodeTree *ntree); void nodeClearActiveID(struct bNodeTree *ntree, short idtype); struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree); @@ -447,9 +448,7 @@ struct bNodeSocket *node_group_add_socket(struct bNodeTree *ngroup, const char * struct bNodeSocket *node_group_expose_socket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out); void node_group_expose_all_sockets(struct bNodeTree *ngroup); void node_group_remove_socket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out); - -struct bNode *node_group_make_from_selected(struct bNodeTree *ntree); -int node_group_ungroup(struct bNodeTree *ntree, struct bNode *gnode); +struct bNodeSocket *node_group_add_extern_socket(struct bNodeTree *ntree, ListBase *lb, int in_out, struct bNodeSocket *gsock); /* in node_common.c */ void register_node_type_frame(struct bNodeTreeType *ttype); @@ -659,6 +658,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); #define CMP_NODE_DOUBLEEDGEMASK 266 #define CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED 267 /* DEPRECATED multi file node has been merged into regular CMP_NODE_OUTPUT_FILE */ #define CMP_NODE_MASK 268 +#define CMP_NODE_KEYINGSCREEN 269 +#define CMP_NODE_KEYING 270 #define CMP_NODE_GLARE 301 #define CMP_NODE_TONEMAP 302 @@ -692,6 +693,9 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); #define CMP_SCALE_ABSOLUTE 1 #define CMP_SCALE_SCENEPERCENT 2 #define CMP_SCALE_RENDERPERCENT 3 +/* custom2 */ +#define CMP_SCALE_RENDERSIZE_FRAME_ASPECT (1 << 0) +#define CMP_SCALE_RENDERSIZE_FRAME_CROP (1 << 1) /* API */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 890fc40c284..b8ba3095905 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -158,6 +158,26 @@ void BKE_object_relink(struct Object *ob); struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, int use_default); +/* this function returns a superset of the scenes selection based on relationships */ + +typedef enum eObRelationTypes { + OB_REL_NONE = 0, /* just the selection as is */ + OB_REL_PARENT = (1 << 0), /* immediate parent */ + OB_REL_PARENT_RECURSIVE = (1 << 1), /* parents up to root of selection tree*/ + OB_REL_CHILDREN = (1 << 2), /* immediate children */ + OB_REL_CHILDREN_RECURSIVE = (1 << 3), /* All children */ + OB_REL_MOD_ARMATURE = (1 << 4), /* Armatures related to the selected objects */ + OB_REL_SCENE_CAMERA = (1 << 5), /* you might want the scene camera too even if unselected? */ +} eObRelationTypes; + +typedef enum eObjectSet { + OB_SET_SELECTED, /* Selected Objects */ + OB_SET_VISIBLE, /* Visible Objects */ + OB_SET_ALL /* All Objects */ +} eObjectSet; + +struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 5b09f8fdf3d..a7b03cef933 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -72,8 +72,8 @@ typedef struct SpaceTransform { } SpaceTransform; void space_transform_from_matrixs(struct SpaceTransform *data, float local[4][4], float target[4][4]); -void space_transform_apply(const struct SpaceTransform *data, float *co); -void space_transform_invert(const struct SpaceTransform *data, float *co); +void space_transform_apply(const struct SpaceTransform *data, float co[3]); +void space_transform_invert(const struct SpaceTransform *data, float co[3]); #define space_transform_setup(data, local, target) space_transform_from_matrixs(data, (local)->obmat, (target)->obmat) diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 8c28dd93a5e..2b30c845754 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -47,164 +47,191 @@ struct Camera; struct Object; struct Scene; -void BKE_tracking_init_settings(struct MovieTracking *tracking); -void BKE_tracking_clamp_marker(struct MovieTrackingMarker *marker, int event); -void BKE_tracking_track_flag(struct MovieTrackingTrack *track, int area, int flag, int clear); +/* **** Common functions **** */ -struct MovieTrackingTrack *BKE_tracking_add_track(struct MovieTracking *tracking, struct ListBase *tracksbase, - float x, float y, int framenr, int width, int height); -struct MovieTrackingMarker *BKE_tracking_insert_marker(struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker); -void BKE_tracking_delete_marker(struct MovieTrackingTrack *track, int framenr); +void BKE_tracking_free(struct MovieTracking *tracking); -void BKE_tracking_marker_pattern_minmax(struct MovieTrackingMarker *marker, float min[2], float max[2]); -struct MovieTrackingMarker *BKE_tracking_get_marker(struct MovieTrackingTrack *track, int framenr); -struct MovieTrackingMarker *BKE_tracking_ensure_marker(struct MovieTrackingTrack *track, int framenr); -struct MovieTrackingMarker *BKE_tracking_exact_marker(struct MovieTrackingTrack *track, int framenr); -int BKE_tracking_has_marker(struct MovieTrackingTrack *track, int framenr); -int BKE_tracking_has_enabled_marker(struct MovieTrackingTrack *track, int framenr); +void BKE_tracking_settings_init(struct MovieTracking *tracking); -void BKE_tracking_free_track(struct MovieTrackingTrack *track); +struct ListBase *BKE_tracking_get_active_tracks(struct MovieTracking *tracking); +struct MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(struct MovieTracking *tracking); -void BKE_tracking_clear_path(struct MovieTrackingTrack *track, int ref_frame, int action); +/* matrices for constraints and drawing */ +void BKE_tracking_get_camera_object_matrix(struct Scene *scene, struct Object *ob, float mat[4][4]); +void BKE_tracking_get_projection_matrix(struct MovieTracking *tracking, struct MovieTrackingObject *object, + int framenr, int winx, int winy, float mat[4][4]); -void BKE_tracking_join_tracks(struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); -void BKE_tracking_free(struct MovieTracking *tracking); +/* **** Clipboard **** */ +void BKE_tracking_clipboard_free(void); +void BKE_tracking_clipboard_copy_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); +int BKE_tracking_clipboard_has_tracks(void); +void BKE_tracking_clipboard_paste_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); -struct ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, - struct ImBuf *struct_ibuf, struct MovieTrackingMarker *marker, - int num_samples_x, int num_samples_y, float pos[2]); -struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int anchored, int disable_channels); -struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int anchored, int disable_channels); -struct ImBuf *BKE_tracking_track_mask_get(struct MovieTracking *tracking, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int width, int height); +/* **** Track **** */ +struct MovieTrackingTrack *BKE_tracking_track_add(struct MovieTracking *tracking, struct ListBase *tracksbase, + float x, float y, int framenr, int width, int height); +void BKE_tracking_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); +void BKE_tracking_track_free(struct MovieTrackingTrack *track); -void BKE_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); +void BKE_tracking_track_flag_set(struct MovieTrackingTrack *track, int area, int flag); +void BKE_tracking_track_flag_clear(struct MovieTrackingTrack *track, int area, int flag); -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); +int BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr); +int BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr); -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_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action); +void BKE_tracking_tracks_join(struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); -void BKE_get_tracking_mat(struct Scene *scene, struct Object *ob, 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 MovieTrackingTrack *BKE_tracking_track_get_named(struct MovieTracking *tracking, + struct MovieTrackingObject *object, + const char *name); +struct MovieTrackingTrack *BKE_tracking_track_get_indexed(struct MovieTracking *tracking, int tracknr, + struct ListBase **tracksbase_r); -struct ListBase *BKE_tracking_get_tracks(struct MovieTracking *tracking); -struct MovieTrackingReconstruction *BKE_tracking_get_reconstruction(struct MovieTracking *tracking); +struct MovieTrackingTrack *BKE_tracking_track_get_active(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); +float *BKE_tracking_track_get_mask(int frame_width, int frame_height, struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker); -void BKE_tracking_disable_imbuf_channels(struct ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, int grayscale); +/* selection */ +void BKE_tracking_track_select(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend); +void BKE_tracking_track_deselect(struct MovieTrackingTrack *track, int area); -/* clipboard */ -void BKE_tracking_free_clipboard(void); -void BKE_tracking_clipboard_copy_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); -int BKE_tracking_clipboard_has_tracks(void); -void BKE_tracking_clipboard_paste_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); +/* **** Marker **** */ +struct MovieTrackingMarker *BKE_tracking_marker_insert(struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker); +void BKE_tracking_marker_delete(struct MovieTrackingTrack *track, int framenr); -/* 2D tracking */ -struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user, - short backwards, short sequence); -void BKE_tracking_context_free(struct MovieTrackingContext *context); -void BKE_tracking_sync(struct MovieTrackingContext *context); -void BKE_tracking_sync_user(struct MovieClipUser *user, struct MovieTrackingContext *context); -int BKE_tracking_next(struct MovieTrackingContext *context); +void BKE_tracking_marker_clamp(struct MovieTrackingMarker *marker, int event); -/* Camera solving */ -int BKE_tracking_can_reconstruct(struct MovieTracking *tracking, struct MovieTrackingObject *object, - char *error_msg, int error_size); +struct MovieTrackingMarker *BKE_tracking_marker_get(struct MovieTrackingTrack *track, int framenr); +struct MovieTrackingMarker *BKE_tracking_marker_get_exact(struct MovieTrackingTrack *track, int framenr); +struct MovieTrackingMarker *BKE_tracking_marker_ensure(struct MovieTrackingTrack *track, int framenr); -struct MovieReconstructContext* BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking, - 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); +void BKE_tracking_marker_pattern_minmax(const struct MovieTrackingMarker *marker, float min[2], float max[2]); -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]); +/* **** Object **** */ +struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name); +void BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object); -/* Feature detection */ -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); +void BKE_tracking_object_unique_name(struct MovieTracking *tracking, struct MovieTrackingObject *object); + +struct MovieTrackingObject *BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name); -/* 2D stabilization */ -void BKE_tracking_stabilization_data(struct MovieTracking *tracking, int framenr, int width, int height, float loc[2], float *scale, float *angle); -struct ImBuf *BKE_tracking_stabilize(struct MovieTracking *tracking, int framenr, struct ImBuf *ibuf, float loc[2], float *scale, float *angle); -void BKE_tracking_stabdata_to_mat4(int width, int height, float aspect, float loc[2], float scale, float angle, float mat[4][4]); +struct MovieTrackingObject *BKE_tracking_object_get_active(struct MovieTracking *tracking); +struct MovieTrackingObject *BKE_tracking_object_get_camera(struct MovieTracking *tracking); -/* Distortion/Undistortion */ -void BKE_tracking_apply_intrinsics(struct MovieTracking *tracking, float co[2], float nco[2]); -void BKE_tracking_invert_intrinsics(struct MovieTracking *tracking, float co[2], float nco[2]); +struct ListBase *BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); +struct MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(struct MovieTracking *tracking, + struct MovieTrackingObject *object); -struct MovieDistortion *BKE_tracking_distortion_create(void); +/* **** Camera **** */ +void BKE_tracking_camera_shift_get(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); + +struct MovieReconstructedCamera *BKE_tracking_camera_get_reconstructed(struct MovieTracking *tracking, + struct MovieTrackingObject *object, + int framenr); +void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tracking, + struct MovieTrackingObject *object, + int framenr, float mat[4][4]); + +/* **** Distortion/Undistortion **** */ +struct MovieDistortion *BKE_tracking_distortion_new(void); +void BKE_tracking_distortion_update(struct MovieDistortion *distortion, struct MovieTracking *tracking, + int calibration_width, int calibration_height); struct MovieDistortion *BKE_tracking_distortion_copy(struct MovieDistortion *distortion); struct ImBuf *BKE_tracking_distortion_exec(struct MovieDistortion *distortion, struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan, int undistort); -void BKE_tracking_distortion_destroy(struct MovieDistortion *distortion); +void BKE_tracking_distortion_free(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); +void BKE_tracking_distort_v2(struct MovieTracking *tracking, float co[2], float nco[2]); +void BKE_tracking_undistort_v2(struct MovieTracking *tracking, float co[2], float nco[2]); -/* 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); +struct ImBuf *BKE_tracking_undistort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, + int calibration_width, int calibration_height, float overscan); +struct ImBuf *BKE_tracking_distort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, + int calibration_width, int calibration_height, float overscan); + +/* **** Image sampling **** */ +struct ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, + struct ImBuf *struct_ibuf, struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker, int use_mask, + int num_samples_x, int num_samples_y, float pos[2]); +struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker, int anchored, int disable_channels); +struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker, int anchored, int disable_channels); -/* Select */ -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); +void BKE_tracking_disable_channels(struct ImBuf *ibuf, int disable_red, int disable_green, + int disable_blue, int grayscale); + +/* **** 2D tracking **** */ +struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user, + short backwards, short sequence); +void BKE_tracking_context_free(struct MovieTrackingContext *context); +void BKE_tracking_context_sync(struct MovieTrackingContext *context); +void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context, struct MovieClipUser *user); +int BKE_tracking_context_step(struct MovieTrackingContext *context); + +/* **** Camera solving **** */ +int BKE_tracking_reconstruction_check(struct MovieTracking *tracking, struct MovieTrackingObject *object, + char *error_msg, int error_size); + +struct MovieReconstructContext *BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking, + struct MovieTrackingObject *object, + int keyframe1, int keyframe2, + int width, int height); +void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context); +void BKE_tracking_reconstruction_solve(struct MovieReconstructContext *context, short *stop, short *do_update, + float *progress, char *stats_message, int message_size); +int BKE_tracking_reconstruction_finish(struct MovieReconstructContext *context, struct MovieTracking *tracking); + +/* **** Feature detection **** */ +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); + +/* **** 2D stabilization **** */ +void BKE_tracking_stabilization_data_get(struct MovieTracking *tracking, int framenr, int width, int height, + float loc[2], float *scale, float *angle); +struct ImBuf *BKE_tracking_stabilize_frame(struct MovieTracking *tracking, int framenr, struct ImBuf *ibuf, + float loc[2], float *scale, float *angle); +void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, float loc[2], + float scale, float angle, float mat[4][4]); /* Dopesheet */ void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking); -void BKE_tracking_dopesheet_update(struct MovieTracking *tracking, int sort_method, int inverse); - -#define TRACK_SELECTED(track) ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT) +void BKE_tracking_dopesheet_update(struct MovieTracking *tracking); -#define TRACK_AREA_SELECTED(track, area) ((area)==TRACK_AREA_POINT ? (track)->flag&SELECT : \ - ((area)==TRACK_AREA_PAT ? (track)->pat_flag&SELECT : \ - (track)->search_flag&SELECT)) +#define TRACK_SELECTED(track) ((track)->flag & SELECT || (track)->pat_flag & SELECT || (track)->search_flag & SELECT) -#define TRACK_VIEW_SELECTED(sc, track) ((((track)->flag & TRACK_HIDDEN)==0) && \ - ( TRACK_AREA_SELECTED(track, TRACK_AREA_POINT) || \ - (((sc)->flag & SC_SHOW_MARKER_PATTERN) && TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) || \ - (((sc)->flag & SC_SHOW_MARKER_SEARCH) && TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)))) +#define TRACK_AREA_SELECTED(track, area) ((area) == TRACK_AREA_POINT ? (track)->flag & SELECT : \ + ((area) == TRACK_AREA_PAT ? (track)->pat_flag & SELECT : \ + (track)->search_flag & SELECT)) -#define MARKER_VISIBLE(sc, track, marker) (((marker)->flag & MARKER_DISABLED)==0 || ((sc)->flag & SC_HIDE_DISABLED)==0 || (sc->clip->tracking.act_track == track)) +#define TRACK_VIEW_SELECTED(sc, track) ((((track)->flag & TRACK_HIDDEN) == 0) && \ + (TRACK_AREA_SELECTED(track, TRACK_AREA_POINT) || \ + (((sc)->flag & SC_SHOW_MARKER_PATTERN) && TRACK_AREA_SELECTED(track, TRACK_AREA_PAT)) || \ + (((sc)->flag & SC_SHOW_MARKER_SEARCH) && TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH)))) -#define TRACK_CLEAR_UPTO 0 -#define TRACK_CLEAR_REMAINED 1 -#define TRACK_CLEAR_ALL 2 +#define MARKER_VISIBLE(sc, track, marker) (((marker)->flag & MARKER_DISABLED) == 0 || ((sc)->flag & SC_HIDE_DISABLED) == 0 || (sc->clip->tracking.act_track == track)) -#define CLAMP_PAT_DIM 1 -#define CLAMP_PAT_POS 2 -#define CLAMP_SEARCH_DIM 3 -#define CLAMP_SEARCH_POS 4 +#define TRACK_CLEAR_UPTO 0 +#define TRACK_CLEAR_REMAINED 1 +#define TRACK_CLEAR_ALL 2 -#define TRACK_AREA_NONE -1 -#define TRACK_AREA_POINT 1 -#define TRACK_AREA_PAT 2 -#define TRACK_AREA_SEARCH 4 +#define CLAMP_PAT_DIM 1 +#define CLAMP_PAT_POS 2 +#define CLAMP_SEARCH_DIM 3 +#define CLAMP_SEARCH_POS 4 -#define TRACK_AREA_ALL (TRACK_AREA_POINT|TRACK_AREA_PAT|TRACK_AREA_SEARCH) +#define TRACK_AREA_NONE -1 +#define TRACK_AREA_POINT 1 +#define TRACK_AREA_PAT 2 +#define TRACK_AREA_SEARCH 4 -#define TRACK_SORT_NONE -1 -#define TRACK_SORT_NAME 0 -#define TRACK_SORT_LONGEST 1 -#define TRACK_SORT_TOTAL 2 -#define TRACK_SORT_AVERAGE_ERROR 3 +#define TRACK_AREA_ALL (TRACK_AREA_POINT | TRACK_AREA_PAT | TRACK_AREA_SEARCH) #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index ec2b8a04c9a..e5701927b07 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1294,9 +1294,11 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime /* check if this driver's curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { /* check if driver itself is tagged for recalculation */ - if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID) /*&& (driver->flag & DRIVER_FLAG_RECALC)*/) { // XXX driver recalc flag is not set yet by depsgraph! - /* evaluate this using values set already in other places */ - // NOTE: for 'layering' option later on, we should check if we should remove old value before adding new to only be done when drivers only changed + /* XXX driver recalc flag is not set yet by depsgraph! */ + if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID) /*&& (driver->flag & DRIVER_FLAG_RECALC)*/) { + /* evaluate this using values set already in other places + * NOTE: for 'layering' option later on, we should check if we should remove old value before adding + * new to only be done when drivers only changed */ calculate_fcurve(fcu, ctime); ok = animsys_execute_fcurve(ptr, NULL, fcu); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 5ad81db1979..9af1d5f52c4 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -986,7 +986,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float for (j = dvert->totweight; j != 0; j--, dw++) { const int index = dw->def_nr; - if (index < defbase_tot && (pchan = defnrToPC[index])) { + if (index >= 0 && index < defbase_tot && (pchan = defnrToPC[index])) { float weight = dw->weight; Bone *bone = pchan->bone; pdef_info = pdef_info_array + defnrToPCIndex[index]; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 12dee600532..6879ec506f0 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -946,6 +946,62 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons } } +void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short use_color_management) +{ + int i, x, y; + float *fp; + float rgb[3]; + unsigned char *cp; + + int x1 = 0.5f + hist->co[0][0] * ibuf->x; + int x2 = 0.5f + hist->co[1][0] * ibuf->x; + int y1 = 0.5f + hist->co[0][1] * ibuf->y; + int y2 = 0.5f + hist->co[1][1] * ibuf->y; + + hist->channels = 3; + hist->x_resolution = 256; + hist->xmax = 1.0f; + hist->ymax = 1.0f; + + if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; + + /* persistent draw */ + hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */ + + for (i = 0; i < 256; i++) { + x = (int)(0.5f + x1 + (float)i * (x2 - x1) / 255.0f); + y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f); + + if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y) { + hist->data_luma[i] = hist->data_r[i] = hist->data_g[i] = hist->data_b[i] = hist->data_a[i] = 0.0f; + } + else { + if (ibuf->rect_float) { + fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); + + if (use_color_management) + linearrgb_to_srgb_v3_v3(rgb, fp); + else + copy_v3_v3(rgb, fp); + + hist->data_luma[i] = rgb_to_luma(rgb); + hist->data_r[i] = rgb[0]; + hist->data_g[i] = rgb[1]; + hist->data_b[i] = rgb[2]; + hist->data_a[i] = fp[3]; + } + else if (ibuf->rect) { + cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); + hist->data_luma[i] = (float)rgb_to_luma_byte(cp) / 255.0f; + hist->data_r[i] = (float)cp[0] / 255.0f; + hist->data_g[i] = (float)cp[1] / 255.0f; + hist->data_b[i] = (float)cp[2] / 255.0f; + hist->data_a[i] = (float)cp[3] / 255.0f; + } + } + } +} + void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) { int x, y, c; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 0150646a96c..c12e740958c 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -822,12 +822,12 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar if (data->flag == CHILDOF_ALL) { /* multiply target (parent matrix) by offset (parent inverse) to get - * the effect of the parent that will be exherted on the owner + * the effect of the parent that will be exerted on the owner */ mult_m4_m4m4(parmat, ct->matrix, data->invmat); /* now multiply the parent matrix by the owner matrix to get the - * the effect of this constraint (i.e. owner is 'parented' to parent) + * the effect of this constraint (i.e. owner is 'parented' to parent) */ mult_m4_m4m4(cob->matrix, parmat, cob->matrix); } @@ -864,7 +864,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder); /* multiply target (parent matrix) by offset (parent inverse) to get - * the effect of the parent that will be exherted on the owner + * the effect of the parent that will be exerted on the owner */ mult_m4_m4m4(parmat, ct->matrix, invmat); @@ -1620,7 +1620,7 @@ static void rotlike_new_data(void *cdata) static void rotlike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) { - bChildOfConstraint *data = con->data; + bRotateLikeConstraint *data = con->data; /* target only */ func(con, (ID **)&data->tar, FALSE, userdata); @@ -2159,7 +2159,15 @@ static void actcon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintT printf("do Action Constraint %s - Ob %s Pchan %s\n", con->name, cob->ob->id.name + 2, (cob->pchan) ? cob->pchan->name : NULL); /* Get the appropriate information from the action */ - if (cob->type == CONSTRAINT_OBTYPE_BONE) { + if (cob->type == CONSTRAINT_OBTYPE_OBJECT || (data->flag & ACTCON_BONE_USE_OBJECT_ACTION)) { + Object workob; + + /* evaluate using workob */ + // FIXME: we don't have any consistent standards on limiting effects on object... + what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t); + BKE_object_to_mat4(&workob, ct->matrix); + } + else if (cob->type == CONSTRAINT_OBTYPE_BONE) { Object workob; bPose *pose; bPoseChannel *pchan, *tchan; @@ -2185,14 +2193,6 @@ static void actcon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintT /* Clean up */ BKE_pose_free(pose); } - else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) { - Object workob; - - /* evaluate using workob */ - // FIXME: we don't have any consistent standards on limiting effects on object... - what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t); - BKE_object_to_mat4(&workob, ct->matrix); - } else { /* behavior undefined... */ puts("Error: unknown owner type for Action Constraint"); @@ -3278,6 +3278,15 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t switch (data->from) { case 2: /* scale */ mat4_to_size(dvec, ct->matrix); + + if (is_negative_m4(ct->matrix)) { + /* Bugfix [#27886] + * We can't be sure which axis/axes are negative, though we know that something is negative. + * Assume we don't care about negativity of separate axes. <--- This is a limitation that + * riggers will have to live with for now. + */ + negate_v3(dvec); + } break; case 1: /* rotation (convert to degrees first) */ mat4_to_eulO(dvec, cob->rotOrder, ct->matrix); @@ -3908,14 +3917,14 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase tracking = &clip->tracking; if (data->object[0]) - tracking_object = BKE_tracking_named_object(tracking, data->object); + tracking_object = BKE_tracking_object_get_named(tracking, data->object); else - tracking_object = BKE_tracking_get_camera_object(tracking); + tracking_object = BKE_tracking_object_get_camera(tracking); if (!tracking_object) return; - track = BKE_tracking_named_track(tracking, tracking_object, data->track); + track = BKE_tracking_track_get_named(tracking, tracking_object, data->track); if (!track) return; @@ -3933,14 +3942,14 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase copy_m4_m4(mat, camob->obmat); - BKE_tracking_get_interpolated_camera(tracking, tracking_object, framenr, imat); + BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, 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); + BKE_tracking_get_camera_object_matrix(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]); @@ -3972,7 +3981,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase CameraParams params; float pos[2], rmat[4][4]; - marker = BKE_tracking_get_marker(track, framenr); + marker = BKE_tracking_marker_get(track, framenr); add_v2_v2v2(pos, marker->pos, track->offset); @@ -4094,10 +4103,10 @@ static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (clip) { float mat[4][4], obmat[4][4]; MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *object = BKE_tracking_get_camera_object(tracking); + MovieTrackingObject *object = BKE_tracking_object_get_camera(tracking); int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra); - BKE_tracking_get_interpolated_camera(tracking, object, framenr, mat); + BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat); copy_m4_m4(obmat, cob->matrix); @@ -4156,7 +4165,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object; - object = BKE_tracking_named_object(tracking, data->object); + object = BKE_tracking_object_get_named(tracking, data->object); if (object) { float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4]; @@ -4164,7 +4173,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase BKE_object_where_is_calc_mat4(scene, camob, cammat); - BKE_tracking_get_interpolated_camera(tracking, object, framenr, mat); + BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat); invert_m4_m4(camimat, cammat); mult_m4_m4m4(parmat, cammat, data->invmat); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index ce62b9c10dc..623d4b8a931 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1002,9 +1002,7 @@ void BKE_nurb_makeFaces(Nurb *nu, float *coord_array, int rowstride, int resolu, bp++; if (*fp != 0.0f) { - in[0] += (*fp) * bp->vec[0]; - in[1] += (*fp) * bp->vec[1]; - in[2] += (*fp) * bp->vec[2]; + madd_v3_v3fl(in, bp->vec, *fp); } } } @@ -1106,9 +1104,7 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float * bp++; if (*fp != 0.0f) { - coord_fp[0] += (*fp) * bp->vec[0]; - coord_fp[1] += (*fp) * bp->vec[1]; - coord_fp[2] += (*fp) * bp->vec[2]; + madd_v3_v3fl(coord_fp, bp->vec, *fp); if (tilt_fp) (*tilt_fp) += (*fp) * bp->alfa; diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index bb2940091e4..48db916b4ba 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1029,10 +1029,27 @@ void BKE_mask_layer_shape_free(MaskLayerShape *masklay_shape) MEM_freeN(masklay_shape); } +/** \brief Free all animation keys for a mask layer + */ +void BKE_mask_layer_free_shapes(MaskLayer *masklay) +{ + MaskLayerShape *masklay_shape; + + /* free animation data */ + masklay_shape = masklay->splines_shapes.first; + while (masklay_shape) { + MaskLayerShape *next_masklay_shape = masklay_shape->next; + + BLI_remlink(&masklay->splines_shapes, masklay_shape); + BKE_mask_layer_shape_free(masklay_shape); + + masklay_shape = next_masklay_shape; + } +} + void BKE_mask_layer_free(MaskLayer *masklay) { MaskSpline *spline; - MaskLayerShape *masklay_shape; /* free splines */ spline = masklay->splines.first; @@ -1046,15 +1063,7 @@ void BKE_mask_layer_free(MaskLayer *masklay) } /* free animation data */ - masklay_shape = masklay->splines_shapes.first; - while (masklay_shape) { - MaskLayerShape *next_masklay_shape = masklay_shape->next; - - BLI_remlink(&masklay->splines_shapes, masklay_shape); - BKE_mask_layer_shape_free(masklay_shape); - - masklay_shape = next_masklay_shape; - } + BKE_mask_layer_free_shapes(masklay); MEM_freeN(masklay); } @@ -1147,16 +1156,16 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[ if (parent->id) { MovieClip *clip = (MovieClip *) parent->id; MovieTracking *tracking = (MovieTracking *) &clip->tracking; - MovieTrackingObject *ob = BKE_tracking_named_object(tracking, parent->parent); + MovieTrackingObject *ob = BKE_tracking_object_get_named(tracking, parent->parent); if (ob) { - MovieTrackingTrack *track = BKE_tracking_named_track(tracking, ob, parent->sub_parent); + MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, ob, parent->sub_parent); MovieClipUser user = {0}; user.framenr = ctime; if (track) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, ctime); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, ctime); float marker_pos_ofs[2]; add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset); BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs); @@ -2061,19 +2070,6 @@ static void m_invert_vn_vn(float *array, const float f, const int size) } } -static void clamp_vn_vn_linear(float *array, const int size) -{ - float *arr = array + (size - 1); - - int i = size; - while (i--) { - if (*arr <= 0.0f) *arr = 0.0f; - else if (*arr >= 1.0f) *arr = 1.0f; - else *arr = srgb_to_linearrgb(*arr); - arr--; - } -} - static void clamp_vn_vn(float *array, const int size) { float *arr = array + (size - 1); @@ -2093,7 +2089,7 @@ int BKE_mask_get_duration(Mask *mask) /* rasterization */ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer, - const short do_aspect_correct, const short do_linear) + const short do_aspect_correct, int do_mask_aa) { MaskLayer *masklay; @@ -2158,7 +2154,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer, if (tot_diff_point) { PLX_raskterize(diff_points, tot_diff_point, - buffer_tmp, width, height); + buffer_tmp, width, height, do_mask_aa); if (tot_diff_feather_points) { PLX_raskterize_feather(diff_points, tot_diff_point, @@ -2213,12 +2209,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer, } /* clamp at the end */ - if (do_linear) { - clamp_vn_vn_linear(buffer, buffer_size); - } - else { - clamp_vn_vn(buffer, buffer_size); - } + clamp_vn_vn(buffer, buffer_size); } MEM_freeN(buffer_tmp); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 8b91ee29c59..68adb599c6c 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -159,7 +159,7 @@ static void get_sequence_fname(MovieClip *clip, int framenr, char *name) offset = sequence_guess_offset(clip->name, strlen(head), numlen); if (numlen) - BLI_stringenc(name, head, tail, numlen, offset + framenr - clip->start_frame); + BLI_stringenc(name, head, tail, numlen, offset + framenr - clip->start_frame + clip->frame_offset); else BLI_strncpy(name, clip->name, sizeof(clip->name)); @@ -171,7 +171,7 @@ static void get_proxy_fname(MovieClip *clip, int proxy_render_size, int undistor { int size = rendersize_to_number(proxy_render_size); char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX]; - int proxynr = framenr - clip->start_frame + 1; + int proxynr = framenr - clip->start_frame + 1 + clip->frame_offset; BLI_split_dirfile(clip->name, clipdir, clipfile, FILE_MAX, FILE_MAX); @@ -250,7 +250,7 @@ static ImBuf *movieclip_load_movie_file(MovieClip *clip, MovieClipUser *user, in int fra; dur = IMB_anim_get_duration(clip->anim, tc); - fra = framenr - clip->start_frame; + fra = framenr - clip->start_frame + clip->frame_offset; if (fra < 0) fra = 0; @@ -436,7 +436,7 @@ static MovieClip *movieclip_alloc(const char *name) clip->aspx = clip->aspy = 1.0f; - BKE_tracking_init_settings(&clip->tracking); + BKE_tracking_settings_init(&clip->tracking); clip->proxy.build_size_flag = IMB_PROXY_25; clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN | @@ -446,6 +446,7 @@ static MovieClip *movieclip_alloc(const char *name) clip->proxy.quality = 90; clip->start_frame = 1; + clip->frame_offset = 0; return clip; } @@ -547,7 +548,7 @@ static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *dist if (distortion) undistibuf = BKE_tracking_distortion_exec(distortion, &clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f, 1); else - undistibuf = BKE_tracking_undistort(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f); + undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f); if (undistibuf->userflags & IB_RECT_INVALID) { ibuf->userflags &= ~IB_RECT_INVALID; @@ -677,7 +678,7 @@ static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *u postproc_ibuf = IMB_dupImBuf(ibuf); if (disable_red || disable_green || disable_blue || grayscale) - BKE_tracking_disable_imbuf_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1); + BKE_tracking_disable_channels(postproc_ibuf, disable_red, disable_green, disable_blue, 1); } IMB_refImBuf(postproc_ibuf); @@ -772,6 +773,7 @@ static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, int float tloc[2], tscale, tangle; short proxy = IMB_PROXY_NONE; int render_flag = 0; + int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr); if (clip->flag & MCLIP_USE_PROXY) { proxy = rendersize_to_proxy(user, clip->flag); @@ -798,7 +800,7 @@ static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, int stableibuf = cache->stabilized.ibuf; - BKE_tracking_stabilization_data(&clip->tracking, framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); + BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); /* check for stabilization parameters */ if (tscale != cache->stabilized.scale || @@ -820,11 +822,12 @@ static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user MovieTracking *tracking = &clip->tracking; ImBuf *stableibuf; float tloc[2], tscale, tangle; + int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr); if (cache->stabilized.ibuf) IMB_freeImBuf(cache->stabilized.ibuf); - stableibuf = BKE_tracking_stabilize(&clip->tracking, framenr, ibuf, tloc, &tscale, &tangle); + stableibuf = BKE_tracking_stabilize_frame(&clip->tracking, clip_framenr, ibuf, tloc, &tscale, &tangle); cache->stabilized.ibuf = stableibuf; @@ -1039,14 +1042,15 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->marker = NULL; scopes->track = NULL; + scopes->track_locked = TRUE; if (clip) { - MovieTrackingTrack *act_track = BKE_tracking_active_track(&clip->tracking); + MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking); if (act_track) { MovieTrackingTrack *track = act_track; int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); if (marker->flag & MARKER_DISABLED) { scopes->track_disabled = TRUE; @@ -1055,6 +1059,8 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, user); scopes->track_disabled = FALSE; + scopes->marker = marker; + scopes->track = track; if (ibuf && (ibuf->rect || ibuf->rect_float)) { ImBuf *search_ibuf; @@ -1069,7 +1075,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip undist_marker.pos[0] *= width; undist_marker.pos[1] *= height * aspy; - BKE_tracking_invert_intrinsics(&clip->tracking, undist_marker.pos, undist_marker.pos); + BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos); undist_marker.pos[0] /= width; undist_marker.pos[1] /= height * aspy; @@ -1087,6 +1093,8 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->frame_width = ibuf->x; scopes->frame_height = ibuf->y; + + scopes->use_track_mask = track->flag & TRACK_PREVIEW_ALPHA; } IMB_freeImBuf(ibuf); @@ -1095,8 +1103,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip if ((track->flag & TRACK_LOCKED) == 0) { float pat_min[2], pat_max[2]; - scopes->marker = marker; - scopes->track = track; + scopes->track_locked = FALSE; /* XXX: would work fine with non-transformed patterns, but would likely fail * with transformed patterns, but that would be easier to debug when diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 4cbfb4f0f3e..cb6f6823f48 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -548,13 +548,6 @@ static void multires_reallocate_mdisps(int totloop, MDisps *mdisps, int lvl) } } -static void column_vectors_to_mat3(float mat[][3], float v1[3], float v2[3], float v3[3]) -{ - copy_v3_v3(mat[0], v1); - copy_v3_v3(mat[1], v2); - copy_v3_v3(mat[2], v3); -} - static void multires_copy_grid(float (*gridA)[3], float (*gridB)[3], int sizeA, int sizeB) { int x, y, j, skip; @@ -962,7 +955,7 @@ void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updat multires_subdivide(mmd, ob, mmd->totlvl + 1, updateblock, simple); } -void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3]) +static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3]) { if (axis == 0) { if (x == key->grid_size - 1) { @@ -986,6 +979,19 @@ void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, floa } } +/* Construct 3x3 tangent-space matrix in 'mat' */ +static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, + int x, int y, CCGElem *grid) +{ + grid_tangent(key, x, y, 0, grid, mat[0]); + normalize_v3(mat[0]); + + grid_tangent(key, x, y, 1, grid, mat[1]); + normalize_v3(mat[1]); + + copy_v3_v3(mat[2], CCG_grid_elem_no(key, grid, x, y)); +} + static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; @@ -1067,22 +1073,11 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm for (x = 0; x < gridSize; x++) { float *co = CCG_grid_elem_co(&key, grid, x, y); float *sco = CCG_grid_elem_co(&key, subgrid, x, y); - float *no = CCG_grid_elem_no(&key, subgrid, x, y); float *data = dispgrid[dGridSize * y * dSkip + x * dSkip]; - float mat[3][3], tx[3], ty[3], disp[3], d[3], mask; + float mat[3][3], disp[3], d[3], mask; /* construct tangent space matrix */ - grid_tangent(&key, x, y, 0, subGridData[gIndex], tx); - normalize_v3(tx); - - grid_tangent(&key, x, y, 1, subGridData[gIndex], ty); - normalize_v3(ty); - - //mul_v3_fl(tx, 1.0f/(gridSize-1)); - //mul_v3_fl(ty, 1.0f/(gridSize-1)); - //cross_v3_v3v3(no, tx, ty); - - column_vectors_to_mat3(mat, tx, ty, no); + grid_tangent_matrix(mat, &key, x, y, subgrid); switch (op) { case APPLY_DISPLACEMENTS: @@ -1344,17 +1339,11 @@ void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to) for (y = 0; y < gridSize; y++) { for (x = 0; x < gridSize; x++) { float *data = dispgrid[dGridSize * y * dSkip + x * dSkip]; - float *no = CCG_grid_elem_no(&key, subgrid, x, y); float *co = CCG_grid_elem_co(&key, subgrid, x, y); - float mat[3][3], tx[3], ty[3], dco[3]; + float mat[3][3], dco[3]; /* construct tangent space matrix */ - grid_tangent(&key, x, y, 0, subGridData[gIndex], tx); - normalize_v3(tx); - - grid_tangent(&key, x, y, 1, subGridData[gIndex], ty); - normalize_v3(ty); - column_vectors_to_mat3(mat, tx, ty, no); + grid_tangent_matrix(mat, &key, x, y, subgrid); /* convert to absolute coordinates in space */ if (from == MULTIRES_SPACE_TANGENT) { @@ -1368,8 +1357,6 @@ void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to) copy_v3_v3(dco, data); } - column_vectors_to_mat3(mat, tx, ty, no); - /*now, convert to desired displacement type*/ if (to == MULTIRES_SPACE_TANGENT) { invert_m3(mat); @@ -2142,7 +2129,7 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) { DerivedMesh *dm = NULL, *cddm = NULL, *subdm = NULL; CCGElem **gridData, **subGridData; - CCGKey key; + CCGKey dm_key, subdm_key; Mesh *me = (Mesh *)ob->data; MPoly *mpoly = me->mpoly; /* MLoop *mloop = me->mloop; */ /* UNUSED */ @@ -2180,12 +2167,12 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) dm = subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0); cddm->release(cddm); - /*numGrids = dm->getNumGrids(dm);*/ /*UNUSED*/ gridSize = dm->getGridSize(dm); gridData = dm->getGridData(dm); gridOffset = dm->getGridOffset(dm); - dm->getGridKey(dm, &key); + dm->getGridKey(dm, &dm_key); subGridData = subdm->getGridData(subdm); + subdm->getGridKey(subdm, &subdm_key); dGridSize = multires_side_tot[high_mmd.totlvl]; dSkip = (dGridSize - 1) / (gridSize - 1); @@ -2203,20 +2190,13 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) for (y = 0; y < gridSize; y++) { for (x = 0; x < gridSize; x++) { - float *co = CCG_grid_elem_co(&key, grid, x, y); - float *sco = CCG_grid_elem_co(&key, subgrid, x, y); - float *no = CCG_grid_elem_no(&key, grid, x, y); + float *co = CCG_grid_elem_co(&dm_key, grid, x, y); + float *sco = CCG_grid_elem_co(&subdm_key, subgrid, x, y); float *data = dispgrid[dGridSize * y * dSkip + x * dSkip]; - float mat[3][3], tx[3], ty[3], disp[3]; + float mat[3][3], disp[3]; /* construct tangent space matrix */ - grid_tangent(&key, x, y, 0, gridData[gIndex], tx); - normalize_v3(tx); - - grid_tangent(&key, x, y, 1, gridData[gIndex], ty); - normalize_v3(ty); - - column_vectors_to_mat3(mat, tx, ty, no); + grid_tangent_matrix(mat, &dm_key, x, y, grid); /* scale subgrid coord and calculate displacement */ mul_m3_v3(smat, sco); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index d62e91dbde5..bd3690e2174 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -802,7 +802,7 @@ void ntreeClearPreview(bNodeTree *ntree) /* hack warning! this function is only used for shader previews, and * since it gets called multiple times per pixel for Ztransp we only * add the color once. Preview gets cleared before it starts render though */ -void nodeAddToPreview(bNode *node, float *col, int x, int y, int do_manage) +void nodeAddToPreview(bNode *node, float col[4], int x, int y, int do_manage) { bNodePreview *preview= node->preview; if (preview) { @@ -1313,6 +1313,17 @@ void nodeClearActiveID(bNodeTree *ntree, short idtype) node->flag &= ~NODE_ACTIVE_ID; } +void nodeClearActive(bNodeTree *ntree) +{ + bNode *node; + + if (ntree==NULL) return; + + for (node= ntree->nodes.first; node; node= node->next) + node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_ID); +} + + /* two active flags, ID nodes have special flag for buttons display */ void nodeSetActive(bNodeTree *ntree, bNode *node) { @@ -1889,6 +1900,8 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_color_spill(ttype); register_node_type_cmp_luma_matte(ttype); register_node_type_cmp_doubleedgemask(ttype); + register_node_type_cmp_keyingscreen(ttype); + register_node_type_cmp_keying(ttype); register_node_type_cmp_translate(ttype); register_node_type_cmp_rotate(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b656cb6d8de..1d045d4142d 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -63,6 +63,7 @@ #include "BLI_math.h" #include "BLI_pbvh.h" #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "BKE_main.h" #include "BKE_global.h" @@ -3086,3 +3087,135 @@ MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, int use_default) return clip; } + + +/* + * Find an associated Armature object + */ +static Object *obrel_armature_find(Object *ob) +{ + Object *ob_arm = NULL; + + if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { + ob_arm = ob->parent; + } + else { + ModifierData *mod; + for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) { + if (mod->type == eModifierType_Armature) { + ob_arm = ((ArmatureModifierData *)mod)->object; + } + } + } + + return ob_arm; +} + +static int obrel_is_recursive_child(Object *ob, Object *child) { + Object *par; + for (par = child->parent; par; par = par->parent) { + if (par == ob) { + return TRUE; + } + } + return FALSE; +} + + +static int obrel_list_test(Object *ob) +{ + return ob && !(ob->id.flag & LIB_DOIT); +} + +static void obrel_list_add(LinkNode **links, Object *ob) +{ + BLI_linklist_prepend(links, ob); + ob->id.flag |= LIB_DOIT; +} + +/* + * Iterates over all objects of the given scene. + * Depending on the eObjectSet flag: + * collect either OB_SET_ALL, OB_SET_VISIBLE or OB_SET_SELECTED objects. + * If OB_SET_VISIBLE or OB_SET_SELECTED are collected, + * then also add related objects according to the given includeFilters. + */ +struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter) +{ + LinkNode *links = NULL; + + Base *base; + + /* Remove markers from all objects */ + for (base = scene->base.first; base; base = base->next) { + base->object->id.flag &= ~LIB_DOIT; + } + + /* iterate over all selected and visible objects */ + for (base = scene->base.first; base; base = base->next) { + if (objectSet == OB_SET_ALL) { + // as we get all anyways just add it + Object *ob = base->object; + obrel_list_add(&links, ob); + } + else { + if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) || + (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, base))) + { + Object *ob = base->object; + + if (obrel_list_test(ob)) + obrel_list_add(&links, ob); + + /* parent relationship */ + if (includeFilter & (OB_REL_PARENT | OB_REL_PARENT_RECURSIVE)) { + Object *parent = ob->parent; + if (obrel_list_test(parent)) { + + obrel_list_add(&links, parent); + + /* recursive parent relationship */ + if (includeFilter & OB_REL_PARENT_RECURSIVE) { + parent = parent->parent; + while (obrel_list_test(parent)) { + + obrel_list_add(&links, parent); + parent = parent->parent; + } + } + } + } + + /* child relationship */ + if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) { + Base *local_base; + for (local_base = scene->base.first; local_base; local_base = local_base->next) { + if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) { + + Object *child = local_base->object; + if (obrel_list_test(child)) { + if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && obrel_is_recursive_child(ob, child)) || + (includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob)) + { + obrel_list_add(&links, child); + } + } + } + } + } + + + /* include related armatures */ + if (includeFilter & OB_REL_MOD_ARMATURE) { + Object *arm = obrel_armature_find(ob); + if (obrel_list_test(arm)) { + obrel_list_add(&links, arm); + } + } + + } + } + } + + return links; +} diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index af5b7716bbc..ddf30ecfa81 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2081,7 +2081,8 @@ static ImBuf *seq_render_mask_strip( BKE_mask_rasterize(seq->mask, context.rectx, context.recty, maskbuf, - TRUE, FALSE); + TRUE, + FALSE /*XXX- TODO: make on/off for anti-aliasing*/); fp_src = maskbuf; fp_dst = ibuf->rect_float; @@ -2104,7 +2105,8 @@ static ImBuf *seq_render_mask_strip( BKE_mask_rasterize(seq->mask, context.rectx, context.recty, maskbuf, - TRUE, FALSE); + TRUE, + FALSE /*XXX- TODO: mask on/off for anti-aliasing*/); fp_src = maskbuf; ub_dst = (unsigned char *)ibuf->rect; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index bbb70bb77ff..b32400586a8 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -39,7 +39,7 @@ #include "DNA_gpencil_types.h" #include "DNA_camera_types.h" #include "DNA_movieclip_types.h" -#include "DNA_object_types.h" /* SELECT */ +#include "DNA_object_types.h" /* SELECT */ #include "DNA_scene_types.h" #include "BLI_utildefines.h" @@ -76,7 +76,191 @@ static struct { ListBase tracks; } tracking_clipboard; -/*********************** space transformation functions *************************/ +/*********************** Common functions *************************/ + +static MovieTrackingTrack *tracking_track_duplicate(MovieTrackingTrack *track) +{ + MovieTrackingTrack *new_track; + + new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track"); + + *new_track = *track; + new_track->next = new_track->prev = NULL; + + new_track->markers = MEM_dupallocN(new_track->markers); + + return new_track; +} + +static void tracking_tracks_free(ListBase *tracks) +{ + MovieTrackingTrack *track; + + for (track = tracks->first; track; track = track->next) { + BKE_tracking_track_free(track); + } + + 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); +} + +static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) +{ + MovieTrackingDopesheetChannel *channel; + + channel = dopesheet->channels.first; + while (channel) { + if (channel->segments) { + MEM_freeN(channel->segments); + } + + channel = channel->next; + } + + BLI_freelistN(&dopesheet->channels); + + dopesheet->channels.first = dopesheet->channels.last = NULL; + dopesheet->tot_channel = 0; +} + +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); + + if (tracking->camera.intrinsics) + BKE_tracking_distortion_free(tracking->camera.intrinsics); + + tracking_dopesheet_free(&tracking->dopesheet); +} + +void BKE_tracking_settings_init(MovieTracking *tracking) +{ + tracking->camera.sensor_width = 35.0f; + tracking->camera.pixel_aspect = 1.0f; + tracking->camera.units = CAMERA_UNITS_MM; + + tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION; + tracking->settings.default_minimum_correlation = 0.75; + tracking->settings.default_pattern_size = 11; + tracking->settings.default_search_size = 61; + 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_object_add(tracking, "Camera"); +} + +ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking) +{ + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); + + if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) { + return &object->tracks; + } + + return &tracking->tracks; +} + +MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking) +{ + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); + + return BKE_tracking_object_get_reconstruction(tracking, object); +} + +void BKE_tracking_get_camera_object_matrix(Scene *scene, Object *ob, float mat[4][4]) +{ + if (!ob) { + if (scene->camera) + ob = scene->camera; + else + ob = BKE_scene_camera_find(scene); + } + + if (ob) + BKE_object_where_is_calc_mat4(scene, ob, mat); + else + unit_m4(mat); +} + +void BKE_tracking_get_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; + float viewfac, pixsize, left, right, bottom, top, clipsta, clipend; + float winmat[4][4]; + float ycor = 1.0f / tracking->camera.pixel_aspect; + float shiftx, shifty, winside = MAX2(winx, winy); + + BKE_tracking_camera_shift_get(tracking, winx, winy, &shiftx, &shifty); + + clipsta = 0.1f; + clipend = 1000.0f; + + if (winx >= winy) + viewfac = (lens * winx) / tracking->camera.sensor_width; + else + viewfac = (ycor * lens * winy) / tracking->camera.sensor_width; + + pixsize = clipsta / viewfac; + + left = -0.5f * (float)winx + shiftx * winside; + bottom = -0.5f * (ycor) * (float)winy + shifty * winside; + right = 0.5f * (float)winx + shiftx * winside; + top = 0.5f * (ycor) * (float)winy + shifty * winside; + + left *= pixsize; + right *= pixsize; + bottom *= pixsize; + top *= pixsize; + + perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); + + camera = BKE_tracking_camera_get_reconstructed(tracking, object, framenr); + + if (camera) { + float imat[4][4]; + + invert_m4_m4(imat, camera->mat); + mult_m4_m4m4(mat, winmat, imat); + } + else copy_m4_m4(mat, winmat); +} + +/* **** space transformation functions **** */ /* Three coordinate frames: Frame, Search, and Marker * Two units: Pixels, Unified @@ -100,7 +284,8 @@ static void marker_to_frame_unified(const MovieTrackingMarker *marker, const flo static void marker_unified_to_frame_pixel_coordinates(int frame_width, int frame_height, const MovieTrackingMarker *marker, - const float marker_unified_coords[2], float frame_pixel_coords[2]) + const float marker_unified_coords[2], + float frame_pixel_coords[2]) { marker_to_frame_unified(marker, marker_unified_coords, frame_pixel_coords); unified_to_pixel(frame_width, frame_height, frame_pixel_coords, frame_pixel_coords); @@ -168,6 +353,7 @@ static void get_marker_coords_for_tracking(int frame_width, int frame_height, search_pixel_x[i] = pixel_coords[0]; search_pixel_y[i] = pixel_coords[1]; } + /* Convert the center position (aka "pos"); this is the origin */ unified_coords[0] = 0.0; unified_coords[1] = 0.0; @@ -211,121 +397,81 @@ static void set_marker_coords_from_tracking(int frame_width, int frame_height, M } #endif -/*********************** common functions *************************/ +/*********************** clipboard *************************/ -void BKE_tracking_init_settings(MovieTracking *tracking) +void BKE_tracking_clipboard_free(void) { - tracking->camera.sensor_width = 35.0f; - tracking->camera.pixel_aspect = 1.0f; - tracking->camera.units = CAMERA_UNITS_MM; + MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track; - tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION; - tracking->settings.default_minimum_correlation = 0.75; - tracking->settings.default_pattern_size = 11; - tracking->settings.default_search_size = 61; - tracking->settings.keyframe1 = 1; - tracking->settings.keyframe2 = 30; - tracking->settings.dist = 1; - tracking->settings.object_distance = 1; + while (track) { + next_track = track->next; - tracking->stabilization.scaleinf = 1.0f; - tracking->stabilization.locinf = 1.0f; - tracking->stabilization.rotinf = 1.0f; - tracking->stabilization.maxscale = 2.0f; + BKE_tracking_track_free(track); + MEM_freeN(track); - BKE_tracking_new_object(tracking, "Camera"); + track = next_track; + } } -void BKE_tracking_clamp_marker(MovieTrackingMarker *marker, int event) +void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) { - int a; - float pat_min[2], pat_max[2]; + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + BKE_tracking_clipboard_free(); - if (event == CLAMP_PAT_DIM) { - for (a = 0; a < 2; a++) { - /* search shouldn't be resized smaller than pattern */ - marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); - marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); + while (track) { + if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) { + MovieTrackingTrack *new_track = tracking_track_duplicate(track); + + BLI_addtail(&tracking_clipboard.tracks, new_track); } + + track = track->next; } - else if (event == CLAMP_PAT_POS) { - float dim[2]; +} - sub_v2_v2v2(dim, pat_max, pat_min); +int BKE_tracking_clipboard_has_tracks(void) +{ + return tracking_clipboard.tracks.first != NULL; +} - for (a = 0; a < 2; a++) { - int b; - /* pattern shouldn't be moved outside of search */ - if (pat_min[a] < marker->search_min[a]) { - for (b = 0; b < 4; b++) - marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a]; - } - if (pat_max[a] > marker->search_max[a]) { - for (b = 0; b < 4; b++) - marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a]; - } - } - } - else if (event == CLAMP_SEARCH_DIM) { - for (a = 0; a < 2; a++) { - /* search shouldn't be resized smaller than pattern */ - marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); - marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); - } - } - else if (event == CLAMP_SEARCH_POS) { - float dim[2]; +void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object) +{ + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracking_clipboard.tracks.first; - sub_v2_v2v2(dim, marker->search_max, marker->search_min); + while (track) { + MovieTrackingTrack *new_track = tracking_track_duplicate(track); - for (a = 0; a < 2; a++) { - /* search shouldn't be moved inside pattern */ - if (marker->search_min[a] > pat_min[a]) { - marker->search_min[a] = pat_min[a]; - marker->search_max[a] = marker->search_min[a] + dim[a]; - } - if (marker->search_max[a] < pat_max[a]) { - marker->search_max[a] = pat_max[a]; - marker->search_min[a] = marker->search_max[a] - dim[a]; - } - } - } - else if (event == CLAMP_SEARCH_DIM) { - float dim[2]; - sub_v2_v2v2(dim, pat_max, pat_min); - for (a = 0; a < 2; a++) { - marker->search_min[a] = pat_min[a]; - marker->search_max[a] = pat_max[a]; - } + BLI_addtail(tracksbase, new_track); + BKE_tracking_track_unique_name(tracksbase, new_track); + + track = track->next; } } -void BKE_tracking_track_flag(MovieTrackingTrack *track, int area, int flag, int clear) +/*********************** Tracks *************************/ + +static void tracking_marker_insert_disabled(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, + int before, int overwrite) { - if (area == TRACK_AREA_NONE) - return; + MovieTrackingMarker marker_new; - if (clear) { - if (area & TRACK_AREA_POINT) - track->flag &= ~flag; - if (area & TRACK_AREA_PAT) - track->pat_flag &= ~flag; - if (area & TRACK_AREA_SEARCH) - track->search_flag &= ~flag; - } - else { - if (area & TRACK_AREA_POINT) - track->flag |= flag; - if (area & TRACK_AREA_PAT) - track->pat_flag |= flag; - if (area & TRACK_AREA_SEARCH) - track->search_flag |= flag; - } + marker_new = *ref_marker; + marker_new.flag &= ~MARKER_TRACKED; + marker_new.flag |= MARKER_DISABLED; + + if (before) + marker_new.framenr--; + else + marker_new.framenr++; + + if (overwrite || !BKE_tracking_track_has_marker_at_frame(track, marker_new.framenr)) + BKE_tracking_marker_insert(track, &marker_new); } -MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tracksbase, float x, float y, +MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, ListBase *tracksbase, float x, float y, int framenr, int width, int height) { MovieTrackingTrack *track; @@ -345,6 +491,7 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr track = MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track"); strcpy(track->name, "Track"); + /* fill track's settings from default settings */ track->motion_model = settings->default_motion_model; track->minimum_correlation = settings->default_minimum_correlation; track->margin = settings->default_margin; @@ -370,22 +517,416 @@ MovieTrackingTrack *BKE_tracking_add_track(MovieTracking *tracking, ListBase *tr copy_v2_v2(marker.search_max, search); negate_v2_v2(marker.search_min, search); - BKE_tracking_insert_marker(track, &marker); + BKE_tracking_marker_insert(track, &marker); BLI_addtail(tracksbase, track); - BKE_track_unique_name(tracksbase, track); + BKE_tracking_track_unique_name(tracksbase, track); return track; } -MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, MovieTrackingMarker *marker) +void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track) +{ + BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); +} + +void BKE_tracking_track_free(MovieTrackingTrack *track) +{ + if (track->markers) + MEM_freeN(track->markers); +} + +void BKE_tracking_track_flag_set(MovieTrackingTrack *track, int area, int flag) +{ + if (area == TRACK_AREA_NONE) + return; + + if (area & TRACK_AREA_POINT) + track->flag |= flag; + if (area & TRACK_AREA_PAT) + track->pat_flag |= flag; + if (area & TRACK_AREA_SEARCH) + track->search_flag |= flag; +} + +void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag) +{ + if (area == TRACK_AREA_NONE) + return; + + if (area & TRACK_AREA_POINT) + track->flag &= ~flag; + if (area & TRACK_AREA_PAT) + track->pat_flag &= ~flag; + if (area & TRACK_AREA_SEARCH) + track->search_flag &= ~flag; +} + +int BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr) +{ + return BKE_tracking_marker_get_exact(track, framenr) != 0; +} + +int BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr) +{ + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr); + + return marker && (marker->flag & MARKER_DISABLED) == 0; +} + +void BKE_tracking_track_path_clear(MovieTrackingTrack *track, int ref_frame, int action) +{ + int a; + + if (action == TRACK_CLEAR_REMAINED) { + a = 1; + + while (a < track->markersnr) { + if (track->markers[a].framenr > ref_frame) { + track->markersnr = a; + track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr); + + break; + } + + a++; + } + + if (track->markersnr) + tracking_marker_insert_disabled(track, &track->markers[track->markersnr - 1], FALSE, TRUE); + } + else if (action == TRACK_CLEAR_UPTO) { + a = track->markersnr - 1; + + while (a >= 0) { + if (track->markers[a].framenr <= ref_frame) { + memmove(track->markers, track->markers + a, (track->markersnr - a) * sizeof(MovieTrackingMarker)); + + track->markersnr = track->markersnr - a; + track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr); + + break; + } + + a--; + } + + if (track->markersnr) + tracking_marker_insert_disabled(track, &track->markers[0], TRUE, TRUE); + } + else if (action == TRACK_CLEAR_ALL) { + MovieTrackingMarker *marker, marker_new; + + marker = BKE_tracking_marker_get(track, ref_frame); + marker_new = *marker; + + MEM_freeN(track->markers); + track->markers = NULL; + track->markersnr = 0; + + BKE_tracking_marker_insert(track, &marker_new); + + tracking_marker_insert_disabled(track, &marker_new, TRUE, TRUE); + tracking_marker_insert_disabled(track, &marker_new, FALSE, TRUE); + } +} + +void BKE_tracking_tracks_join(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) +{ + int i = 0, a = 0, b = 0, tot; + MovieTrackingMarker *markers; + + tot = dst_track->markersnr + src_track->markersnr; + markers = MEM_callocN(tot * sizeof(MovieTrackingMarker), "tmp tracking joined tracks"); + + while (a < src_track->markersnr || b < dst_track->markersnr) { + if (b >= dst_track->markersnr) { + markers[i] = src_track->markers[a++]; + } + else if (a >= src_track->markersnr) { + markers[i] = dst_track->markers[b++]; + } + else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) { + markers[i] = src_track->markers[a++]; + } + else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) { + markers[i] = dst_track->markers[b++]; + } + else { + if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) { + if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) { + /* both tracks are enabled on this frame, so find the whole segment + * on which tracks are intersecting and blend tracks using linear + * interpolation to prevent jumps + */ + + MovieTrackingMarker *marker_a, *marker_b; + int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr; + int j, inverse = 0; + + inverse = (b == 0) || + (dst_track->markers[b - 1].flag & MARKER_DISABLED) || + (dst_track->markers[b - 1].framenr != frame - 1); + + /* find length of intersection */ + while (a < src_track->markersnr && b < dst_track->markersnr) { + marker_a = &src_track->markers[a]; + marker_b = &dst_track->markers[b]; + + if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED) + break; + + if (marker_a->framenr != frame || marker_b->framenr != frame) + break; + + frame++; + len++; + a++; + b++; + } + + a = start_a; + b = start_b; + + /* linear interpolation for intersecting frames */ + for (j = 0; j < len; j++) { + float fac = 0.5f; + + if (len > 1) + fac = 1.0f / (len - 1) * j; + + if (inverse) + fac = 1.0f - fac; + + marker_a = &src_track->markers[a]; + marker_b = &dst_track->markers[b]; + + markers[i] = dst_track->markers[b]; + interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac); + a++; + b++; + i++; + } + + /* this values will be incremented at the end of the loop cycle */ + a--; b--; i--; + } + else { + markers[i] = src_track->markers[a]; + } + } + else { + markers[i] = dst_track->markers[b]; + } + + a++; + b++; + } + + i++; + } + + MEM_freeN(dst_track->markers); + + dst_track->markers = MEM_callocN(i * sizeof(MovieTrackingMarker), "tracking joined tracks"); + memcpy(dst_track->markers, markers, i * sizeof(MovieTrackingMarker)); + + dst_track->markersnr = i; + + MEM_freeN(markers); +} + +MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieTrackingObject *object, const char *name) +{ + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; + + while (track) { + if (!strcmp(track->name, name)) + return track; + + track = track->next; + } + + return NULL; +} + +MovieTrackingTrack *BKE_tracking_track_get_indexed(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r) +{ + MovieTrackingObject *object; + int cur = 1; + + object = tracking->objects.first; + while (object) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; + + while (track) { + if (track->flag & TRACK_HAS_BUNDLE) { + if (cur == tracknr) { + *tracksbase_r = tracksbase; + return track; + } + + cur++; + } + + track = track->next; + } + + object = object->next; + } + + *tracksbase_r = NULL; + + return NULL; +} + +MovieTrackingTrack *BKE_tracking_track_get_active(MovieTracking *tracking) +{ + ListBase *tracksbase; + + if (!tracking->act_track) + return NULL; + + tracksbase = BKE_tracking_get_active_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; +} + +static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) +{ + bGPDlayer *layer; + + if (!track->gpd) + return NULL; + + layer = track->gpd->layers.first; + + while (layer) { + if (layer->flag & GP_LAYER_ACTIVE) { + bGPDframe *frame = layer->frames.first; + int ok = FALSE; + + while (frame) { + if (frame->strokes.first) { + ok = TRUE; + } + + frame = frame->next; + } + + if (ok) + return layer; + } + + layer = layer->next; + } + + return NULL; +} + +static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height, + MovieTrackingMarker *marker, bGPDlayer *layer, + float *mask, int mask_width, int mask_height) +{ + bGPDframe *frame = layer->frames.first; + + while (frame) { + bGPDstroke *stroke = frame->strokes.first; + + while (stroke) { + bGPDspoint *stroke_points = stroke->points; + float *mask_points, *fp; + int i; + + if (stroke->flag & GP_STROKE_2DSPACE) { + fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float), + "track mask rasterization points"); + + for (i = 0; i < stroke->totpoints; i++, fp += 2) { + fp[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width / mask_width; + fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height; + } + + /* TODO: add an option to control wether AA is enabled or not */ + PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE); + + MEM_freeN(mask_points); + } + + stroke = stroke->next; + } + + frame = frame->next; + } +} + +float *BKE_tracking_track_get_mask(int frame_width, int frame_height, + MovieTrackingTrack *track, MovieTrackingMarker *marker) +{ + float *mask = NULL; + bGPDlayer *layer = track_mask_gpencil_layer_get(track); + int mask_width, mask_height; + + mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width; + mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height; + + if (layer) { + mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask"); + + track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer, + mask, mask_width, mask_height); + } + + return mask; +} + +/* area - which part of marker should be selected. see TRACK_AREA_* constants */ +void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend) +{ + if (extend) { + BKE_tracking_track_flag_set(track, area, SELECT); + } + else { + MovieTrackingTrack *cur = tracksbase->first; + + while (cur) { + if ((cur->flag & TRACK_HIDDEN) == 0) { + if (cur == track) { + BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT); + BKE_tracking_track_flag_set(cur, area, SELECT); + } + else { + BKE_tracking_track_flag_clear(cur, TRACK_AREA_ALL, SELECT); + } + } + + cur = cur->next; + } + } +} + +void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area) +{ + BKE_tracking_track_flag_clear(track, area, SELECT); +} + +/*********************** Marker *************************/ + +MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker) { MovieTrackingMarker *old_marker = NULL; if (track->markersnr) - old_marker = BKE_tracking_exact_marker(track, marker->framenr); + old_marker = BKE_tracking_marker_get_exact(track, marker->framenr); if (old_marker) { + /* simply replace settings for already allocated marker */ *old_marker = *marker; return old_marker; @@ -393,6 +934,7 @@ MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, Movie else { int a = track->markersnr; + /* find position in array where to add new marker */ while (a--) { if (track->markers[a].framenr < marker->framenr) break; @@ -401,12 +943,15 @@ MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, Movie track->markersnr++; if (track->markers) - track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr); + track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr); else track->markers = MEM_callocN(sizeof(MovieTrackingMarker), "MovieTracking markers"); + /* shift array to "free" space for new marker */ memmove(track->markers + a + 2, track->markers + a + 1, (track->markersnr - a - 2) * sizeof(MovieTrackingMarker)); + + /* put new marker */ track->markers[a + 1] = *marker; track->last_marker = a + 1; @@ -415,7 +960,7 @@ MovieTrackingMarker *BKE_tracking_insert_marker(MovieTrackingTrack *track, Movie } } -void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr) +void BKE_tracking_marker_delete(MovieTrackingTrack *track, int framenr) { int a = 0; @@ -440,17 +985,73 @@ void BKE_tracking_delete_marker(MovieTrackingTrack *track, int framenr) } } -void BKE_tracking_marker_pattern_minmax(MovieTrackingMarker *marker, float min[2], float max[2]) +void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) { - INIT_MINMAX2(min, max); + int a; + float pat_min[2], pat_max[2]; - DO_MINMAX2(marker->pattern_corners[0], min, max); - DO_MINMAX2(marker->pattern_corners[1], min, max); - DO_MINMAX2(marker->pattern_corners[2], min, max); - DO_MINMAX2(marker->pattern_corners[3], min, max); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + + if (event == CLAMP_PAT_DIM) { + for (a = 0; a < 2; a++) { + /* search shouldn't be resized smaller than pattern */ + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); + } + } + else if (event == CLAMP_PAT_POS) { + float dim[2]; + + sub_v2_v2v2(dim, pat_max, pat_min); + + for (a = 0; a < 2; a++) { + int b; + /* pattern shouldn't be moved outside of search */ + if (pat_min[a] < marker->search_min[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a]; + } + if (pat_max[a] > marker->search_max[a]) { + for (b = 0; b < 4; b++) + marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a]; + } + } + } + else if (event == CLAMP_SEARCH_DIM) { + for (a = 0; a < 2; a++) { + /* search shouldn't be resized smaller than pattern */ + marker->search_min[a] = MIN2(pat_min[a], marker->search_min[a]); + marker->search_max[a] = MAX2(pat_max[a], marker->search_max[a]); + } + } + else if (event == CLAMP_SEARCH_POS) { + float dim[2]; + + sub_v2_v2v2(dim, marker->search_max, marker->search_min); + + for (a = 0; a < 2; a++) { + /* search shouldn't be moved inside pattern */ + if (marker->search_min[a] > pat_min[a]) { + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = marker->search_min[a] + dim[a]; + } + if (marker->search_max[a] < pat_max[a]) { + marker->search_max[a] = pat_max[a]; + marker->search_min[a] = marker->search_max[a] - dim[a]; + } + } + } + else if (event == CLAMP_SEARCH_DIM) { + float dim[2]; + sub_v2_v2v2(dim, pat_max, pat_min); + for (a = 0; a < 2; a++) { + marker->search_min[a] = pat_min[a]; + marker->search_max[a] = pat_max[a]; + } + } } -MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int framenr) +MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr) { int a = track->markersnr - 1; @@ -495,9 +1096,19 @@ MovieTrackingMarker *BKE_tracking_get_marker(MovieTrackingTrack *track, int fram return NULL; } -MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int framenr) +MovieTrackingMarker *BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr) +{ + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + + if (marker->framenr != framenr) + return NULL; + + return marker; +} + +MovieTrackingMarker *BKE_tracking_marker_ensure(MovieTrackingTrack *track, int framenr) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); if (marker->framenr != framenr) { MovieTrackingMarker marker_new; @@ -505,352 +1116,663 @@ MovieTrackingMarker *BKE_tracking_ensure_marker(MovieTrackingTrack *track, int f marker_new = *marker; marker_new.framenr = framenr; - BKE_tracking_insert_marker(track, &marker_new); - marker = BKE_tracking_get_marker(track, framenr); + BKE_tracking_marker_insert(track, &marker_new); + marker = BKE_tracking_marker_get(track, framenr); } return marker; } -MovieTrackingMarker *BKE_tracking_exact_marker(MovieTrackingTrack *track, int framenr) +void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2]) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); - - if (marker->framenr != framenr) - return NULL; + INIT_MINMAX2(min, max); - return marker; + DO_MINMAX2(marker->pattern_corners[0], min, max); + DO_MINMAX2(marker->pattern_corners[1], min, max); + DO_MINMAX2(marker->pattern_corners[2], min, max); + DO_MINMAX2(marker->pattern_corners[3], min, max); } -int BKE_tracking_has_marker(MovieTrackingTrack *track, int framenr) +/*********************** Object *************************/ + +MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name) { - return BKE_tracking_exact_marker(track, framenr) != 0; + 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; + + object->scale = 1.0f; + + BKE_tracking_object_unique_name(tracking, object); + + return object; } -int BKE_tracking_has_enabled_marker(MovieTrackingTrack *track, int framenr) +void BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object) { - MovieTrackingMarker *marker = BKE_tracking_exact_marker(track, framenr); + MovieTrackingTrack *track; + int index = BLI_findindex(&tracking->objects, object); - return marker && (marker->flag & MARKER_DISABLED) == 0; + 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_free_track(MovieTrackingTrack *track) +void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object) { - if (track->markers) - MEM_freeN(track->markers); + BLI_uniquename(&tracking->objects, object, "Object", '.', + offsetof(MovieTrackingObject, name), sizeof(object->name)); } -static void put_disabled_marker(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, int before, int overwrite) +MovieTrackingObject *BKE_tracking_object_get_named(MovieTracking *tracking, const char *name) { - MovieTrackingMarker marker_new; + MovieTrackingObject *object = tracking->objects.first; - marker_new = *ref_marker; - marker_new.flag &= ~MARKER_TRACKED; - marker_new.flag |= MARKER_DISABLED; + while (object) { + if (!strcmp(object->name, name)) + return object; - if (before) - marker_new.framenr--; - else - marker_new.framenr++; + object = object->next; + } - if (!BKE_tracking_has_marker(track, marker_new.framenr) || overwrite) - BKE_tracking_insert_marker(track, &marker_new); + return NULL; } -void BKE_tracking_clear_path(MovieTrackingTrack *track, int ref_frame, int action) +MovieTrackingObject *BKE_tracking_object_get_active(MovieTracking *tracking) { - int a; + return BLI_findlink(&tracking->objects, tracking->objectnr); +} - if (action == TRACK_CLEAR_REMAINED) { - a = 1; +MovieTrackingObject *BKE_tracking_object_get_camera(MovieTracking *tracking) +{ + MovieTrackingObject *object = tracking->objects.first; - while (a < track->markersnr) { - if (track->markers[a].framenr > ref_frame) { - track->markersnr = a; - track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr); + while (object) { + if (object->flag & TRACKING_OBJECT_CAMERA) + return object; - break; - } + object = object->next; + } - a++; - } + return NULL; +} - if (track->markersnr) - put_disabled_marker(track, &track->markers[track->markersnr - 1], 0, 1); +ListBase *BKE_tracking_object_get_tracks(MovieTracking *tracking, MovieTrackingObject *object) +{ + if (object->flag & TRACKING_OBJECT_CAMERA) { + return &tracking->tracks; } - else if (action == TRACK_CLEAR_UPTO) { - a = track->markersnr - 1; - - while (a >= 0) { - if (track->markers[a].framenr <= ref_frame) { - memmove(track->markers, track->markers + a, (track->markersnr - a) * sizeof(MovieTrackingMarker)); - track->markersnr = track->markersnr - a; - track->markers = MEM_reallocN(track->markers, sizeof(MovieTrackingMarker)*track->markersnr); + return &object->tracks; +} - break; - } +MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(MovieTracking *tracking, + MovieTrackingObject *object) +{ + if (object->flag & TRACKING_OBJECT_CAMERA) { + return &tracking->reconstruction; + } - a--; - } + return &object->reconstruction; +} - if (track->markersnr) - put_disabled_marker(track, &track->markers[0], 1, 1); - } - else if (action == TRACK_CLEAR_ALL) { - MovieTrackingMarker *marker, marker_new; +/*********************** Camera *************************/ - marker = BKE_tracking_get_marker(track, ref_frame); - marker_new = *marker; +static int reconstructed_camera_index_get(MovieTrackingReconstruction *reconstruction, int framenr, int nearest) +{ + MovieReconstructedCamera *cameras = reconstruction->cameras; + int a = 0, d = 1; - MEM_freeN(track->markers); - track->markers = NULL; - track->markersnr = 0; + if (!reconstruction->camnr) + return -1; - BKE_tracking_insert_marker(track, &marker_new); + if (framenr < cameras[0].framenr) { + if (nearest) + return 0; + else + return -1; + } - put_disabled_marker(track, &marker_new, 1, 1); - put_disabled_marker(track, &marker_new, 0, 1); + if (framenr > cameras[reconstruction->camnr - 1].framenr) { + if (nearest) + return reconstruction->camnr - 1; + else + return -1; } -} -void BKE_tracking_join_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) -{ - int i = 0, a = 0, b = 0, tot; - MovieTrackingMarker *markers; + if (reconstruction->last_camera < reconstruction->camnr) + a = reconstruction->last_camera; - tot = dst_track->markersnr + src_track->markersnr; - markers = MEM_callocN(tot * sizeof(MovieTrackingMarker), "tmp tracking joined tracks"); + if (cameras[a].framenr >= framenr) + d = -1; - while (a < src_track->markersnr || b < dst_track->markersnr) { - if (b >= dst_track->markersnr) { - markers[i] = src_track->markers[a++]; - } - else if (a >= src_track->markersnr) { - markers[i] = dst_track->markers[b++]; + while (a >= 0 && a < reconstruction->camnr) { + int cfra = cameras[a].framenr; + + /* check if needed framenr was "skipped" -- no data for requested frame */ + + if (d > 0 && cfra > framenr) { + /* interpolate with previous position */ + if (nearest) + return a - 1; + else + break; } - else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) { - markers[i] = src_track->markers[a++]; + + if (d < 0 && cfra < framenr) { + /* interpolate with next position */ + if (nearest) + return a; + else + break; } - else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) { - markers[i] = dst_track->markers[b++]; + + if (cfra == framenr) { + reconstruction->last_camera = a; + + return a; } - else { - if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) { - if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) { - /* both tracks are enabled on this frame, so find the whole segment - * on which tracks are intersecting and blend tracks using linear - * interpolation to prevent jumps - */ - MovieTrackingMarker *marker_a, *marker_b; - int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr; - int j, inverse = 0; + a += d; + } - inverse = (b == 0) || - (dst_track->markers[b - 1].flag & MARKER_DISABLED) || - (dst_track->markers[b - 1].framenr != frame - 1); + return -1; +} - /* find length of intersection */ - while (a < src_track->markersnr && b < dst_track->markersnr) { - marker_a = &src_track->markers[a]; - marker_b = &dst_track->markers[b]; +static void reconstructed_camera_scale_set(MovieTrackingObject *object, float mat[4][4]) +{ + if ((object->flag & TRACKING_OBJECT_CAMERA) == 0) { + float smat[4][4]; - if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED) - break; + scale_m4_fl(smat, 1.0f / object->scale); + mult_m4_m4m4(mat, mat, smat); + } +} - if (marker_a->framenr != frame || marker_b->framenr != frame) - break; - frame++; - len++; - a++; - b++; - } +/* converts principal offset from center to offset of blender's camera */ +void BKE_tracking_camera_shift_get(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty) +{ + /* indeed in both of cases it should be winx -- it's just how camera shift works for blender's camera */ + *shiftx = (0.5f * winx - tracking->camera.principal[0]) / winx; + *shifty = (0.5f * winy - tracking->camera.principal[1]) / winx; +} - a = start_a; - b = start_b; +void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height) +{ + float focal = tracking->camera.focal; - /* linear interpolation for intersecting frames */ - for (j = 0; j < len; j++) { - float fac = 0.5f; + camera->sensor_x = tracking->camera.sensor_width; + camera->sensor_fit = CAMERA_SENSOR_FIT_AUTO; + camera->lens = focal * camera->sensor_x / width; - if (len > 1) - fac = 1.0f / (len - 1) * j; + scene->r.xsch = width * tracking->camera.pixel_aspect; + scene->r.ysch = height; - if (inverse) - fac = 1.0f - fac; + scene->r.xasp = 1.0f; + scene->r.yasp = 1.0f; - marker_a = &src_track->markers[a]; - marker_b = &dst_track->markers[b]; + BKE_tracking_camera_shift_get(tracking, width, height, &camera->shiftx, &camera->shifty); +} - markers[i] = dst_track->markers[b]; - interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac); - a++; - b++; - i++; - } +MovieReconstructedCamera *BKE_tracking_camera_get_reconstructed(MovieTracking *tracking, + MovieTrackingObject *object, int framenr) +{ + MovieTrackingReconstruction *reconstruction; + int a; - /* this values will be incremented at the end of the loop cycle */ - a--; b--; i--; - } - else markers[i] = src_track->markers[a]; - } - else markers[i] = dst_track->markers[b]; + reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + a = reconstructed_camera_index_get(reconstruction, framenr, FALSE); - a++; - b++; - } + if (a == -1) + return NULL; - i++; - } + return &reconstruction->cameras[a]; +} - MEM_freeN(dst_track->markers); +void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking, MovieTrackingObject *object, + int framenr, float mat[4][4]) +{ + MovieTrackingReconstruction *reconstruction; + MovieReconstructedCamera *cameras; + int a; - dst_track->markers = MEM_callocN(i*sizeof(MovieTrackingMarker), "tracking joined tracks"); - memcpy(dst_track->markers, markers, i*sizeof(MovieTrackingMarker)); + reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + cameras = reconstruction->cameras; + a = reconstructed_camera_index_get(reconstruction, framenr, 1); - dst_track->markersnr = i; + if (a == -1) { + unit_m4(mat); - MEM_freeN(markers); -} + return; + } -static void tracking_tracks_free(ListBase *tracks) -{ - MovieTrackingTrack *track; + if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) { + float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr); - for (track = tracks->first; track; track = track->next) { - BKE_tracking_free_track(track); + blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t); + } + else { + copy_m4_m4(mat, cameras[a].mat); } - BLI_freelistN(tracks); + reconstructed_camera_scale_set(object, mat); } -static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction) +/*********************** Distortion/Undistortion *************************/ + +MovieDistortion *BKE_tracking_distortion_new(void) { - if (reconstruction->cameras) - MEM_freeN(reconstruction->cameras); + MovieDistortion *distortion; + + distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); + + return distortion; } -static void tracking_object_free(MovieTrackingObject *object) +void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, + int calibration_width, int calibration_height) { - tracking_tracks_free(&object->tracks); - tracking_reconstruction_free(&object->reconstruction); + MovieTrackingCamera *camera = &tracking->camera; + float aspy = 1.0f / tracking->camera.pixel_aspect; + +#ifdef WITH_LIBMV + if (!distortion->intrinsics) { + distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal, + camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, + calibration_width, calibration_height * aspy); + } + else { + libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal, + camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, + calibration_width, calibration_height * aspy); + } +#else + (void) distortion; + (void) calibration_width; + (void) calibration_height; + (void) camera; + (void) aspy; +#endif } -static void tracking_objects_free(ListBase *objects) +MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion) { - MovieTrackingObject *object; + MovieDistortion *new_distortion; - for (object = objects->first; object; object = object->next) - tracking_object_free(object); + new_distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); - BLI_freelistN(objects); +#ifdef WITH_LIBMV + new_distortion->intrinsics = libmv_CameraIntrinsicsCopy(distortion->intrinsics); +#else + (void) distortion; +#endif + + return new_distortion; } -static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) +ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, ImBuf *ibuf, + int calibration_width, int calibration_height, float overscan, int undistort) { - MovieTrackingDopesheetChannel *channel; + ImBuf *resibuf; - channel = dopesheet->channels.first; - while (channel) { - if (channel->segments) { - MEM_freeN(channel->segments); + BKE_tracking_distortion_update(distortion, tracking, calibration_width, calibration_height); + + resibuf = IMB_dupImBuf(ibuf); + +#ifdef WITH_LIBMV + if (ibuf->rect_float) { + if (undistort) { + libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics, + ibuf->rect_float, resibuf->rect_float, + ibuf->x, ibuf->y, overscan, ibuf->channels); + } + else { + libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics, + ibuf->rect_float, resibuf->rect_float, + ibuf->x, ibuf->y, overscan, ibuf->channels); } - channel = channel->next; + resibuf->userflags |= IB_RECT_INVALID; + } + else { + if (undistort) { + libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics, + (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, + ibuf->x, ibuf->y, overscan, ibuf->channels); + } + else { + libmv_CameraIntrinsicsDistortByte(distortion->intrinsics, + (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, + ibuf->x, ibuf->y, overscan, ibuf->channels); + } } +#else + (void) overscan; + (void) undistort; - BLI_freelistN(&dopesheet->channels); + if (ibuf->rect_float) { + resibuf->userflags |= IB_RECT_INVALID; + } +#endif - dopesheet->channels.first = dopesheet->channels.last = NULL; - dopesheet->tot_channel = 0; + return resibuf; } -void BKE_tracking_free(MovieTracking *tracking) +void BKE_tracking_distortion_free(MovieDistortion *distortion) { - tracking_tracks_free(&tracking->tracks); - tracking_reconstruction_free(&tracking->reconstruction); - tracking_objects_free(&tracking->objects); +#ifdef WITH_LIBMV + libmv_CameraIntrinsicsDestroy(distortion->intrinsics); +#endif - if (tracking->stabilization.scaleibuf) - IMB_freeImBuf(tracking->stabilization.scaleibuf); + MEM_freeN(distortion); +} - if (tracking->camera.intrinsics) - BKE_tracking_distortion_destroy(tracking->camera.intrinsics); +void BKE_tracking_distort_v2(MovieTracking *tracking, float co[2], float nco[2]) +{ + MovieTrackingCamera *camera = &tracking->camera; - tracking_dopesheet_free(&tracking->dopesheet); +#ifdef WITH_LIBMV + double x, y; + float aspy = 1.0f / tracking->camera.pixel_aspect; + + /* normalize coords */ + x = (co[0] - camera->principal[0]) / camera->focal; + y = (co[1] - camera->principal[1] * aspy) / camera->focal; + + libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, x, y, &x, &y); + + /* result is in image coords already */ + nco[0] = x; + nco[1] = y; +#else + (void) camera; + (void) co; + (void) nco; +#endif } -static MovieTrackingTrack *duplicate_track(MovieTrackingTrack *track) +void BKE_tracking_undistort_v2(MovieTracking *tracking, float co[2], float nco[2]) { - MovieTrackingTrack *new_track; + MovieTrackingCamera *camera = &tracking->camera; - new_track = MEM_callocN(sizeof(MovieTrackingTrack), "tracksMapMerge new_track"); +#ifdef WITH_LIBMV + double x = co[0], y = co[1]; + float aspy = 1.0f / tracking->camera.pixel_aspect; - *new_track = *track; - new_track->next = new_track->prev = NULL; + libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, + camera->k1, camera->k2, camera->k3, x, y, &x, &y); - new_track->markers = MEM_dupallocN(new_track->markers); + nco[0] = x * camera->focal + camera->principal[0]; + nco[1] = y * camera->focal + camera->principal[1] * aspy; +#else + (void) camera; + (void) co; + (void) nco; +#endif +} - return new_track; +ImBuf *BKE_tracking_undistort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width, + int calibration_height, float overscan) +{ + MovieTrackingCamera *camera = &tracking->camera; + + if (camera->intrinsics == NULL) + camera->intrinsics = BKE_tracking_distortion_new(); + + return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width, + calibration_height, overscan, TRUE); } -/*********************** clipboard *************************/ +ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width, + int calibration_height, float overscan) +{ + MovieTrackingCamera *camera = &tracking->camera; + + if (camera->intrinsics == NULL) + camera->intrinsics = BKE_tracking_distortion_new(); -void BKE_tracking_free_clipboard(void) + return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width, + calibration_height, overscan, FALSE); +} + +/*********************** Image sampling *************************/ + +static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) { - MovieTrackingTrack *track = tracking_clipboard.tracks.first, *next_track; + BKE_tracking_disable_channels(ibuf, track->flag & TRACK_DISABLE_RED, + track->flag & TRACK_DISABLE_GREEN, + track->flag & TRACK_DISABLE_BLUE, grayscale); +} - while (track) { - next_track = track->next; +ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf, + MovieTrackingTrack *track, MovieTrackingMarker *marker, + int use_mask, int num_samples_x, int num_samples_y, + float pos[2]) +{ +#ifdef WITH_LIBMV + ImBuf *pattern_ibuf; + double src_pixel_x[5], src_pixel_y[5]; + double warped_position_x, warped_position_y; + float *mask = NULL; - BKE_tracking_free_track(track); - MEM_freeN(track); + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; - track = next_track; + if (!search_ibuf->rect_float) { + IMB_float_from_rect(search_ibuf); + } + + get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y); + + if (use_mask) { + mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker); + } + + libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4, + src_pixel_x, src_pixel_y, num_samples_x, + num_samples_y, mask, pattern_ibuf->rect_float, + &warped_position_x, &warped_position_y); + + if (pos) { + pos[0] = warped_position_x; + pos[1] = warped_position_y; + } + + if (mask) { + MEM_freeN(mask); } + + return pattern_ibuf; +#else + ImBuf *pattern_ibuf; + + /* real sampling requires libmv, but areas are supposing pattern would be + * sampled if search area does exists, so we'll need to create empty + * pattern area here to prevent adding NULL-checks all over just to deal + * with situation when lubmv is disabled + */ + + (void) frame_width; + (void) frame_height; + (void) search_ibuf; + (void) marker; + (void) track; + (void) use_mask; + + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); + + pos[0] = num_samples_x / 2.0f; + pos[1] = num_samples_y / 2.0f; + + return pattern_ibuf; +#endif } -void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) +ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int anchored, int disable_channels) { - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; + ImBuf *pattern_ibuf, *search_ibuf; + float pat_min[2], pat_max[2]; + int num_samples_x, num_samples_y; - BKE_tracking_free_clipboard(); + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - while (track) { - if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) { - MovieTrackingTrack *new_track = duplicate_track(track); + num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x; + num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y; - BLI_addtail(&tracking_clipboard.tracks, new_track); - } + search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); - track = track->next; - } + pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker, + FALSE, num_samples_x, num_samples_y, NULL); + + IMB_freeImBuf(search_ibuf); + + return pattern_ibuf; } -int BKE_tracking_clipboard_has_tracks(void) +ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int anchored, int disable_channels) { - return tracking_clipboard.tracks.first != NULL; + ImBuf *searchibuf; + int x, y, w, h; + float search_origin[2]; + + get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin); + + x = search_origin[0]; + y = search_origin[1]; + + if (anchored) { + x += track->offset[0] * ibuf->x; + y += track->offset[1] * ibuf->y; + } + + w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; + h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; + + searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); + searchibuf->profile = ibuf->profile; + + IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); + + if (disable_channels) { + if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || + (track->flag & TRACK_DISABLE_RED) || + (track->flag & TRACK_DISABLE_GREEN) || + (track->flag & TRACK_DISABLE_BLUE)) + { + disable_imbuf_channels(searchibuf, track, TRUE); + } + } + + return searchibuf; } -void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingObject *object) +/* zap channels from the imbuf that are disabled by the user. this can lead to + * better tracks sometimes. however, instead of simply zeroing the channels + * out, do a partial grayscale conversion so the display is better. + */ +void BKE_tracking_disable_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, + int grayscale) { - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - MovieTrackingTrack *track = tracking_clipboard.tracks.first; + int x, y; + float scale; - while (track) { - MovieTrackingTrack *new_track = duplicate_track(track); + if (!disable_red && !disable_green && !disable_blue && !grayscale) + return; - BLI_addtail(tracksbase, new_track); - BKE_track_unique_name(tracksbase, new_track); + /* if only some components are selected, it's important to rescale the result + * appropriately so that e.g. if only blue is selected, it's not zeroed out. + */ + scale = (disable_red ? 0.0f : 0.2126f) + + (disable_green ? 0.0f : 0.7152f) + + (disable_blue ? 0.0f : 0.0722f); - track = track->next; + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + int pixel = ibuf->x * y + x; + + if (ibuf->rect_float) { + float *rrgbf = ibuf->rect_float + pixel * 4; + float r = disable_red ? 0.0f : rrgbf[0]; + float g = disable_green ? 0.0f : rrgbf[1]; + float b = disable_blue ? 0.0f : rrgbf[2]; + + if (grayscale) { + float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale; + + rrgbf[0] = rrgbf[1] = rrgbf[2] = gray; + } + else { + rrgbf[0] = r; + rrgbf[1] = g; + rrgbf[2] = b; + } + } + else { + char *rrgb = (char *)ibuf->rect + pixel * 4; + char r = disable_red ? 0 : rrgb[0]; + char g = disable_green ? 0 : rrgb[1]; + char b = disable_blue ? 0 : rrgb[2]; + + if (grayscale) { + float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale; + + rrgb[0] = rrgb[1] = rrgb[2] = gray; + } + else { + rrgb[0] = r; + rrgb[1] = g; + rrgb[2] = b; + } + } + } } + + if (ibuf->rect_float) + ibuf->userflags |= IB_RECT_INVALID; } -/*********************** tracks map *************************/ +/*********************** Tracks map *************************/ typedef struct TracksMap { char object_name[MAX_NAME]; @@ -877,27 +1799,27 @@ static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num map->num_tracks = num_tracks; map->customdata_size = customdata_size; - map->tracks = MEM_callocN(sizeof(MovieTrackingTrack)*num_tracks, "TrackingsMap tracks"); + map->tracks = MEM_callocN(sizeof(MovieTrackingTrack) * num_tracks, "TrackingsMap tracks"); if (customdata_size) - map->customdata = MEM_callocN(customdata_size*num_tracks, "TracksMap customdata"); + map->customdata = MEM_callocN(customdata_size * num_tracks, "TracksMap customdata"); map->hash = BLI_ghash_ptr_new("TracksMap hash"); return map; } -static int tracks_map_size(TracksMap *map) +static int tracks_map_get_size(TracksMap *map) { return map->num_tracks; } -static void tracks_map_get(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata) +static void tracks_map_get_indexed_element(TracksMap *map, int index, MovieTrackingTrack **track, void **customdata) { *track = &map->tracks[index]; if (map->customdata) - *customdata = &map->customdata[index*map->customdata_size]; + *customdata = &map->customdata[index * map->customdata_size]; } static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *customdata) @@ -909,7 +1831,7 @@ static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *c map->tracks[map->ptr] = new_track; if (customdata) - memcpy(&map->customdata[map->ptr*map->customdata_size], customdata, map->customdata_size); + memcpy(&map->customdata[map->ptr * map->customdata_size], customdata, map->customdata_size); BLI_ghash_insert(map->hash, &map->tracks[map->ptr], track); @@ -919,7 +1841,7 @@ 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); + MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); MovieTrackingTrack *rot_track = tracking->stabilization.rot_track; ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL}; ListBase *old_tracks; @@ -929,11 +1851,11 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) old_tracks = &tracking->tracks; } else { - MovieTrackingObject *object = BKE_tracking_named_object(tracking, map->object_name); + MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name); if (!object) { /* object was deleted by user, create new one */ - object = BKE_tracking_new_object(tracking, map->object_name); + object = BKE_tracking_object_add(tracking, map->object_name); } old_tracks = &object->tracks; @@ -972,20 +1894,20 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) track->pat_flag = cur->pat_flag; track->search_flag = cur->search_flag; - BKE_tracking_free_track(cur); + BKE_tracking_track_free(cur); BLI_freelinkN(old_tracks, cur); } } - new_track = duplicate_track(track); + new_track = tracking_track_duplicate(track); BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */ BLI_ghash_insert(map->hash, track, new_track); - if (replace_sel) /* update current selection in clip */ + if (replace_sel) /* update current selection in clip */ tracking->act_track = new_track; - if (replace_rot) /* update track used for rotation stabilization */ + if (replace_rot) /* update track used for rotation stabilization */ tracking->stabilization.rot_track = new_track; BLI_addtail(&tracks, new_track); @@ -1020,7 +1942,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) *old_tracks = new_tracks; } -static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *customdata)) +static void tracks_map_free(TracksMap *map, void (*customdata_free)(void *customdata)) { int i = 0; @@ -1028,9 +1950,9 @@ static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *custo for (i = 0; i < map->num_tracks; i++) { if (map->customdata && customdata_free) - customdata_free(&map->customdata[i*map->customdata_size]); + customdata_free(&map->customdata[i * map->customdata_size]); - BKE_tracking_free_track(&map->tracks[i]); + BKE_tracking_track_free(&map->tracks[i]); } if (map->customdata) @@ -1040,7 +1962,7 @@ static void tracks_map_free(TracksMap *map, void (*customdata_free) (void *custo MEM_freeN(map); } -/*********************** tracking *************************/ +/*********************** 2D tracking *************************/ typedef struct TrackContext { #ifdef WITH_LIBMV @@ -1052,6 +1974,8 @@ typedef struct TrackContext { int search_area_height; int search_area_width; int framenr; + + float *mask; #else int pad; #endif @@ -1071,16 +1995,33 @@ typedef struct MovieTrackingContext { int sync_frame; } MovieTrackingContext; +static void track_context_free(void *customdata) +{ + TrackContext *track_context = (TrackContext *)customdata; + +#if WITH_LIBMV + if (track_context->search_area) + MEM_freeN(track_context->search_area); + + if (track_context->mask) + MEM_freeN(track_context->mask); + +#else + (void)track_context; +#endif +} + MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, short backwards, short sequence) { MovieTrackingContext *context = MEM_callocN(sizeof(MovieTrackingContext), "trackingContext"); MovieTracking *tracking = &clip->tracking; MovieTrackingSettings *settings = &tracking->settings; - ListBase *tracksbase = BKE_tracking_get_tracks(tracking); + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); MovieTrackingTrack *track; - MovieTrackingObject *object = BKE_tracking_active_object(tracking); + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); int num_tracks = 0; + context->clip = clip; context->settings = *settings; context->backwards = backwards; context->sync_frame = user->framenr; @@ -1092,7 +2033,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u while (track) { if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) { int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) num_tracks++; @@ -1101,6 +2042,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u track = track->next; } + /* create tracking contextx for all tracks which would be tracked */ if (num_tracks) { int width, height; @@ -1114,7 +2056,7 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u while (track) { if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) { int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); if ((marker->flag & MARKER_DISABLED) == 0) { TrackContext track_context; @@ -1127,8 +2069,6 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u } } - context->clip = clip; - /* store needed clip flags passing to get_buffer functions * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip * only in case Proxy/Timecode flag is set, so store this flag to use @@ -1150,19 +2090,6 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u return context; } -static void track_context_free(void *customdata) -{ - TrackContext *track_context = (TrackContext *)customdata; - -#if WITH_LIBMV - if (track_context->search_area) - MEM_freeN(track_context->search_area); - -#else - (void) track_context; -#endif -} - void BKE_tracking_context_free(MovieTrackingContext *context) { if (!context->sequence) @@ -1173,289 +2100,32 @@ void BKE_tracking_context_free(MovieTrackingContext *context) MEM_freeN(context); } -/* zap channels from the imbuf that are disabled by the user. this can lead to - * better tracks sometimes. however, instead of simply zeroing the channels - * out, do a partial grayscale conversion so the display is better. - */ -void BKE_tracking_disable_imbuf_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, - int grayscale) -{ - int x, y; - float scale; - - if (!disable_red && !disable_green && !disable_blue && !grayscale) - return; - - /* If only some components are selected, it's important to rescale the result - * appropriately so that e.g. if only blue is selected, it's not zeroed out. - */ - scale = (disable_red ? 0.0f : 0.2126f) + - (disable_green ? 0.0f : 0.7152f) + - (disable_blue ? 0.0f : 0.0722f); - - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - int pixel = ibuf->x*y + x; - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + pixel*4; - float r = disable_red ? 0.0f : rrgbf[0]; - float g = disable_green ? 0.0f : rrgbf[1]; - float b = disable_blue ? 0.0f : rrgbf[2]; - - if (grayscale) { - float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale; - - rrgbf[0] = rrgbf[1] = rrgbf[2] = gray; - } - else { - rrgbf[0] = r; - rrgbf[1] = g; - rrgbf[2] = b; - } - } - else { - char *rrgb = (char*)ibuf->rect + pixel*4; - char r = disable_red ? 0 : rrgb[0]; - char g = disable_green ? 0 : rrgb[1]; - char b = disable_blue ? 0 : rrgb[2]; - - if (grayscale) { - float gray = (0.2126f*r + 0.7152f*g + 0.0722f*b) / scale; - - rrgb[0] = rrgb[1] = rrgb[2] = gray; - } - else { - rrgb[0] = r; - rrgb[1] = g; - rrgb[2] = b; - } - } - } - } - - if (ibuf->rect_float) - ibuf->userflags |= IB_RECT_INVALID; -} - -static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) -{ - BKE_tracking_disable_imbuf_channels(ibuf, track->flag & TRACK_DISABLE_RED, - track->flag & TRACK_DISABLE_GREEN, track->flag & TRACK_DISABLE_BLUE, grayscale); -} - -ImBuf *BKE_tracking_sample_pattern_imbuf(int frame_width, int frame_height, - ImBuf *search_ibuf, MovieTrackingMarker *marker, - int num_samples_x, int num_samples_y, float pos[2]) +void BKE_tracking_context_sync(MovieTrackingContext *context) { -#ifdef WITH_LIBMV - ImBuf *pattern_ibuf; - double src_pixel_x[5], src_pixel_y[5]; - double warped_position_x, warped_position_y; - - pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); - pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; - - if (!search_ibuf->rect_float) { - IMB_float_from_rect(search_ibuf); - } - - get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y); - - libmv_samplePlanarPatch(search_ibuf->rect_float, search_ibuf->x, search_ibuf->y, 4, - src_pixel_x, src_pixel_y, num_samples_x, - num_samples_y, pattern_ibuf->rect_float, - &warped_position_x, &warped_position_y); - - if (pos) { - pos[0] = warped_position_x; - pos[1] = warped_position_y; - } - - return pattern_ibuf; -#else - ImBuf *pattern_ibuf; - - /* real sampling requires libmv, but areas are supposing pattern would be - * sampled if search area does exists, so we'll need to create empty - * pattern area here to prevent adding NULL-checks all over just to deal - * with situation when lubmv is disabled - */ - - (void) frame_width; - (void) frame_height; - (void) search_ibuf; - (void) marker; - - pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); - - pos[0] = num_samples_x / 2.0f; - pos[1] = num_samples_y / 2.0f; - - return pattern_ibuf; -#endif -} - -ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int anchored, int disable_channels) -{ - ImBuf *pattern_ibuf, *search_ibuf; - float pat_min[2], pat_max[2]; - int num_samples_x, num_samples_y; - - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - - num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x; - num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y; - - search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); - - pattern_ibuf = BKE_tracking_sample_pattern_imbuf(ibuf->x, ibuf->y, search_ibuf, marker, - num_samples_x, num_samples_y, NULL); - - IMB_freeImBuf(search_ibuf); - - return pattern_ibuf; -} - -ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int anchored, int disable_channels) -{ - ImBuf *searchibuf; - int x, y, w, h; - float search_origin[2]; - - get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin); - - x = search_origin[0]; - y = search_origin[1]; - - if (anchored) { - x += track->offset[0] * ibuf->x; - y += track->offset[1] * ibuf->y; - } - - w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; - h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; - - searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); - searchibuf->profile = ibuf->profile; - - IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); - - if (disable_channels) { - if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || - (track->flag & TRACK_DISABLE_RED) || - (track->flag & TRACK_DISABLE_GREEN) || - (track->flag & TRACK_DISABLE_BLUE)) - { - disable_imbuf_channels(searchibuf, track, TRUE); - } - } - - return searchibuf; -} - -static bGPDlayer *track_mask_gpencil_layer_get(MovieTrackingTrack *track) -{ - bGPDlayer *layer; - - if (!track->gpd) - return NULL; - - layer = track->gpd->layers.first; - - while (layer) { - if (layer->flag & GP_LAYER_ACTIVE) - return layer; - - layer = layer->next; - } - - return NULL; -} - -static void track_mask_gpencil_layer_rasterize(MovieTracking *tracking, MovieTrackingMarker *marker, - bGPDlayer *layer, ImBuf *ibuf, int width, int height) -{ - bGPDframe *frame = layer->frames.first; - float *mask; - int x, y; - float aspy = 1.0f / tracking->camera.pixel_aspect; - - mask = MEM_callocN(ibuf->x * ibuf->y * sizeof(float), "track mask"); - - while (frame) { - bGPDstroke *stroke = frame->strokes.first; - - while (stroke) { - bGPDspoint *stroke_points = stroke->points; - float *mask_points, *fp; - int i; - - if (stroke->flag & GP_STROKE_2DSPACE) { - fp = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(float), - "track mask rasterization points"); - - for (i = 0; i < stroke->totpoints; i++, fp += 2) { - fp[0] = stroke_points[i].x * width / ibuf->x - marker->search_min[0]; - fp[1] = stroke_points[i].y * height * aspy / ibuf->x - marker->search_min[1]; - } - - PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, ibuf->x, ibuf->y); - - MEM_freeN(mask_points); - } - - stroke = stroke->next; - } - - frame = frame->next; - } + MovieTracking *tracking = &context->clip->tracking; + int newframe; - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - float *pixel = &ibuf->rect_float[4 * (y * ibuf->x + x)]; - float val = mask[y * ibuf->x + x]; + tracks_map_merge(context->tracks_map, tracking); - pixel[0] = val; - pixel[1] = val; - pixel[2] = val; - pixel[3] = 1.0f; - } - } + if (context->backwards) + newframe = context->user.framenr + 1; + else + newframe = context->user.framenr - 1; - MEM_freeN(mask); + context->sync_frame = newframe; - IMB_rect_from_float(ibuf); + tracking->dopesheet.ok = FALSE; } -ImBuf *BKE_tracking_track_mask_get(MovieTracking *tracking, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int width, int height) +void BKE_tracking_context_sync_user(const MovieTrackingContext *context, MovieClipUser *user) { - ImBuf *ibuf; - bGPDlayer *layer = track_mask_gpencil_layer_get(track); - int mask_width, mask_height; - - mask_width = (marker->search_max[0] - marker->search_min[0]) * width; - mask_height = (marker->search_max[1] - marker->search_min[1]) * height; - - ibuf = IMB_allocImBuf(mask_width, mask_height, 32, IB_rect | IB_rectfloat); - - if (layer) { - track_mask_gpencil_layer_rasterize(tracking, marker, layer, ibuf, width, height); - } - else { - float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - IMB_rectfill(ibuf, white); - } - - return ibuf; + user->framenr = context->sync_frame; } #ifdef WITH_LIBMV +/* **** utility functions for tracking **** */ -/* Convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ +/* convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ static void float_rgba_to_gray(const float *rgba, float *gray, int num_pixels, float weight_red, float weight_green, float weight_blue) { @@ -1476,12 +2146,12 @@ static void uint8_rgba_to_float_gray(const unsigned char *rgba, float *gray, int for (i = 0; i < num_pixels; i++) { const unsigned char *pixel = rgba + i * 4; - *gray++ = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; + gray[i] = (weight_red * pixel[0] + weight_green * pixel[1] + weight_blue * pixel[2]) / 255.0f; } } -static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int *width_r, int *height_r) +static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int *width_r, int *height_r) { ImBuf *searchibuf; float *gray_pixels; @@ -1492,55 +2162,26 @@ static float *get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieT width = searchibuf->x; height = searchibuf->y; - *width_r = searchibuf->x; - *height_r = searchibuf->y; - gray_pixels = MEM_callocN(width * height * sizeof(float), "tracking floatBuf"); if (searchibuf->rect_float) { float_rgba_to_gray(searchibuf->rect_float, gray_pixels, width * height, - 0.2126f, 0.7152f, 0.0722f); + 0.2126f, 0.7152f, 0.0722f); } else { uint8_rgba_to_float_gray((unsigned char *)searchibuf->rect, gray_pixels, width * height, - 0.2126f, 0.7152f, 0.0722f); + 0.2126f, 0.7152f, 0.0722f); } IMB_freeImBuf(searchibuf); - return gray_pixels; -} - -static unsigned char *get_ucharbuf(ImBuf *ibuf) -{ - int x, y; - unsigned char *pixels, *cp; - - cp = pixels = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned char), "tracking ucharBuf"); - for (y = 0; y < ibuf->y; y++) { - for (x = 0; x < ibuf->x; x++) { - int pixel = ibuf->x * y + x; - - if (ibuf->rect_float) { - const float *rrgbf = ibuf->rect_float + pixel*4; - const float grey_f = 0.2126f * rrgbf[0] + 0.7152f * rrgbf[1] + 0.0722f * rrgbf[2]; - - *cp = FTOCHAR(grey_f); - } - else { - const unsigned char *rrgb = (unsigned char*)ibuf->rect + pixel * 4; - - *cp = 0.2126f * rrgb[0] + 0.7152f * rrgb[1] + 0.0722f * rrgb[2]; - } - - cp++; - } - } + *width_r = width; + *height_r = height; - return pixels; + return gray_pixels; } -static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) +static ImBuf *tracking_context_get_frame_ibuf(MovieTrackingContext *context, int framenr) { ImBuf *ibuf; MovieClipUser user = context->user; @@ -1552,13 +2193,11 @@ static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) return ibuf; } -static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, - MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed) +MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker) { - int framenr = marker->framenr; int a = marker - track->markers; - - *marker_keyed = marker; + MovieTrackingMarker *marker_keyed = marker; while (a >= 0 && a < track->markersnr) { int next = (context->backwards) ? a + 1 : a - 1; @@ -1576,8 +2215,7 @@ static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTra is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0; if (is_keyframed) { - framenr = cur_marker->framenr; - *marker_keyed = cur_marker; + marker_keyed = cur_marker; break; } @@ -1585,19 +2223,34 @@ static ImBuf *get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTra a = next; } - return get_frame_ibuf(context, framenr); + return marker_keyed; +} + +static ImBuf *tracking_context_get_keyframed_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker, MovieTrackingMarker **marker_keyed_r) +{ + MovieTrackingMarker *marker_keyed; + int keyed_framenr; + + marker_keyed = tracking_context_get_keyframed_marker(context, track, marker); + keyed_framenr = marker_keyed->framenr; + + *marker_keyed_r = marker_keyed; + + return tracking_context_get_frame_ibuf(context, keyed_framenr); } -static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int curfra, MovieTrackingMarker **marker_keyed) +static ImBuf *tracking_context_get_reference_ibuf(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker, int curfra, + MovieTrackingMarker **marker_keyed) { ImBuf *ibuf = NULL; if (track->pattern_match == TRACK_MATCH_KEYFRAME) { - ibuf = get_keyframed_ibuf(context, track, marker, marker_keyed); + ibuf = tracking_context_get_keyframed_ibuf(context, track, marker, marker_keyed); } else { - ibuf = get_frame_ibuf(context, curfra); + ibuf = tracking_context_get_frame_ibuf(context, curfra); /* use current marker as keyframed position */ *marker_keyed = marker; @@ -1606,54 +2259,163 @@ static ImBuf *get_adjust_ibuf(MovieTrackingContext *context, MovieTrackingTrack return ibuf; } -#endif +static void track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context, + MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra, + int frame_width, int frame_height) +{ + MovieTrackingMarker *marker_keyed = NULL; + ImBuf *reference_ibuf = NULL; + int width, height; + + /* calculate patch for keyframed position */ + reference_ibuf = tracking_context_get_reference_ibuf(context, track, marker, curfra, &marker_keyed); + track_context->marker = *marker_keyed; -void BKE_tracking_sync(MovieTrackingContext *context) + if (track_context->search_area) { + MEM_freeN(track_context->search_area); + } + + track_context->search_area = track_get_search_floatbuf(reference_ibuf, track, marker_keyed, &width, &height); + track_context->search_area_height = height; + track_context->search_area_width = width; + + if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) { + if (track_context->mask) + MEM_freeN(track_context->mask); + + track_context->mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker); + } + + IMB_freeImBuf(reference_ibuf); +} + +static void tracking_configure_tracker(TrackContext *track_context, MovieTrackingTrack *track, + struct libmv_trackRegionOptions *options) { - MovieTracking *tracking = &context->clip->tracking; - int newframe; + options->motion_model = track->motion_model; - tracks_map_merge(context->tracks_map, tracking); + options->use_brute = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0); - if (context->backwards) - newframe = context->user.framenr + 1; - else - newframe = context->user.framenr - 1; + options->use_normalization = ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0); - context->sync_frame = newframe; + options->num_iterations = 50; + options->minimum_correlation = track->minimum_correlation; + options->sigma = 0.9; - tracking->dopesheet.ok = FALSE; + if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) + options->image1_mask = track_context->mask; } -void BKE_tracking_sync_user(MovieClipUser *user, MovieTrackingContext *context) +/* returns FALSE if marker crossed margin area from frame bounds */ +static int tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker, + int frame_width, int frame_height) { - user->framenr = context->sync_frame; + float pat_min[2], pat_max[2], dim[2], margin[2]; + + /* margin from frame boundaries */ + BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); + sub_v2_v2v2(dim, pat_max, pat_min); + margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f; + + margin[0] = MAX2(margin[0], (float)track->margin / frame_width); + margin[1] = MAX2(margin[1], (float)track->margin / frame_height); + + /* do not track markers which are too close to boundary */ + if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || + marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1]) + { + return FALSE; + } + + return TRUE; +} + +static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker) +{ + float old_pat_min[2], old_pat_max[2]; + float new_pat_min[2], new_pat_max[2]; + float scale_x, scale_y; + + BKE_tracking_marker_pattern_minmax(old_marker, old_pat_min, old_pat_max); + BKE_tracking_marker_pattern_minmax(new_marker, new_pat_min, new_pat_max); + + scale_x = (new_pat_max[0] - new_pat_min[0]) / (old_pat_max[0] - old_pat_min[0]); + scale_y = (new_pat_max[1] - new_pat_min[1]) / (old_pat_max[1] - old_pat_min[1]); + + new_marker->search_min[0] *= scale_x; + new_marker->search_min[1] *= scale_y; + + new_marker->search_max[0] *= scale_x; + new_marker->search_max[1] *= scale_y; +} + +static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track, + const MovieTrackingMarker *old_marker, int curfra, int tracked, + int frame_width, int frame_height, + double dst_pixel_x[5], double dst_pixel_y[5]) +{ + MovieTrackingMarker new_marker; + int frame_delta = context->backwards ? -1 : 1; + int nextfra = curfra + frame_delta; + + new_marker = *old_marker; + + if (tracked) { + set_marker_coords_from_tracking(frame_width, frame_height, &new_marker, dst_pixel_x, dst_pixel_y); + new_marker.flag |= MARKER_TRACKED; + new_marker.framenr = nextfra; + + tracking_scale_marker_search(old_marker, &new_marker); + + if (context->first_time) { + /* check if there's no keyframe/tracked markers before tracking marker. + * if so -- create disabled marker before currently tracking "segment" + */ + + tracking_marker_insert_disabled(track, &new_marker, !context->backwards, FALSE); + } + + /* insert currently tracked marker */ + BKE_tracking_marker_insert(track, &new_marker); + + /* make currently tracked segment be finished with disabled marker */ + tracking_marker_insert_disabled(track, &new_marker, context->backwards, FALSE); + } + else { + new_marker.framenr = nextfra; + new_marker.flag |= MARKER_DISABLED; + + BKE_tracking_marker_insert(track, &new_marker); + } } -int BKE_tracking_next(MovieTrackingContext *context) +#endif + +int BKE_tracking_context_step(MovieTrackingContext *context) { ImBuf *destination_ibuf; + int frame_delta = context->backwards ? -1 : 1; int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr); + int nextfra; int a, ok = FALSE, map_size; int frame_width, frame_height; - map_size = tracks_map_size(context->tracks_map); + map_size = tracks_map_get_size(context->tracks_map); /* nothing to track, avoid unneeded frames reading to save time and memory */ if (!map_size) return FALSE; - if (context->backwards) - context->user.framenr--; - else - context->user.framenr++; + context->user.framenr += frame_delta; destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); if (!destination_ibuf) return FALSE; + nextfra = curfra + frame_delta; + frame_width = destination_ibuf->x; frame_height = destination_ibuf->y; @@ -1663,16 +2425,13 @@ int BKE_tracking_next(MovieTrackingContext *context) MovieTrackingTrack *track; MovieTrackingMarker *marker; - tracks_map_get(context->tracks_map, a, &track, (void **)&track_context); + tracks_map_get_indexed_element(context->tracks_map, a, &track, (void **)&track_context); - marker = BKE_tracking_exact_marker(track, curfra); + marker = BKE_tracking_marker_get_exact(track, curfra); if (marker && (marker->flag & MARKER_DISABLED) == 0) { #ifdef WITH_LIBMV - int width, height, tracked = 0, need_readjust = 0; - float margin[2], dim[2], pat_min[2], pat_max[2]; - MovieTrackingMarker marker_new, *marker_keyed; - int onbound = FALSE, nextfra; + int width, height, tracked = FALSE, need_readjust; double dst_pixel_x[5], dst_pixel_y[5]; if (track->pattern_match == TRACK_MATCH_KEYFRAME) @@ -1680,127 +2439,57 @@ int BKE_tracking_next(MovieTrackingContext *context) else need_readjust = TRUE; - if (context->backwards) - nextfra = curfra - 1; - else - nextfra = curfra + 1; - - /* margin from frame boundaries */ - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - sub_v2_v2v2(dim, pat_max, pat_min); - margin[0] = margin[1] = MAX2(dim[0], dim[1]) / 2.0f; - - margin[0] = MAX2(margin[0], (float)track->margin / destination_ibuf->x); - margin[1] = MAX2(margin[1], (float)track->margin / destination_ibuf->y); - /* do not track markers which are too close to boundary */ - if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || - marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1]) - { - onbound = TRUE; - } - else { + if (tracking_check_marker_margin(track, marker, frame_width, frame_height)) { /* to convert to the x/y split array format for libmv. */ - double src_pixel_x[5]; - double src_pixel_y[5]; + double src_pixel_x[5], src_pixel_y[5]; /* settings for the tracker */ - struct libmv_trackRegionOptions options; + struct libmv_trackRegionOptions options = {0}; struct libmv_trackRegionResult result; float *patch_new; if (need_readjust) { - ImBuf *reference_ibuf = NULL; - /* calculate patch for keyframed position */ - reference_ibuf = get_adjust_ibuf(context, track, marker, curfra, &marker_keyed); - track_context->marker = *marker_keyed; - - if (track_context->search_area) - MEM_freeN(track_context->search_area); - - track_context->search_area = get_search_floatbuf(reference_ibuf, track, - marker_keyed, &width, &height); - track_context->search_area_height = height; - track_context->search_area_width = width; - - IMB_freeImBuf(reference_ibuf); + track_context_update_reference(context, track_context, track, marker, + curfra, frame_width, frame_height); } /* for now track to the same search area dimension as marker has got for current frame * will make all tracked markers in currently tracked segment have the same search area * size, but it's quite close to what is actually needed */ - patch_new = get_search_floatbuf(destination_ibuf, track, marker, &width, &height); - - /* Configure the tracker */ - options.motion_model = track->motion_model; - - options.use_brute = - ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_BRUTE) != 0); - - options.use_normalization = - ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_NORMALIZATION) != 0); + patch_new = track_get_search_floatbuf(destination_ibuf, track, marker, &width, &height); - options.num_iterations = 50; - options.minimum_correlation = track->minimum_correlation; - options.sigma = 0.9; + /* configure the tracker */ + tracking_configure_tracker(track_context, track, &options); - /* Convert the marker corners and center into pixel coordinates in the search/destination images. */ + /* convert the marker corners and center into pixel coordinates in the search/destination images. */ get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y); get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y); - /* Run the tracker! */ + /* run the tracker! */ tracked = libmv_trackRegion(&options, - track_context->search_area, patch_new, - width, height, + track_context->search_area, + track_context->search_area_width, + track_context->search_area_height, + patch_new, width, height, src_pixel_x, src_pixel_y, &result, dst_pixel_x, dst_pixel_y); MEM_freeN(patch_new); } - if (tracked && !onbound) { - memset(&marker_new, 0, sizeof(marker_new)); - marker_new = *marker; - set_marker_coords_from_tracking(frame_width, frame_height, &marker_new, dst_pixel_x, dst_pixel_y); - marker_new.flag |= MARKER_TRACKED; - marker_new.framenr = nextfra; - - if (context->first_time) { - #pragma omp critical - { - /* check if there's no keyframe/tracked markers before tracking marker. - * if so -- create disabled marker before currently tracking "segment" - */ - put_disabled_marker(track, &marker_new, !context->backwards, 0); - } - } - - #pragma omp critical - { - BKE_tracking_insert_marker(track, &marker_new); - } - - /* make currently tracked segment be finished with disabled marker */ - #pragma omp critical - { - put_disabled_marker(track, &marker_new, context->backwards, 0); - } - } - else { - marker_new = *marker; - - marker_new.framenr = nextfra; - marker_new.flag |= MARKER_DISABLED; - - //#pragma omp critical - { - BKE_tracking_insert_marker(track, &marker_new); - } + #pragma omp critical + { + tracking_insert_new_marker(context, track, marker, curfra, tracked, + frame_width, frame_height, dst_pixel_x, dst_pixel_y); } ok = TRUE; +#else + (void)frame_height; + (void)frame_width; #endif } } @@ -1813,7 +2502,7 @@ int BKE_tracking_next(MovieTrackingContext *context) return ok; } -/*********************** camera solving *************************/ +/*********************** Camera solving *************************/ typedef struct MovieReconstructContext { #ifdef WITH_LIBMV @@ -1846,8 +2535,8 @@ typedef struct ReconstructProgressData { int message_size; } ReconstructProgressData; -#if WITH_LIBMV -static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, int height) +#ifdef WITH_LIBMV +static struct libmv_Tracks *libmv_tracks_new(ListBase *tracksbase, int width, int height) { int tracknr = 0; MovieTrackingTrack *track; @@ -1862,7 +2551,7 @@ static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, if ((marker->flag & MARKER_DISABLED) == 0) { libmv_tracksInsert(tracks, marker->framenr, tracknr, - marker->pos[0] * width, marker->pos[1] * height); + marker->pos[0] * width, marker->pos[1] * height); } } @@ -1873,7 +2562,7 @@ static struct libmv_Tracks *create_libmv_tracks(ListBase *tracksbase, int width, return tracks; } -static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *context, MovieTracking *tracking) +static void reconstruct_retrieve_libmv_intrinscis(MovieReconstructContext *context, MovieTracking *tracking) { struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction; struct libmv_CameraIntrinsics *libmv_intrinsics = libmv_ReconstructionExtractIntrinsics(libmv_reconstruction); @@ -1894,7 +2583,7 @@ static void retrieve_libmv_reconstruct_intrinscis(MovieReconstructContext *conte tracking->camera.k2 = k2; } -static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, MovieTracking *tracking) +static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking) { struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction; MovieTrackingReconstruction *reconstruction = NULL; @@ -1910,7 +2599,7 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M reconstruction = &tracking->reconstruction; } else { - MovieTrackingObject *object = BKE_tracking_named_object(tracking, context->object_name); + MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, context->object_name); tracksbase = &object->tracks; reconstruction = &object->reconstruction; @@ -2002,15 +2691,15 @@ static int retrieve_libmv_reconstruct_tracks(MovieReconstructContext *context, M return ok; } -static int retrieve_libmv_reconstruct(MovieReconstructContext *context, MovieTracking *tracking) +static int reconstruct_retrieve_libmv(MovieReconstructContext *context, MovieTracking *tracking) { /* take the intrinscis back from libmv */ - retrieve_libmv_reconstruct_intrinscis(context, tracking); + reconstruct_retrieve_libmv_intrinscis(context, tracking); - return retrieve_libmv_reconstruct_tracks(context, tracking); + return reconstruct_retrieve_libmv_tracks(context, tracking); } -static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObject *object) +static int reconstruct_refine_intrinsics_get_flags(MovieTracking *tracking, MovieTrackingObject *object) { int refine = tracking->settings.refine_camera_intrinsics; int flags = 0; @@ -2033,7 +2722,7 @@ static int get_refine_intrinsics_flags(MovieTracking *tracking, MovieTrackingObj return flags; } -static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase) +static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase) { int tot = 0; int frame1 = tracking->settings.keyframe1, frame2 = tracking->settings.keyframe2; @@ -2041,9 +2730,11 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tra track = tracksbase->first; while (track) { - if (BKE_tracking_has_enabled_marker(track, frame1)) - if (BKE_tracking_has_enabled_marker(track, frame2)) + if (BKE_tracking_track_has_enabled_marker_at_frame(track, frame1)) { + if (BKE_tracking_track_has_enabled_marker_at_frame(track, frame2)) { tot++; + } + } track = track->next; } @@ -2052,16 +2743,16 @@ static int count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tra } #endif -int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) +int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) { #if WITH_LIBMV - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) { /* TODO: check for number of tracks? */ return TRUE; } - else if (count_tracks_on_both_keyframes(tracking, tracksbase) < 8) { + else if (reconstruct_count_tracks_on_both_keyframes(tracking, tracksbase) < 8) { BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction", error_size); @@ -2079,12 +2770,12 @@ int BKE_tracking_can_reconstruct(MovieTracking *tracking, MovieTrackingObject *o #endif } -MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking *tracking, MovieTrackingObject *object, +MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking *tracking, 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); + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); float aspy = 1.0f / tracking->camera.pixel_aspect; int num_tracks = BLI_countlist(tracksbase); int sfra = INT_MAX, efra = INT_MIN; @@ -2094,6 +2785,14 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking * context->is_camera = object->flag & TRACKING_OBJECT_CAMERA; context->motion_flag = tracking->settings.motion_flag; + context->focal_length = camera->focal; + context->principal_point[0] = camera->principal[0]; + context->principal_point[1] = camera->principal[1] * aspy; + + context->k1 = camera->k1; + context->k2 = camera->k2; + context->k3 = camera->k3; + context->tracks_map = tracks_map_new(context->object_name, context->is_camera, num_tracks, 0); track = tracksbase->first; @@ -2129,10 +2828,10 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking * context->efra = efra; #ifdef WITH_LIBMV - context->tracks = create_libmv_tracks(tracksbase, width, height*aspy); + context->tracks = libmv_tracks_new(tracksbase, width, height * aspy); context->keyframe1 = keyframe1; context->keyframe2 = keyframe2; - context->refine_flags = get_refine_intrinsics_flags(tracking, object); + context->refine_flags = reconstruct_refine_intrinsics_get_flags(tracking, object); #else (void) width; (void) height; @@ -2140,14 +2839,6 @@ MovieReconstructContext* BKE_tracking_reconstruction_context_new(MovieTracking * (void) keyframe2; #endif - context->focal_length = camera->focal; - context->principal_point[0] = camera->principal[0]; - context->principal_point[1] = camera->principal[1] * aspy; - - context->k1 = camera->k1; - context->k2 = camera->k2; - context->k3 = camera->k3; - return context; } @@ -2155,7 +2846,7 @@ void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context) { #ifdef WITH_LIBMV if (context->reconstruction) - libmv_destroyReconstruction(context->reconstruction); + libmv_destroyReconstruction(context->reconstruction); libmv_tracksDestroy(context->tracks); #endif @@ -2166,7 +2857,7 @@ void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context) } #ifdef WITH_LIBMV -static void solve_reconstruction_update_cb(void *customdata, double progress, const char *message) +static void reconstruct_update_solve_cb(void *customdata, double progress, const char *message) { ReconstructProgressData *progressdata = customdata; @@ -2179,19 +2870,7 @@ static void solve_reconstruction_update_cb(void *customdata, double progress, co } #endif -#if 0 -static int solve_reconstruction_testbreak_cb(void *customdata) -{ - ReconstructProgressData *progressdata = customdata; - - if (progressdata->stop && *progressdata->stop) - return TRUE; - - return G.afbreek; -} -#endif - -void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short *stop, short *do_update, +void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *stop, short *do_update, float *progress, char *stats_message, int message_size) { #ifdef WITH_LIBMV @@ -2207,19 +2886,19 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * if (context->motion_flag & TRACKING_MOTION_MODAL) { context->reconstruction = libmv_solveModal(context->tracks, - context->focal_length, - context->principal_point[0], context->principal_point[1], - context->k1, context->k2, context->k3, - solve_reconstruction_update_cb, &progressdata); + context->focal_length, + context->principal_point[0], context->principal_point[1], + context->k1, context->k2, context->k3, + reconstruct_update_solve_cb, &progressdata); } else { context->reconstruction = libmv_solveReconstruction(context->tracks, - context->keyframe1, context->keyframe2, - context->refine_flags, - context->focal_length, - context->principal_point[0], context->principal_point[1], - context->k1, context->k2, context->k3, - solve_reconstruction_update_cb, &progressdata); + context->keyframe1, context->keyframe2, + context->refine_flags, + context->focal_length, + context->principal_point[0], context->principal_point[1], + context->k1, context->k2, context->k3, + reconstruct_update_solve_cb, &progressdata); } error = libmv_reprojectionError(context->reconstruction); @@ -2235,7 +2914,7 @@ void BKE_tracking_solve_reconstruction(MovieReconstructContext *context, short * #endif } -int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTracking *tracking) +int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking) { MovieTrackingReconstruction *reconstruction; @@ -2247,7 +2926,7 @@ int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTr else { MovieTrackingObject *object; - object = BKE_tracking_named_object(tracking, context->object_name); + object = BKE_tracking_object_get_named(tracking, context->object_name); reconstruction = &object->reconstruction; } @@ -2255,350 +2934,17 @@ int BKE_tracking_finish_reconstruction(MovieReconstructContext *context, MovieTr reconstruction->flag |= TRACKING_RECONSTRUCTED; #ifdef WITH_LIBMV - if (!retrieve_libmv_reconstruct(context, tracking)) + if (!reconstruct_retrieve_libmv(context, tracking)) return FALSE; #endif return TRUE; } -void BKE_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track) -{ - BLI_uniquename(tracksbase, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); -} - -MovieTrackingTrack *BKE_tracking_named_track(MovieTracking *tracking, MovieTrackingObject *object, const char *name) -{ - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; - - while (track) { - if (!strcmp(track->name, name)) - return track; - - track = track->next; - } - - return NULL; -} - -static int reconstruction_camera_index(MovieTrackingReconstruction *reconstruction, int framenr, int nearest) -{ - MovieReconstructedCamera *cameras = reconstruction->cameras; - int a = 0, d = 1; - - if (!reconstruction->camnr) - return -1; - - if (framenr < cameras[0].framenr) { - if (nearest) - return 0; - else - return -1; - } - - if (framenr > cameras[reconstruction->camnr - 1].framenr) { - if (nearest) - return reconstruction->camnr - 1; - else - return -1; - } - - if (reconstruction->last_camera < reconstruction->camnr) - a = reconstruction->last_camera; - - if (cameras[a].framenr >= framenr) - d = -1; - - while (a >= 0 && a < reconstruction->camnr) { - int cfra = cameras[a].framenr; - - /* check if needed framenr was "skipped" -- no data for requested frame */ - - if (d > 0 && cfra > framenr) { - /* interpolate with previous position */ - if (nearest) - return a - 1; - else - break; - } - - if (d < 0 && cfra < framenr) { - /* interpolate with next position */ - if (nearest) - return a; - else - break; - } - - if (cfra == framenr) { - reconstruction->last_camera = a; - - return a; - } - - a += d; - } - - return -1; -} - -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) -{ - MovieTrackingReconstruction *reconstruction; - int a; - - reconstruction = BKE_tracking_object_reconstruction(tracking, object); - a = reconstruction_camera_index(reconstruction, framenr, FALSE); - - if (a ==-1) - return NULL; - - return &reconstruction->cameras[a]; -} - -void BKE_tracking_get_interpolated_camera(MovieTracking *tracking, MovieTrackingObject *object, - int framenr, float mat[4][4]) -{ - 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); - - return; - } - - if (cameras[a].framenr != framenr && a > 0 && a < reconstruction->camnr - 1) { - float t = ((float)framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr); - - blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t); - } - 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]) -{ - if (!ob) { - if (scene->camera) - ob = scene->camera; - else - ob = BKE_scene_camera_find(scene); - } - - if (ob) - BKE_object_where_is_calc_mat4(scene, ob, mat); - else - unit_m4(mat); -} - -void BKE_tracking_camera_shift(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty) -{ - /* indeed in both of cases it should be winx -- it's just how camera shift works for blender's camera */ - *shiftx = (0.5f * winx - tracking->camera.principal[0]) / winx; - *shifty = (0.5f * winy - tracking->camera.principal[1]) / winx; -} - -void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height) -{ - float focal = tracking->camera.focal; - - camera->sensor_x = tracking->camera.sensor_width; - camera->sensor_fit = CAMERA_SENSOR_FIT_AUTO; - camera->lens = focal * camera->sensor_x / width; - - scene->r.xsch = width * tracking->camera.pixel_aspect; - scene->r.ysch = height; - - scene->r.xasp = 1.0f; - scene->r.yasp = 1.0f; - - BKE_tracking_camera_shift(tracking, width, height, &camera->shiftx, &camera->shifty); -} - -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; - float viewfac, pixsize, left, right, bottom, top, clipsta, clipend; - float winmat[4][4]; - float ycor = 1.0f / tracking->camera.pixel_aspect; - float shiftx, shifty, winside = MAX2(winx, winy); - - BKE_tracking_camera_shift(tracking, winx, winy, &shiftx, &shifty); - - clipsta = 0.1f; - clipend = 1000.0f; - - if (winx >= winy) - viewfac = (lens * winx) / tracking->camera.sensor_width; - else - viewfac = (ycor * lens * winy) / tracking->camera.sensor_width; - - pixsize = clipsta / viewfac; - - left = -0.5f * (float)winx + shiftx * winside; - bottom = -0.5f * (ycor) * (float)winy + shifty * winside; - right = 0.5f * (float)winx + shiftx * winside; - top = 0.5f * (ycor) * (float)winy + shifty * winside; - - left *= pixsize; - right *= pixsize; - bottom *= pixsize; - top *= pixsize; - - perspective_m4(winmat, left, right, bottom, top, clipsta, clipend); - - camera = BKE_tracking_get_reconstructed_camera(tracking, object, framenr); - - if (camera) { - float imat[4][4]; - - invert_m4_m4(imat, camera->mat); - mult_m4_m4m4(mat, winmat, imat); - } - 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; +/*********************** Feature detection *************************/ #ifdef WITH_LIBMV - double x, y; - float aspy = 1.0f / tracking->camera.pixel_aspect; - - /* normalize coords */ - x = (co[0] - camera->principal[0]) / camera->focal; - y = (co[1] - camera->principal[1] * aspy) / camera->focal; - - libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, x, y, &x, &y); - - /* result is in image coords already */ - nco[0] = x; - nco[1] = y; -#else - (void) camera; - (void) co; - (void) nco; -#endif -} - -void BKE_tracking_invert_intrinsics(MovieTracking *tracking, float co[2], float nco[2]) -{ - MovieTrackingCamera *camera = &tracking->camera; - -#ifdef WITH_LIBMV - double x = co[0], y = co[1]; - float aspy = 1.0f / tracking->camera.pixel_aspect; - - libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, x, y, &x, &y); - - nco[0] = x * camera->focal + camera->principal[0]; - nco[1] = y * camera->focal + camera->principal[1] * aspy; -#else - (void) camera; - (void) co; - (void) nco; -#endif -} - -#ifdef WITH_LIBMV -static int point_in_stroke(bGPDstroke *stroke, float x, float y) +static int check_point_in_stroke(bGPDstroke *stroke, float x, float y) { int i, prev; int count = 0; @@ -2620,7 +2966,7 @@ static int point_in_stroke(bGPDstroke *stroke, float x, float y) return count % 2; } -static int point_in_layer(bGPDlayer *layer, float x, float y) +static int check_point_in_layer(bGPDlayer *layer, float x, float y) { bGPDframe *frame = layer->frames.first; @@ -2628,7 +2974,7 @@ static int point_in_layer(bGPDlayer *layer, float x, float y) bGPDstroke *stroke = frame->strokes.first; while (stroke) { - if (point_in_stroke(stroke, x, y)) + if (check_point_in_stroke(stroke, x, y)) return TRUE; stroke = stroke->next; @@ -2639,9 +2985,9 @@ static int point_in_layer(bGPDlayer *layer, float x, float y) return FALSE; } -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) +static void detect_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; @@ -2658,16 +3004,45 @@ static void retrieve_libmv_features(MovieTracking *tracking, ListBase *tracksbas yu = y / height; if (layer) - ok = point_in_layer(layer, xu, yu) != place_outside_layer; + ok = check_point_in_layer(layer, xu, yu) != place_outside_layer; if (ok) { - track = BKE_tracking_add_track(tracking, tracksbase, xu, yu, framenr, width, height); + track = BKE_tracking_track_add(tracking, tracksbase, xu, yu, framenr, width, height); track->flag |= SELECT; track->pat_flag |= SELECT; track->search_flag |= SELECT; } } } + +static unsigned char *detect_get_frame_ucharbuf(ImBuf *ibuf) +{ + int x, y; + unsigned char *pixels, *cp; + + cp = pixels = MEM_callocN(ibuf->x * ibuf->y * sizeof(unsigned char), "tracking ucharBuf"); + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + int pixel = ibuf->x * y + x; + + if (ibuf->rect_float) { + const float *rrgbf = ibuf->rect_float + pixel * 4; + const float grey_f = 0.2126f * rrgbf[0] + 0.7152f * rrgbf[1] + 0.0722f * rrgbf[2]; + + *cp = FTOCHAR(grey_f); + } + else { + const unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4; + + *cp = 0.2126f * rrgb[0] + 0.7152f * rrgb[1] + 0.0722f * rrgb[2]; + } + + cp++; + } + } + + return pixels; +} #endif void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf, @@ -2676,14 +3051,14 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImB { #ifdef WITH_LIBMV struct libmv_Features *features; - unsigned char *pixels = get_ucharbuf(ibuf); + unsigned char *pixels = detect_get_frame_ucharbuf(ibuf); features = libmv_detectFeaturesFAST(pixels, ibuf->x, ibuf->y, ibuf->x, margin, min_trackness, min_distance); MEM_freeN(pixels); - retrieve_libmv_features(tracking, tracksbase, features, framenr, + detect_retrieve_libmv_features(tracking, tracksbase, features, framenr, ibuf->x, ibuf->y, layer, place_outside_layer); libmv_destroyFeatures(features); @@ -2700,38 +3075,9 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImB #endif } -MovieTrackingTrack *BKE_tracking_indexed_track(MovieTracking *tracking, int tracknr, ListBase **tracksbase_r) -{ - MovieTrackingObject *object; - int cur = 1; - - 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++; - } - - track = track->next; - } - - object = object->next; - } - - *tracksbase_r = NULL; - - return NULL; -} +/*********************** 2D stabilization *************************/ -static int stabilization_median_point(MovieTracking *tracking, int framenr, float median[2]) +static int stabilization_median_point_get(MovieTracking *tracking, int framenr, float median[2]) { int ok = FALSE; float min[2], max[2]; @@ -2742,7 +3088,7 @@ static int stabilization_median_point(MovieTracking *tracking, int framenr, floa track = tracking->tracks.first; while (track) { if (track->flag & TRACK_USE_2D_STAB) { - MovieTrackingMarker *marker = BKE_tracking_get_marker(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); DO_MINMAX2(marker->pos, min, max); @@ -2758,16 +3104,17 @@ static int stabilization_median_point(MovieTracking *tracking, int framenr, floa return ok; } -static void calculate_stabdata(MovieTracking *tracking, int framenr, float width, float height, - float firstmedian[2], float median[2], float loc[2], float *scale, float *angle) +static void stabilization_calculate_data(MovieTracking *tracking, int framenr, float width, float height, + float firstmedian[2], float median[2], float loc[2], + float *scale, float *angle) { MovieTrackingStabilization *stab = &tracking->stabilization; *scale = (stab->scale - 1.0f) * stab->scaleinf + 1.0f; *angle = 0.0f; - loc[0] = (firstmedian[0] - median[0]) *width * (*scale); - loc[1] = (firstmedian[1] - median[1]) *height * (*scale); + loc[0] = (firstmedian[0] - median[0]) * width * (*scale); + loc[1] = (firstmedian[1] - median[1]) * height * (*scale); mul_v2_fl(loc, stab->locinf); @@ -2777,12 +3124,12 @@ static void calculate_stabdata(MovieTracking *tracking, int framenr, float width float x0 = (float)width / 2.0f, y0 = (float)height / 2.0f; float x = median[0] * width, y = median[1] * height; - marker = BKE_tracking_get_marker(stab->rot_track, 1); + marker = BKE_tracking_marker_get(stab->rot_track, 1); sub_v2_v2v2(a, marker->pos, firstmedian); a[0] *= width; a[1] *= height; - marker = BKE_tracking_get_marker(stab->rot_track, framenr); + marker = BKE_tracking_marker_get(stab->rot_track, framenr); sub_v2_v2v2(b, marker->pos, median); b[0] *= width; b[1] *= height; @@ -2796,7 +3143,7 @@ static void calculate_stabdata(MovieTracking *tracking, int framenr, float width } } -static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, int height) +static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, int width, int height) { float firstmedian[2]; MovieTrackingStabilization *stab = &tracking->stabilization; @@ -2805,7 +3152,7 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, if (stab->ok) return stab->scale; - if (stabilization_median_point(tracking, 1, firstmedian)) { + if (stabilization_median_point_get(tracking, 1, firstmedian)) { int sfra = INT_MAX, efra = INT_MIN, cfra; float scale = 1.0f; MovieTrackingTrack *track; @@ -2815,7 +3162,7 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, track = tracking->tracks.first; while (track) { if (track->flag & TRACK_USE_2D_STAB || - ((stab->flag & TRACKING_STABILIZE_ROTATION) && track == stab->rot_track)) + ((stab->flag & TRACKING_STABILIZE_ROTATION) && track == stab->rot_track)) { sfra = MIN2(sfra, track->markers[0].framenr); efra = MAX2(efra, track->markers[track->markersnr - 1].framenr); @@ -2832,11 +3179,11 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}}; float si, co; - stabilization_median_point(tracking, cfra, median); + stabilization_median_point_get(tracking, cfra, median); - calculate_stabdata(tracking, cfra, width, height, firstmedian, median, loc, &tmp_scale, &angle); + stabilization_calculate_data(tracking, cfra, width, height, firstmedian, median, loc, &tmp_scale, &angle); - BKE_tracking_stabdata_to_mat4(width, height, aspect, loc, 1.0f, angle, mat); + BKE_tracking_stabilization_data_to_mat4(width, height, aspect, loc, 1.0f, angle, mat); si = sin(angle); co = cos(angle); @@ -2876,23 +3223,23 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, h = (float)height / 2.0f; } - E = -w*co + h*si; - F = -h*co - w*si; + E = -w * co + h * si; + F = -h * co - w * si; if ((i % 2) == (j % 2)) { - G = -w*co - h*si; - H = h*co - w*si; + G = -w * co - h * si; + H = h * co - w * si; } else { - G = w*co + h*si; - H = -h*co + w*si; + G = w * co + h * si; + H = -h * co + w * si; } I = F - H; J = G - E; - K = G*F - E*H; + K = G * F - E * H; - S = (-w*I - h*J) / (dx*I + dy*J + K); + S = (-w * I - h * J) / (dx * I + dy * J + K); scale = MAX2(scale, S); } @@ -2914,7 +3261,7 @@ static float stabilization_auto_scale_factor(MovieTracking *tracking, int width, return stab->scale; } -static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill) +static ImBuf *stabilization_allocate_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill) { int flags; @@ -2943,8 +3290,9 @@ static ImBuf* stabilize_alloc_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int fill) return cacheibuf; } -void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int width, int height, - float loc[2], float *scale, float *angle) +/* NOTE: frame number should be in clip space, not scene space */ +void BKE_tracking_stabilization_data_get(MovieTracking *tracking, int framenr, int width, int height, + float loc[2], float *scale, float *angle) { float firstmedian[2], median[2]; MovieTrackingStabilization *stab = &tracking->stabilization; @@ -2957,22 +3305,22 @@ void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int w return; } - if (stabilization_median_point(tracking, 1, firstmedian)) { - stabilization_median_point(tracking, framenr, median); + if (stabilization_median_point_get(tracking, 1, firstmedian)) { + stabilization_median_point_get(tracking, framenr, median); if ((stab->flag & TRACKING_AUTOSCALE) == 0) stab->scale = 1.0f; if (!stab->ok) { if (stab->flag & TRACKING_AUTOSCALE) - stabilization_auto_scale_factor(tracking, width, height); + stabilization_calculate_autoscale_factor(tracking, width, height); - calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); + stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); stab->ok = TRUE; } else { - calculate_stabdata(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); + stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, loc, scale, angle); } } else { @@ -2982,8 +3330,9 @@ void BKE_tracking_stabilization_data(MovieTracking *tracking, int framenr, int w } } -ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, - float loc[2], float *scale, float *angle) +/* NOTE: frame number should be in clip space, not scene space */ +ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf *ibuf, + float loc[2], float *scale, float *angle) { float tloc[2], tscale, tangle; MovieTrackingStabilization *stab = &tracking->stabilization; @@ -3007,21 +3356,21 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, return ibuf; } - BKE_tracking_stabilization_data(tracking, framenr, width, height, tloc, &tscale, &tangle); + BKE_tracking_stabilization_data_get(tracking, framenr, width, height, tloc, &tscale, &tangle); - tmpibuf = stabilize_alloc_ibuf(NULL, ibuf, TRUE); + tmpibuf = stabilization_allocate_ibuf(NULL, ibuf, TRUE); /* scale would be handled by matrix transformation when angle is non-zero */ if (tscale != 1.0f && tangle == 0.0f) { ImBuf *scaleibuf; - stabilization_auto_scale_factor(tracking, width, height); + stabilization_calculate_autoscale_factor(tracking, width, height); - scaleibuf = stabilize_alloc_ibuf(stab->scaleibuf, ibuf, 0); + scaleibuf = stabilization_allocate_ibuf(stab->scaleibuf, ibuf, 0); stab->scaleibuf = scaleibuf; IMB_rectcpy(scaleibuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); - IMB_scalefastImBuf(scaleibuf, ibuf->x*tscale, ibuf->y*tscale); + IMB_scalefastImBuf(scaleibuf, ibuf->x * tscale, ibuf->y * tscale); ibuf = scaleibuf; } @@ -3038,9 +3387,9 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, else { float mat[4][4]; int i, j, filter = tracking->stabilization.filter; - void (*interpolation) (struct ImBuf*, struct ImBuf*, float, float, int, int) = NULL; + void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL; - BKE_tracking_stabdata_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); + BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); invert_m4(mat); if (filter == TRACKING_FILTER_NEAREAST) @@ -3054,7 +3403,7 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, interpolation = neareast_interpolation; for (j = 0; j < tmpibuf->y; j++) { - for (i = 0; i < tmpibuf->x;i++) { + for (i = 0; i < tmpibuf->x; i++) { float vec[3] = {i, j, 0}; mul_v3_m4v3(vec, mat, vec); @@ -3081,8 +3430,8 @@ ImBuf *BKE_tracking_stabilize(MovieTracking *tracking, int framenr, ImBuf *ibuf, return tmpibuf; } -void BKE_tracking_stabdata_to_mat4(int width, int height, float aspect, - float loc[2], float scale, float angle, float mat[4][4]) +void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, float loc[2], + float scale, float angle, float mat[4][4]) { float lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4], amat[4][4], iamat[4][4]; float svec[3] = {scale, scale, scale}; @@ -3102,249 +3451,15 @@ void BKE_tracking_stabdata_to_mat4(int width, int height, float aspect, cmat[3][1] = (float)height / 2.0f; invert_m4_m4(icmat, cmat); - size_to_mat4(smat, svec); /* scale matrix */ - add_v2_v2(lmat[3], loc); /* translation matrix */ - rotate_m4(rmat, 'Z', angle); /* rotation matrix */ + size_to_mat4(smat, svec); /* scale matrix */ + add_v2_v2(lmat[3], loc); /* translation matrix */ + rotate_m4(rmat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ mul_serie_m4(mat, lmat, cmat, amat, rmat, iamat, smat, icmat, NULL); } -MovieDistortion *BKE_tracking_distortion_create(void) -{ - MovieDistortion *distortion; - - distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); - - return distortion; -} - -MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion) -{ - MovieDistortion *new_distortion; - - new_distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); - -#ifdef WITH_LIBMV - new_distortion->intrinsics = libmv_CameraIntrinsicsCopy(distortion->intrinsics); -#else - (void) distortion; -#endif - - return new_distortion; -} - -void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int width, int height) -{ - MovieTrackingCamera *camera = &tracking->camera; - float aspy = 1.0f / tracking->camera.pixel_aspect; - -#ifdef WITH_LIBMV - if (!distortion->intrinsics) { - distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal, - camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, width, height * aspy); - } - else { - libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal, - camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, width, height * aspy); - } -#else - (void) distortion; - (void) width; - (void) height; - (void) camera; - (void) aspy; -#endif -} - -ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, - ImBuf *ibuf, int width, int height, float overscan, int undistort) -{ - ImBuf *resibuf; - - BKE_tracking_distortion_update(distortion, tracking, width, height); - - resibuf = IMB_dupImBuf(ibuf); - - if (ibuf->rect_float) { -#ifdef WITH_LIBMV - if (undistort) { - libmv_CameraIntrinsicsUndistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } - else { - libmv_CameraIntrinsicsDistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } -#endif - - resibuf->userflags |= IB_RECT_INVALID; - } - else { -#ifdef WITH_LIBMV - if (undistort) { - libmv_CameraIntrinsicsUndistortByte(distortion->intrinsics, - (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } - else { - libmv_CameraIntrinsicsDistortByte(distortion->intrinsics, - (unsigned char*)ibuf->rect, (unsigned char*)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); - } -#endif - } - -#ifndef WITH_LIBMV - (void) overscan; - (void) undistort; -#endif - - return resibuf; -} - -void BKE_tracking_distortion_destroy(MovieDistortion *distortion) -{ -#ifdef WITH_LIBMV - libmv_CameraIntrinsicsDestroy(distortion->intrinsics); -#endif - - MEM_freeN(distortion); -} - -ImBuf *BKE_tracking_undistort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan) -{ - MovieTrackingCamera *camera = &tracking->camera; - - if (camera->intrinsics == NULL) - camera->intrinsics = BKE_tracking_distortion_create(); - - return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 1); -} - -ImBuf *BKE_tracking_distort(MovieTracking *tracking, ImBuf *ibuf, int width, int height, float overscan) -{ - MovieTrackingCamera *camera = &tracking->camera; - - if (camera->intrinsics == NULL) - camera->intrinsics = BKE_tracking_distortion_create(); - - return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, width, height, overscan, 0); -} - -/* area - which part of marker should be selected. see TRACK_AREA_* constants */ -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 = tracksbase->first; - - while (cur) { - if ((cur->flag & TRACK_HIDDEN) == 0) { - if (cur == track) { - BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1); - BKE_tracking_track_flag(cur, area, SELECT, 0); - } - else { - BKE_tracking_track_flag(cur, TRACK_AREA_ALL, SELECT, 1); - } - } - - cur = cur->next; - } - } -} - -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; - - object->scale = 1.0f; - - 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; -} - -/*********************** dopesheet functions *************************/ +/*********************** Dopesheet functions *************************/ static int channels_alpha_sort(void *a, void *b) { @@ -3507,40 +3622,34 @@ static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, i { MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; - if (dopesheet->sort_method == sort_method && dopesheet->sort_inverse == inverse) - return; - if (inverse) { - if (sort_method == TRACK_SORT_NAME) { + if (sort_method == TRACKING_DOPE_SORT_NAME) { BLI_sortlist(&dopesheet->channels, channels_alpha_inverse_sort); } - else if (sort_method == TRACK_SORT_LONGEST) { + else if (sort_method == TRACKING_DOPE_SORT_LONGEST) { BLI_sortlist(&dopesheet->channels, channels_longest_segment_inverse_sort); } - else if (sort_method == TRACK_SORT_TOTAL) { + else if (sort_method == TRACKING_DOPE_SORT_TOTAL) { BLI_sortlist(&dopesheet->channels, channels_total_track_inverse_sort); } - else if (sort_method == TRACK_SORT_AVERAGE_ERROR) { + else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) { BLI_sortlist(&dopesheet->channels, channels_average_error_inverse_sort); } } else { - if (sort_method == TRACK_SORT_NAME) { + if (sort_method == TRACKING_DOPE_SORT_NAME) { BLI_sortlist(&dopesheet->channels, channels_alpha_sort); } - else if (sort_method == TRACK_SORT_LONGEST) { + else if (sort_method == TRACKING_DOPE_SORT_LONGEST) { BLI_sortlist(&dopesheet->channels, channels_longest_segment_sort); } - else if (sort_method == TRACK_SORT_TOTAL) { + else if (sort_method == TRACKING_DOPE_SORT_TOTAL) { BLI_sortlist(&dopesheet->channels, channels_total_track_sort); } - else if (sort_method == TRACK_SORT_AVERAGE_ERROR) { + else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) { BLI_sortlist(&dopesheet->channels, channels_average_error_sort); } } - - dopesheet->sort_method = sort_method; - dopesheet->sort_inverse = inverse; } void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking) @@ -3550,35 +3659,50 @@ void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking) dopesheet->ok = FALSE; } -void BKE_tracking_dopesheet_update(MovieTracking *tracking, int sort_method, int inverse) +void BKE_tracking_dopesheet_update(MovieTracking *tracking) { - MovieTrackingObject *object = BKE_tracking_active_object(tracking); + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; MovieTrackingTrack *track; - ListBase *tracksbase = BKE_tracking_object_tracks(tracking, object); + MovieTrackingReconstruction *reconstruction; + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); - if (dopesheet->ok) { - tracking_dopesheet_sort(tracking, sort_method, inverse); + short sort_method = dopesheet->sort_method; + short inverse = dopesheet->flag & TRACKING_DOPE_SORT_INVERSE; + short sel_only = dopesheet->flag & TRACKING_DOPE_SELECTED_ONLY; + short show_hidden = dopesheet->flag & TRACKING_DOPE_SHOW_HIDDEN; + + if (dopesheet->ok) return; - } tracking_dopesheet_free(dopesheet); + reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + for (track = tracksbase->first; track; track = track->next) { - if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) { - MovieTrackingDopesheetChannel *channel; + MovieTrackingDopesheetChannel *channel; - channel = MEM_callocN(sizeof(MovieTrackingDopesheetChannel), "tracking dopesheet channel"); - channel->track = track; + if (!show_hidden && (track->flag & TRACK_HIDDEN) != 0) + continue; - channels_segments_calc(channel); + if (sel_only && !TRACK_SELECTED(track)) + continue; - BLI_addtail(&dopesheet->channels, channel); - dopesheet->tot_channel++; + channel = MEM_callocN(sizeof(MovieTrackingDopesheetChannel), "tracking dopesheet channel"); + channel->track = track; + + if (reconstruction->flag & TRACKING_RECONSTRUCTED) { + BLI_snprintf(channel->name, sizeof(channel->name), "%s (%.4f)", track->name, track->error); + } + else { + BLI_strncpy(channel->name, track->name, sizeof(channel->name)); } - } - dopesheet->sort_method = TRACK_SORT_NONE; + channels_segments_calc(channel); + + BLI_addtail(&dopesheet->channels, channel); + dopesheet->tot_channel++; + } tracking_dopesheet_sort(tracking, sort_method, inverse); |