diff options
-rw-r--r-- | source/blender/blenkernel/intern/tracking.c | 88 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_clip/clip_dopesheet_draw.c | 27 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_tracking_types.h | 24 |
4 files changed, 139 insertions, 1 deletions
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index a6519f8005c..1a7458f531c 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -141,8 +141,10 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) } BLI_freelistN(&dopesheet->channels); + BLI_freelistN(&dopesheet->coverage_segments); dopesheet->channels.first = dopesheet->channels.last = NULL; + dopesheet->coverage_segments.first = dopesheet->coverage_segments.last = NULL; dopesheet->tot_channel = 0; } @@ -3784,6 +3786,88 @@ static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, in } } +static int coverage_from_count(int count) +{ + if (count < 8) + return TRACKING_COVERAGE_BAD; + else if (count < 16) + return TRACKING_COVERAGE_ACCEPTABLE; + return TRACKING_COVERAGE_OK; +} + +static void tracking_dopesheet_calc_coverage(MovieTracking *tracking) +{ + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track; + int frames, start_frame = INT_MAX, end_frame = -INT_MAX; + int *per_frame_counter; + int prev_coverage, last_segment_frame; + int i; + + /* find frame boundaries */ + for (track = tracksbase->first; track; track = track->next) { + start_frame = min_ii(start_frame, track->markers[0].framenr); + end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr); + } + + frames = end_frame - start_frame + 1; + + /* this is a per-frame counter of markers (how many markers belongs to the same frame) */ + per_frame_counter = MEM_callocN(sizeof(int) * frames, "per frame track counter"); + + /* find per-frame markers count */ + for (track = tracksbase->first; track; track = track->next) { + int i; + + for (i = 0; i < track->markersnr; i++) { + MovieTrackingMarker *marker = &track->markers[i]; + + /* TODO: perhaps we need to add check for non-single-frame track here */ + if ((marker->flag & MARKER_DISABLED) == 0) + per_frame_counter[marker->framenr - start_frame]++; + } + } + + /* convert markers count to coverage and detect segments with the same coverage */ + prev_coverage = coverage_from_count(per_frame_counter[0]); + last_segment_frame = start_frame; + + /* means only disabled tracks in the beginning, could be ignored */ + if (!per_frame_counter[0]) + prev_coverage = TRACKING_COVERAGE_OK; + + for (i = 1; i < frames; i++) { + int coverage = coverage_from_count(per_frame_counter[i]); + + /* means only disabled tracks in the end, could be ignored */ + if (i == frames - 1 && !per_frame_counter[i]) + coverage = TRACKING_COVERAGE_OK; + + if (coverage != prev_coverage || i == frames - 1) { + MovieTrackingDopesheetCoverageSegment *coverage_segment; + int end_segment_frame = i - 1 + start_frame; + + if (end_segment_frame == last_segment_frame) + end_segment_frame++; + + coverage_segment = MEM_callocN(sizeof(MovieTrackingDopesheetCoverageSegment), "tracking coverage segment"); + coverage_segment->coverage = prev_coverage; + coverage_segment->start_frame = last_segment_frame; + coverage_segment->end_frame = end_segment_frame; + + BLI_addtail(&dopesheet->coverage_segments, coverage_segment); + + last_segment_frame = end_segment_frame; + } + + prev_coverage = coverage; + } + + MEM_freeN(per_frame_counter); +} + void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking) { MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; @@ -3811,6 +3895,7 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking) reconstruction = BKE_tracking_object_get_reconstruction(tracking, object); + /* channels */ for (track = tracksbase->first; track; track = track->next) { MovieTrackingDopesheetChannel *channel; @@ -3838,5 +3923,8 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking) tracking_dopesheet_sort(tracking, sort_method, inverse); + /* frame coverage */ + tracking_dopesheet_calc_coverage(tracking); + dopesheet->ok = TRUE; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0e799b3d951..f3dd4e5d54a 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6450,6 +6450,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) clip->tracking.dopesheet.ok = 0; clip->tracking.dopesheet.channels.first = clip->tracking.dopesheet.channels.last = NULL; + clip->tracking.dopesheet.coverage_segments.first = clip->tracking.dopesheet.coverage_segments.last = NULL; link_list(fd, &tracking->objects); diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 09d97c36436..b1be9217819 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -145,6 +145,31 @@ static void draw_keyframe_shape(float x, float y, float xscale, float yscale, sh glPopMatrix(); } +static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip) +{ + View2D *v2d = &ar->v2d; + MovieTracking *tracking = &clip->tracking; + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + MovieTrackingDopesheetCoverageSegment *coverage_segment; + + for (coverage_segment = dopesheet->coverage_segments.first; + coverage_segment; + coverage_segment = coverage_segment->next) + { + if (coverage_segment->coverage < TRACKING_COVERAGE_OK) { + int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->start_frame); + int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame); + + if (coverage_segment->coverage == TRACKING_COVERAGE_BAD) + glColor4f(1.0f, 0.0f, 0.0f, 0.07f); + else + glColor4f(1.0f, 1.0f, 0.0f, 0.07f); + + glRectf(start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax); + } + } +} + void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) { MovieClip *clip = ED_space_clip_get_clip(sc); @@ -179,6 +204,8 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene) glEnable(GL_BLEND); + clip_draw_dopesheet_background(ar, clip); + for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float) (y - CHANNEL_HEIGHT_HALF); float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index b258fbaa668..8789a17a7f7 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -248,13 +248,28 @@ typedef struct MovieTrackingDopesheetChannel { int max_segment, total_frames; /* longest segment length and total number of tracked frames */ } MovieTrackingDopesheetChannel; +typedef struct MovieTrackingDopesheetCoverageSegment { + struct MovieTrackingDopesheetCoverageSegment *next, *prev; + + int coverage; + int start_frame; + int end_frame; + + int pad; +} MovieTrackingDopesheetCoverageSegment; + typedef struct MovieTrackingDopesheet { int ok; /* flag if dopesheet information is still relevant */ short sort_method; /* method to be used to sort tracks */ short flag; /* dopesheet building flag such as inverted order of sort */ - /* runtime stuff */ + /* ** runtime stuff ** */ + + /* summary */ + ListBase coverage_segments; + + /* detailed */ ListBase channels; int tot_channel; @@ -409,4 +424,11 @@ enum { TRACKING_DOPE_SHOW_HIDDEN = (1 << 2) }; +/* MovieTrackingDopesheetCoverageSegment->trackness */ +enum { + TRACKING_COVERAGE_BAD = 0, + TRACKING_COVERAGE_ACCEPTABLE = 1, + TRACKING_COVERAGE_OK = 2 +}; + #endif |