Blender V5.0
tracking.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <climits>
10#include <cmath>
11#include <cstddef>
12#include <cstdint>
13#include <limits>
14#include <memory.h>
15
16#include "MEM_guardedalloc.h"
17
18#include "DNA_anim_types.h"
19#include "DNA_camera_types.h"
20#include "DNA_defaults.h"
22#include "DNA_movieclip_types.h"
23#include "DNA_object_types.h" /* SELECT */
24#include "DNA_scene_types.h"
25
26#include "BLI_bitmap_draw_2d.h"
27#include "BLI_ghash.h"
28#include "BLI_hash.hh"
29#include "BLI_index_range.hh"
30#include "BLI_listbase.h"
31#include "BLI_math_base.h"
32#include "BLI_math_geom.h"
33#include "BLI_math_matrix.h"
34#include "BLI_math_vector.h"
36#include "BLI_string.h"
37#include "BLI_string_utf8.h"
38#include "BLI_string_utils.hh"
39#include "BLI_task.hh"
40#include "BLI_utildefines.h"
41
42#include "BLT_translation.hh"
43
44#include "BKE_fcurve.hh"
45#include "BKE_lib_id.hh"
46#include "BKE_movieclip.h"
47#include "BKE_object.hh"
48#include "BKE_scene.hh"
49#include "BKE_tracking.h"
50
51#include "IMB_imbuf.hh"
52#include "IMB_imbuf_types.hh"
53
54#include "RNA_prototypes.hh"
55
56#include "libmv-capi.h"
57#include "tracking_private.h"
58
59using blender::Array;
60using blender::int2;
61
64 /* Parameters needed for coordinates normalization. */
65 float principal_px[2];
67 float focal;
68};
69
70static struct {
73
74/* --------------------------------------------------------------------
75 * Common functions.
76 */
77
78/* Free the whole list of tracks, list's head and tail are set to nullptr. */
87
88/* Free the whole list of plane tracks, list's head and tail are set to nullptr. */
89static void tracking_plane_tracks_free(ListBase *plane_tracks)
90{
91 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks) {
93 }
94
95 BLI_freelistN(plane_tracks);
96}
97
98/* Free reconstruction structures, only frees contents of a structure,
99 * (if structure is allocated in heap, it shall be handled outside).
100 *
101 * All the pointers inside structure becomes invalid after this call.
102 */
104{
105 if (reconstruction->cameras) {
106 MEM_freeN(reconstruction->cameras);
107 }
108}
109
110/* Free memory used by tracking object, only frees contents of the structure,
111 * (if structure is allocated in heap, it shall be handled outside).
112 *
113 * All the pointers inside structure becomes invalid after this call.
114 */
115static void tracking_object_free(MovieTrackingObject *tracking_object)
116{
117 tracking_tracks_free(&tracking_object->tracks);
118 tracking_plane_tracks_free(&tracking_object->plane_tracks);
120}
121
122/* Free list of tracking objects, list's head and tail is set to nullptr. */
123static void tracking_objects_free(ListBase *objects)
124{
125 /* Free objects contents. */
126 LISTBASE_FOREACH (MovieTrackingObject *, object, objects) {
127 tracking_object_free(object);
128 }
129
130 /* Free objects themselves. */
131 BLI_freelistN(objects);
132}
133
134/* Free memory used by a dopesheet, only frees dopesheet contents.
135 * leaving dopesheet crystal clean for further usage.
136 */
138{
140
141 /* Free channel's segments. */
142 channel = static_cast<MovieTrackingDopesheetChannel *>(dopesheet->channels.first);
143 while (channel) {
144 if (channel->segments) {
145 MEM_freeN(channel->segments);
146 }
147
148 channel = channel->next;
149 }
150
151 /* Free lists themselves. */
152 BLI_freelistN(&dopesheet->channels);
153 BLI_freelistN(&dopesheet->coverage_segments);
154
155 /* Ensure lists are clean. */
156 BLI_listbase_clear(&dopesheet->channels);
158 dopesheet->tot_channel = 0;
159}
160
162{
163 tracking_objects_free(&tracking->objects);
164
165 if (tracking->camera.intrinsics) {
167 }
168
170}
171
173 /* Map from point and plane track pointer from the source object to the destination object. */
176};
177
179{
180 TrackingCopyContext ctx = {};
183 return ctx;
184}
185
187{
188 BLI_ghash_free(ctx->old_to_new_track_map, nullptr, nullptr);
189 BLI_ghash_free(ctx->old_to_new_plane_track_map, nullptr, nullptr);
190}
191
192/* Copy the whole list of tracks. */
194 ListBase *tracks_dst,
195 const ListBase *tracks_src,
196 const int flag)
197{
198 BLI_listbase_clear(tracks_dst);
199
200 LISTBASE_FOREACH (MovieTrackingTrack *, track_src, tracks_src) {
201 MovieTrackingTrack *track_dst = MEM_dupallocN<MovieTrackingTrack>(__func__, *track_src);
202 if (track_src->markers) {
203 track_dst->markers = static_cast<MovieTrackingMarker *>(MEM_dupallocN(track_src->markers));
204 }
206 id_us_plus(&track_dst->gpd->id);
207 }
208 BLI_addtail(tracks_dst, track_dst);
209
210 BLI_ghash_insert(ctx->old_to_new_track_map, track_src, track_dst);
211 }
212}
213
214/* Copy the whole list of plane tracks
215 * (need whole MovieTracking structures due to embedded pointers to tracks).
216 * WARNING: implies tracking_[dst/src] and their tracks have already been copied. */
218 ListBase *plane_tracks_list_dst,
219 const ListBase *plane_tracks_list_src,
220 const int flag)
221{
222 BLI_listbase_clear(plane_tracks_list_dst);
223
224 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track_src, plane_tracks_list_src) {
225 MovieTrackingPlaneTrack *plane_track_dst = MEM_dupallocN(__func__, *plane_track_src);
226 if (plane_track_src->markers) {
227 plane_track_dst->markers = static_cast<MovieTrackingPlaneMarker *>(
228 MEM_dupallocN(plane_track_src->markers));
229 }
231 sizeof(*plane_track_dst->point_tracks) * plane_track_dst->point_tracksnr, __func__);
232 for (int i = 0; i < plane_track_dst->point_tracksnr; i++) {
233 plane_track_dst->point_tracks[i] = static_cast<MovieTrackingTrack *>(
234 BLI_ghash_lookup(ctx->old_to_new_track_map, plane_track_src->point_tracks[i]));
235 BLI_assert(plane_track_dst->point_tracks[i] != nullptr);
236 }
238 id_us_plus(&plane_track_dst->image->id);
239 }
240 BLI_addtail(plane_tracks_list_dst, plane_track_dst);
241
242 BLI_ghash_insert(ctx->old_to_new_plane_track_map, plane_track_src, plane_track_dst);
243 }
244}
245
246/* Copy reconstruction structure. */
248 MovieTrackingReconstruction *reconstruction_dst,
249 const MovieTrackingReconstruction *reconstruction_src,
250 const int /*flag*/)
251{
252 *reconstruction_dst = *reconstruction_src;
253 if (reconstruction_src->cameras) {
254 reconstruction_dst->cameras = static_cast<MovieReconstructedCamera *>(
255 MEM_dupallocN(reconstruction_src->cameras));
256 }
257}
258
259/* Copy stabilization structure. */
261 const MovieTrackingStabilization *stabilization_src,
262 const int /*flag*/)
263{
264 *stabilization_dst = *stabilization_src;
265}
266
267/* Copy tracking object. */
268static void tracking_object_copy(MovieTrackingObject *tracking_object_dst,
269 const MovieTrackingObject *tracking_object_src,
270 const int flag)
271{
273
274 *tracking_object_dst = *tracking_object_src;
275
276 tracking_tracks_copy(&ctx, &tracking_object_dst->tracks, &tracking_object_src->tracks, flag);
278 &ctx, &tracking_object_dst->plane_tracks, &tracking_object_src->plane_tracks, flag);
280 &ctx, &tracking_object_dst->reconstruction, &tracking_object_src->reconstruction, flag);
281
282 if (tracking_object_src->active_track) {
283 tracking_object_dst->active_track = static_cast<MovieTrackingTrack *>(
284 BLI_ghash_lookup(ctx.old_to_new_track_map, tracking_object_src->active_track));
285 BLI_assert(tracking_object_dst->active_track != nullptr);
286 }
287 if (tracking_object_src->active_plane_track) {
288 tracking_object_dst->active_plane_track = static_cast<MovieTrackingPlaneTrack *>(
290 BLI_assert(tracking_object_dst->active_plane_track != nullptr);
291 }
292
294}
295
296/* Copy list of tracking objects. */
297static void tracking_objects_copy(ListBase *tracking_objects_dst,
298 const ListBase *tracking_objects_src,
299 const int flag)
300{
301 BLI_listbase_clear(tracking_objects_dst);
302
303 LISTBASE_FOREACH (MovieTrackingObject *, tracking_object_src, tracking_objects_src) {
304 MovieTrackingObject *tracking_object_dst = MEM_callocN<MovieTrackingObject>(__func__);
305 tracking_object_copy(tracking_object_dst, tracking_object_src, flag);
306 BLI_addtail(tracking_objects_dst, tracking_object_dst);
307 }
308}
309
311 const MovieTracking *tracking_src,
312 const int flag)
313{
314 *tracking_dst = *tracking_src;
315
316 tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization, flag);
317
318 tracking_objects_copy(&tracking_dst->objects, &tracking_src->objects, flag);
319
320 /* Those remaining are runtime data, they will be reconstructed as needed,
321 * do not bother copying them. */
322 tracking_dst->dopesheet.ok = false;
323 BLI_listbase_clear(&tracking_dst->dopesheet.channels);
325
326 tracking_dst->camera.intrinsics = nullptr;
327 tracking_dst->stats = nullptr;
328}
329
331{
332 tracking->camera.sensor_width = 35.0f;
333 tracking->camera.pixel_aspect = 1.0f;
334 tracking->camera.units = CAMERA_UNITS_MM;
335
337 tracking->settings.default_minimum_correlation = 0.75;
338 tracking->settings.default_pattern_size = 21;
339 tracking->settings.default_search_size = 71;
341 tracking->settings.default_weight = 1.0f;
342 tracking->settings.dist = 1;
343 tracking->settings.object_distance = 1;
345
346 tracking->stabilization.scaleinf = 1.0f;
347 tracking->stabilization.anchor_frame = 1;
349 tracking->stabilization.target_rot = 0.0f;
350 tracking->stabilization.scale = 1.0f;
351
352 tracking->stabilization.act_track = 0;
353 tracking->stabilization.act_rot_track = 0;
354 tracking->stabilization.tot_track = 0;
355 tracking->stabilization.tot_rot_track = 0;
356
357 tracking->stabilization.scaleinf = 1.0f;
358 tracking->stabilization.locinf = 1.0f;
359 tracking->stabilization.rotinf = 1.0f;
360 tracking->stabilization.maxscale = 2.0f;
363
364 /* Descending order of average error: tracks with the highest error are on top. */
367
368 BKE_tracking_object_add(tracking, DATA_("Camera"));
369}
370
371void BKE_tracking_get_camera_object_matrix(const Object *camera_object, float mat[4][4])
372{
373 BLI_assert(camera_object != nullptr);
374 /* NOTE: Construct matrix from scratch rather than using obmat because the camera object here
375 * will have camera solver constraint taken into account. But here we do not want or need it:
376 * object is solved in camera space (as in, camera is stationary and object is moving).
377 *
378 * This will include animation applied on the camera, but not possible camera rig. This isn't
379 * an issue in practice due to the way how VFX is constructed.
380 *
381 * If we ever need to support crazy setups like that one possible solution would be to use
382 * final camera matrix and multiple it by an inverse of solved camera matrix at the current
383 * frame. */
384 BKE_object_where_is_calc_mat4(camera_object, mat);
385}
386
388 MovieTrackingObject *tracking_object,
389 int framenr,
390 int winx,
391 int winy,
392 float mat[4][4])
393{
395 float lens = tracking->camera.focal * tracking->camera.sensor_width / float(winx);
396 float viewfac, pixsize, left, right, bottom, top, clipsta, clipend;
397 float winmat[4][4];
398 float ycor = 1.0f / tracking->camera.pixel_aspect;
399 float shiftx, shifty, winside = float(min_ii(winx, winy));
400
401 BKE_tracking_camera_shift_get(tracking, winx, winy, &shiftx, &shifty);
402
403 clipsta = 0.1f;
404 clipend = 1000.0f;
405
406 if (winx >= winy) {
407 viewfac = (lens * winx) / tracking->camera.sensor_width;
408 }
409 else {
410 viewfac = (ycor * lens * winy) / tracking->camera.sensor_width;
411 }
412
413 pixsize = clipsta / viewfac;
414
415 left = -0.5f * float(winx) + shiftx * winside;
416 bottom = -0.5f * (ycor) * float(winy) + shifty * winside;
417 right = 0.5f * float(winx) + shiftx * winside;
418 top = 0.5f * (ycor) * float(winy) + shifty * winside;
419
420 left *= pixsize;
421 right *= pixsize;
422 bottom *= pixsize;
423 top *= pixsize;
424
425 perspective_m4(winmat, left, right, bottom, top, clipsta, clipend);
426
427 camera = BKE_tracking_camera_get_reconstructed(tracking, tracking_object, framenr);
428
429 if (camera) {
430 float imat[4][4];
431
432 invert_m4_m4(imat, camera->mat);
433 mul_m4_m4m4(mat, winmat, imat);
434 }
435 else {
436 copy_m4_m4(mat, winmat);
437 }
438}
439
440/* --------------------------------------------------------------------
441 * Clipboard.
442 */
443
445{
446 MovieTrackingTrack *track = static_cast<MovieTrackingTrack *>(tracking_clipboard.tracks.first),
447 *next_track;
448
449 while (track) {
450 next_track = track->next;
451
453 MEM_freeN(track);
454
455 track = next_track;
456 }
457
459}
460
462 MovieTrackingObject *tracking_object)
463{
464 /* First drop all tracks from current clipboard. */
466
467 /* Then copy all selected visible tracks to it. */
468 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
469 if (TRACK_SELECTED(track) && (track->flag & TRACK_HIDDEN) == 0) {
471
472 BLI_addtail(&tracking_clipboard.tracks, new_track);
473 }
474 }
475}
476
478{
479 return (BLI_listbase_is_empty(&tracking_clipboard.tracks) == false);
480}
481
483 MovieTrackingObject *tracking_object)
484{
487
488 /* TODO(sergey): Preserve active track from before the copy. */
489 if (track->prev == nullptr) {
490 tracking_object->active_track = new_track;
491 }
492
493 BLI_addtail(&tracking_object->tracks, new_track);
494 BKE_tracking_track_unique_name(&tracking_object->tracks, new_track);
495 }
496}
497
498/* --------------------------------------------------------------------
499 * Tracks.
500 */
501
503{
504 const MovieTrackingSettings *settings = &tracking->settings;
505
506 MovieTrackingTrack *track = MEM_callocN<MovieTrackingTrack>("add_marker_exec track");
508
509 /* Fill track's settings from default settings. */
510 track->motion_model = settings->default_motion_model;
512 track->margin = settings->default_margin;
513 track->pattern_match = settings->default_pattern_match;
514 track->frames_limit = settings->default_frames_limit;
515 track->flag = settings->default_flag;
516 track->algorithm_flag = settings->default_algorithm_flag;
517 track->weight = settings->default_weight;
518 track->weight_stab = settings->default_weight;
519
520 BLI_addtail(tracks_list, track);
521 BKE_tracking_track_unique_name(tracks_list, track);
522
523 return track;
524}
525
527 ListBase *tracksbase,
528 float x,
529 float y,
530 int framenr,
531 int width,
532 int height)
533{
534 const MovieTrackingSettings *settings = &tracking->settings;
535
536 MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase);
537
538 const float half_pattern_px = settings->default_pattern_size / 2.0f;
539 const float half_search_px = settings->default_search_size / 2.0f;
540
541 const float pattern_size[2] = {half_pattern_px / width, half_pattern_px / height};
542 const float search_size[2] = {half_search_px / width, half_search_px / height};
543
544 MovieTrackingMarker marker = {};
545 marker.pos[0] = x;
546 marker.pos[1] = y;
547 marker.framenr = framenr;
548
549 marker.pattern_corners[0][0] = -pattern_size[0];
550 marker.pattern_corners[0][1] = -pattern_size[1];
551
552 marker.pattern_corners[1][0] = pattern_size[0];
553 marker.pattern_corners[1][1] = -pattern_size[1];
554
555 negate_v2_v2(marker.pattern_corners[2], marker.pattern_corners[0]);
556 negate_v2_v2(marker.pattern_corners[3], marker.pattern_corners[1]);
557
558 copy_v2_v2(marker.search_max, search_size);
559 negate_v2_v2(marker.search_min, search_size);
560
561 BKE_tracking_marker_insert(track, &marker);
562
563 return track;
564}
565
567{
568 MovieTrackingTrack *new_track;
569
570 new_track = MEM_callocN<MovieTrackingTrack>("tracking_track_duplicate new_track");
571
572 *new_track = *track;
573 new_track->next = new_track->prev = nullptr;
574
575 new_track->markers = static_cast<MovieTrackingMarker *>(MEM_dupallocN(new_track->markers));
576
577 /* Prevent duplicate from being used for 2D stabilization.
578 * If necessary, it shall be added explicitly.
579 */
580 new_track->flag &= ~TRACK_USE_2D_STAB;
581 new_track->flag &= ~TRACK_USE_2D_STAB_ROT;
582
583 return new_track;
584}
585
587{
588 BLI_uniquename(tracksbase,
589 track,
591 '.',
593 sizeof(track->name));
594}
595
597{
598 if (track->markers) {
599 MEM_freeN(track->markers);
600 }
601}
602
604 int *r_first_frame,
605 int *r_last_frame)
606{
607 BLI_assert(track->markersnr > 0);
608 const int last_marker_index = track->markersnr - 1;
609 *r_first_frame = track->markers[0].framenr;
610 *r_last_frame = track->markers[last_marker_index].framenr;
611}
612
614 const int num_tracks,
615 int *r_first_frame,
616 int *r_last_frame)
617{
618 *r_first_frame = INT_MAX;
619 *r_last_frame = INT_MIN;
620 for (int i = 0; i < num_tracks; ++i) {
621 const MovieTrackingTrack *track = tracks[i];
622 int track_first_frame, track_last_frame;
623 BKE_tracking_track_first_last_frame_get(track, &track_first_frame, &track_last_frame);
624 *r_first_frame = min_ii(*r_first_frame, track_first_frame);
625 *r_last_frame = max_ii(*r_last_frame, track_last_frame);
626 }
627}
628
630{
631 int num_selected_tracks = 0;
632 LISTBASE_FOREACH (const MovieTrackingTrack *, track, tracks_list) {
633 if (TRACK_SELECTED(track)) {
634 ++num_selected_tracks;
635 }
636 }
637 return num_selected_tracks;
638}
639
641{
642 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
643 return BKE_tracking_count_selected_tracks_in_list(&tracking_object->tracks);
644}
645
647 int *r_num_tracks)
648{
649 *r_num_tracks = 0;
650
651 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
652
653 /* Initialize input. */
654 const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking);
655 if (num_selected_tracks == 0) {
656 return nullptr;
657 }
658
660 num_selected_tracks, "selected tracks array");
661 int source_track_index = 0;
662 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
663 if (!TRACK_SELECTED(track)) {
664 continue;
665 }
666 source_tracks[source_track_index] = track;
667 ++source_track_index;
668 }
669
670 *r_num_tracks = num_selected_tracks;
671
672 return source_tracks;
673}
674
676{
677 if (area == TRACK_AREA_NONE) {
678 return;
679 }
680
681 if (area & TRACK_AREA_POINT) {
682 track->flag |= flag;
683 }
684 if (area & TRACK_AREA_PAT) {
685 track->pat_flag |= flag;
686 }
687 if (area & TRACK_AREA_SEARCH) {
688 track->search_flag |= flag;
689 }
690}
691
693{
694 if (area == TRACK_AREA_NONE) {
695 return;
696 }
697
698 if (area & TRACK_AREA_POINT) {
699 track->flag &= ~flag;
700 }
701 if (area & TRACK_AREA_PAT) {
702 track->pat_flag &= ~flag;
703 }
704 if (area & TRACK_AREA_SEARCH) {
705 track->search_flag &= ~flag;
706 }
707}
708
710{
711 return BKE_tracking_marker_get_exact(track, framenr) != nullptr;
712}
713
715{
716 MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
717
718 return marker && (marker->flag & MARKER_DISABLED) == 0;
719}
720
721static void path_clear_remained(MovieTrackingTrack *track, const int ref_frame)
722{
723 for (int a = 1; a < track->markersnr; a++) {
724 if (track->markers[a].framenr > ref_frame) {
725 track->markersnr = a;
726 track->markers = static_cast<MovieTrackingMarker *>(
727 MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr));
728
729 break;
730 }
731 }
732
733 if (track->markersnr) {
734 tracking_marker_insert_disabled(track, &track->markers[track->markersnr - 1], false, true);
735 }
736}
737
738static void path_clear_up_to(MovieTrackingTrack *track, const int ref_frame)
739{
740 for (int a = track->markersnr - 1; a >= 0; a--) {
741 if (track->markers[a].framenr <= ref_frame) {
742 memmove(track->markers,
743 track->markers + a,
744 (track->markersnr - a) * sizeof(MovieTrackingMarker));
745
746 track->markersnr = track->markersnr - a;
747 track->markers = static_cast<MovieTrackingMarker *>(
748 MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr));
749
750 break;
751 }
752 }
753
754 if (track->markersnr) {
755 tracking_marker_insert_disabled(track, &track->markers[0], true, true);
756 }
757}
758
759static void path_clear_all(MovieTrackingTrack *track, const int ref_frame)
760{
761 MovieTrackingMarker *marker, marker_new;
762
763 marker = BKE_tracking_marker_get(track, ref_frame);
764 marker_new = *marker;
765
766 MEM_freeN(track->markers);
767 track->markers = nullptr;
768 track->markersnr = 0;
769
770 BKE_tracking_marker_insert(track, &marker_new);
771
772 tracking_marker_insert_disabled(track, &marker_new, true, true);
773 tracking_marker_insert_disabled(track, &marker_new, false, true);
774}
775
777 const int ref_frame,
778 const eTrackClearAction action)
779{
780 switch (action) {
782 path_clear_remained(track, ref_frame);
783 break;
784 case TRACK_CLEAR_UPTO:
785 path_clear_up_to(track, ref_frame);
786 break;
787 case TRACK_CLEAR_ALL:
788 path_clear_all(track, ref_frame);
789 break;
790 };
791}
792
794 MovieTrackingTrack *dst_track,
795 MovieTrackingTrack *src_track)
796{
797 int i = 0, a = 0, b = 0, tot;
798 MovieTrackingMarker *markers;
799
800 tot = dst_track->markersnr + src_track->markersnr;
801 markers = MEM_calloc_arrayN<MovieTrackingMarker>(tot, "tmp tracking joined tracks");
802
803 while (a < src_track->markersnr || b < dst_track->markersnr) {
804 if (b >= dst_track->markersnr) {
805 markers[i] = src_track->markers[a++];
806 }
807 else if (a >= src_track->markersnr) {
808 markers[i] = dst_track->markers[b++];
809 }
810 else if (src_track->markers[a].framenr < dst_track->markers[b].framenr) {
811 markers[i] = src_track->markers[a++];
812 }
813 else if (src_track->markers[a].framenr > dst_track->markers[b].framenr) {
814 markers[i] = dst_track->markers[b++];
815 }
816 else {
817 if ((src_track->markers[a].flag & MARKER_DISABLED) == 0) {
818 if ((dst_track->markers[b].flag & MARKER_DISABLED) == 0) {
819 /* both tracks are enabled on this frame, so find the whole segment
820 * on which tracks are intersecting and blend tracks using linear
821 * interpolation to prevent jumps
822 */
823
824 MovieTrackingMarker *marker_a, *marker_b;
825 int start_a = a, start_b = b, len = 0, frame = src_track->markers[a].framenr;
826 int inverse = 0;
827
828 inverse = (b == 0) || (dst_track->markers[b - 1].flag & MARKER_DISABLED) ||
829 (dst_track->markers[b - 1].framenr != frame - 1);
830
831 /* find length of intersection */
832 while (a < src_track->markersnr && b < dst_track->markersnr) {
833 marker_a = &src_track->markers[a];
834 marker_b = &dst_track->markers[b];
835
836 if (marker_a->flag & MARKER_DISABLED || marker_b->flag & MARKER_DISABLED) {
837 break;
838 }
839
840 if (marker_a->framenr != frame || marker_b->framenr != frame) {
841 break;
842 }
843
844 frame++;
845 len++;
846 a++;
847 b++;
848 }
849
850 a = start_a;
851 b = start_b;
852
853 /* linear interpolation for intersecting frames */
854 for (int j = 0; j < len; j++) {
855 float fac = 0.5f;
856
857 if (len > 1) {
858 fac = 1.0f / (len - 1) * j;
859 }
860
861 if (inverse) {
862 fac = 1.0f - fac;
863 }
864
865 marker_a = &src_track->markers[a];
866 marker_b = &dst_track->markers[b];
867
868 markers[i] = dst_track->markers[b];
869 interp_v2_v2v2(markers[i].pos, marker_b->pos, marker_a->pos, fac);
870 a++;
871 b++;
872 i++;
873 }
874
875 /* this values will be incremented at the end of the loop cycle */
876 a--;
877 b--;
878 i--;
879 }
880 else {
881 markers[i] = src_track->markers[a];
882 }
883 }
884 else {
885 markers[i] = dst_track->markers[b];
886 }
887
888 a++;
889 b++;
890 }
891
892 i++;
893 }
894
895 MEM_freeN(dst_track->markers);
896
897 dst_track->markers = MEM_calloc_arrayN<MovieTrackingMarker>(i, "tracking joined tracks");
898 memcpy(dst_track->markers, markers, i * sizeof(MovieTrackingMarker));
899
900 dst_track->markersnr = i;
901
902 MEM_freeN(markers);
903
905}
906
908 const MovieTrackingMarker *src_marker)
909{
910 BLI_assert(dst_marker->framenr == src_marker->framenr);
911
912 if (src_marker->flag & MARKER_DISABLED) {
913 return;
914 }
915
916 add_v2_v2(dst_marker->pos, src_marker->pos);
917 for (int corner = 0; corner < 4; ++corner) {
918 add_v2_v2(dst_marker->pattern_corners[corner], src_marker->pattern_corners[corner]);
919 }
920 add_v2_v2(dst_marker->search_min, src_marker->search_min);
921 add_v2_v2(dst_marker->search_max, src_marker->search_max);
922
923 BLI_assert(is_finite_v2(src_marker->search_min));
924 BLI_assert(is_finite_v2(src_marker->search_max));
925
926 dst_marker->flag &= ~MARKER_DISABLED;
927 if ((src_marker->flag & MARKER_TRACKED) == 0) {
928 dst_marker->flag &= ~MARKER_TRACKED;
929 }
930}
931
932static void multiply_marker(MovieTrackingMarker *marker, const float multiplier)
933{
934 mul_v2_fl(marker->pos, multiplier);
935 for (int corner = 0; corner < 4; ++corner) {
936 mul_v2_fl(marker->pattern_corners[corner], multiplier);
937 }
938 mul_v2_fl(marker->search_min, multiplier);
939 mul_v2_fl(marker->search_max, multiplier);
940}
941
942/* Helper function for BKE_tracking_tracks_average which takes care of averaging fields of
943 * markers (position, patterns, ...). */
945 /*const*/ MovieTrackingTrack **src_tracks,
946 const int num_src_tracks)
947{
948 /* Get global range of frames within which averaging would happen. */
949 int first_frame, last_frame;
951 src_tracks, num_src_tracks, &first_frame, &last_frame);
952 if (last_frame < first_frame) {
953 return;
954 }
955 const int num_frames = last_frame - first_frame + 1;
956
957 /* Allocate temporary array where averaging will happen into. */
959 num_frames, "tracks average accumulator");
960 int *counters = MEM_calloc_arrayN<int>(num_frames, "tracks accumulator counters");
961 for (int frame = first_frame; frame <= last_frame; ++frame) {
962 const int frame_index = frame - first_frame;
963 accumulator[frame_index].framenr = frame;
964 accumulator[frame_index].flag |= (MARKER_DISABLED | MARKER_TRACKED);
965 }
966
967 /* Accumulate track markers. */
968 for (int track_index = 0; track_index < num_src_tracks; ++track_index) {
969 /*const*/ MovieTrackingTrack *track = src_tracks[track_index];
970 for (int frame = first_frame; frame <= last_frame; ++frame) {
971 MovieTrackingMarker interpolated_marker;
972 if (!BKE_tracking_marker_get_interpolated(track, frame, &interpolated_marker)) {
973 continue;
974 }
975 const int frame_index = frame - first_frame;
976 accumulate_marker(&accumulator[frame_index], &interpolated_marker);
977 ++counters[frame_index];
978 }
979 }
980
981 /* Average and store the result. */
982 for (int frame = first_frame; frame <= last_frame; ++frame) {
983 /* Average. */
984 const int frame_index = frame - first_frame;
985 if (!counters[frame_index]) {
986 continue;
987 }
988 const float multiplier = 1.0f / float(counters[frame_index]);
989 multiply_marker(&accumulator[frame_index], multiplier);
990 /* Store the result. */
991 BKE_tracking_marker_insert(dst_track, &accumulator[frame_index]);
992 }
993
994 /* Free memory. */
995 MEM_freeN(accumulator);
996 MEM_freeN(counters);
997}
998
999/* Helper function for BKE_tracking_tracks_average which takes care of averaging fields of
1000 * tracks (track for example, offset). */
1002 /*const*/ MovieTrackingTrack **src_tracks,
1003 const int num_src_tracks)
1004{
1005 /* TODO(sergey): Consider averaging weight, stabilization weight, maybe even bundle position. */
1006 zero_v2(dst_track->offset);
1007 for (int track_index = 0; track_index < num_src_tracks; track_index++) {
1008 add_v2_v2(dst_track->offset, src_tracks[track_index]->offset);
1009 }
1010 mul_v2_fl(dst_track->offset, 1.0f / num_src_tracks);
1011}
1012
1014 /*const*/ MovieTrackingTrack **src_tracks,
1015 const int num_src_tracks)
1016{
1017 if (num_src_tracks == 0) {
1018 return;
1019 }
1020
1021 tracking_average_markers(dst_track, src_tracks, num_src_tracks);
1022 tracking_average_tracks(dst_track, src_tracks, num_src_tracks);
1023}
1024
1026 int selection_index,
1027 ListBase **r_tracksbase)
1028{
1029 int cur = 1;
1030
1031 LISTBASE_FOREACH (MovieTrackingObject *, object, &tracking->objects) {
1032 LISTBASE_FOREACH (MovieTrackingTrack *, track, &object->tracks) {
1033 if (track->flag & TRACK_HAS_BUNDLE) {
1034 if (cur == selection_index) {
1035 *r_tracksbase = &object->tracks;
1036 return track;
1037 }
1038
1039 cur++;
1040 }
1041 }
1042 }
1043
1044 *r_tracksbase = nullptr;
1045
1046 return nullptr;
1047}
1048
1050{
1051 bGPDlayer *layer;
1052
1053 if (!track->gpd) {
1054 return nullptr;
1055 }
1056
1057 layer = static_cast<bGPDlayer *>(track->gpd->layers.first);
1058
1059 while (layer) {
1060 if (layer->flag & GP_LAYER_ACTIVE) {
1061 bGPDframe *frame = static_cast<bGPDframe *>(layer->frames.first);
1062 bool ok = false;
1063
1064 while (frame) {
1065 if (frame->strokes.first) {
1066 ok = true;
1067 break;
1068 }
1069
1070 frame = frame->next;
1071 }
1072
1073 if (ok) {
1074 return layer;
1075 }
1076 }
1077
1078 layer = layer->next;
1079 }
1080
1081 return nullptr;
1082}
1083
1089
1090static void track_mask_set_pixel_cb(int x, int x_end, int y, void *user_data)
1091{
1093 size_t index = size_t(y) * data->mask_width + x;
1094 size_t index_end = size_t(y) * data->mask_width + x_end;
1095 do {
1096 data->mask[index] = 1.0f;
1097 } while (++index != index_end);
1098}
1099
1100static void track_mask_gpencil_layer_rasterize(const int frame_width,
1101 const int frame_height,
1102 const float region_min[2],
1103 const bGPDlayer *layer,
1104 float *mask,
1105 const int mask_width,
1106 const int mask_height)
1107{
1108 const bGPDframe *frame = static_cast<const bGPDframe *>(layer->frames.first);
1110
1111 data.mask = mask;
1112 data.mask_width = mask_width;
1113 data.mask_height = mask_height;
1114
1115 while (frame) {
1116 const bGPDstroke *stroke = static_cast<const bGPDstroke *>(frame->strokes.first);
1117
1118 while (stroke) {
1119 const bGPDspoint *stroke_points = stroke->points;
1120 if (stroke->flag & GP_STROKE_2DSPACE) {
1121 Array<int2> mask_points(stroke->totpoints);
1122 for (const int i : mask_points.index_range()) {
1123 mask_points[i][0] = stroke_points[i].x * frame_width - region_min[0];
1124 mask_points[i][1] = stroke_points[i].y * frame_height - region_min[1];
1125 }
1126 /* TODO: add an option to control whether AA is enabled or not */
1128 0, 0, mask_width, mask_height, mask_points, track_mask_set_pixel_cb, &data);
1129 }
1130 stroke = stroke->next;
1131 }
1132 frame = frame->next;
1133 }
1134}
1135
1136float *tracking_track_get_mask_for_region(const int frame_width,
1137 const int frame_height,
1138 const float region_min[2],
1139 const float region_max[2],
1140 const MovieTrackingTrack *track)
1141{
1142 float *mask = nullptr;
1143 const bGPDlayer *layer = track_mask_gpencil_layer_get(track);
1144 if (layer != nullptr) {
1145 const int mask_width = region_max[0] - region_min[0];
1146 const int mask_height = region_max[1] - region_min[1];
1147 mask = MEM_calloc_arrayN<float>(mask_width * mask_height, "track mask");
1149 frame_width, frame_height, region_min, layer, mask, mask_width, mask_height);
1150 }
1151 return mask;
1152}
1153
1154float *BKE_tracking_track_get_mask(const int frame_width,
1155 const int frame_height,
1156 const MovieTrackingTrack *track,
1157 const MovieTrackingMarker *marker)
1158{
1159 /* Convert normalized space marker's search area to pixel-space region. */
1160 const float region_min[2] = {
1161 marker->search_min[0] * frame_width,
1162 marker->search_min[1] * frame_height,
1163 };
1164 const float region_max[2] = {
1165 marker->search_max[0] * frame_width,
1166 marker->search_max[1] * frame_height,
1167 };
1169 frame_width, frame_height, region_min, region_max, track);
1170}
1171
1173 MovieTrackingTrack *track,
1174 MovieTrackingMarker *marker)
1175{
1176 const FCurve *weight_fcurve;
1177 float weight = track->weight;
1178
1179 weight_fcurve = id_data_find_fcurve(
1180 &clip->id, track, &RNA_MovieTrackingTrack, "weight", 0, nullptr);
1181
1182 if (weight_fcurve) {
1183 int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
1184 weight = evaluate_fcurve(weight_fcurve, scene_framenr);
1185 }
1186
1187 return weight;
1188}
1189
1191 MovieTrackingTrack *track,
1192 int area,
1193 bool extend)
1194{
1195 if (extend) {
1196 BKE_tracking_track_flag_set(track, area, SELECT);
1197 }
1198 else {
1199 MovieTrackingTrack *cur = static_cast<MovieTrackingTrack *>(tracksbase->first);
1200
1201 while (cur) {
1202 if ((cur->flag & TRACK_HIDDEN) == 0) {
1203 if (cur == track) {
1206 }
1207 else {
1209 }
1210 }
1211
1212 cur = cur->next;
1213 }
1214 }
1215}
1216
1218{
1220}
1221
1223{
1224 LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
1225 if ((track->flag & TRACK_HIDDEN) == 0) {
1227 }
1228 }
1229}
1230
1231/* --------------------------------------------------------------------
1232 * Marker.
1233 */
1234
1236 MovieTrackingMarker *marker)
1237{
1238 MovieTrackingMarker *old_marker = nullptr;
1239
1240 if (track->markersnr) {
1241 old_marker = BKE_tracking_marker_get_exact(track, marker->framenr);
1242 }
1243
1244 if (old_marker) {
1245 /* simply replace settings for already allocated marker */
1246 *old_marker = *marker;
1247
1248 return old_marker;
1249 }
1250
1251 int a = track->markersnr;
1252
1253 /* find position in array where to add new marker */
1254 while (a--) {
1255 if (track->markers[a].framenr < marker->framenr) {
1256 break;
1257 }
1258 }
1259
1260 track->markersnr++;
1261
1262 if (track->markers) {
1263 track->markers = static_cast<MovieTrackingMarker *>(
1264 MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr));
1265 }
1266 else {
1267 track->markers = MEM_callocN<MovieTrackingMarker>("MovieTracking markers");
1268 }
1269
1270 /* shift array to "free" space for new marker */
1271 memmove(track->markers + a + 2,
1272 track->markers + a + 1,
1273 (track->markersnr - a - 2) * sizeof(MovieTrackingMarker));
1274
1275 /* put new marker */
1276 track->markers[a + 1] = *marker;
1277
1278 return &track->markers[a + 1];
1279}
1280
1282{
1283 int a = 0;
1284
1285 while (a < track->markersnr) {
1286 if (track->markers[a].framenr == framenr) {
1287 if (track->markersnr > 1) {
1288 memmove(track->markers + a,
1289 track->markers + a + 1,
1290 (track->markersnr - a - 1) * sizeof(MovieTrackingMarker));
1291 track->markersnr--;
1292 track->markers = static_cast<MovieTrackingMarker *>(
1293 MEM_reallocN(track->markers, sizeof(MovieTrackingMarker) * track->markersnr));
1294 }
1295 else {
1296 MEM_freeN(track->markers);
1297 track->markers = nullptr;
1298 track->markersnr = 0;
1299 }
1300
1301 break;
1302 }
1303
1304 a++;
1305 }
1306}
1307
1309{
1310 float pat_min[2], pat_max[2];
1311 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1312
1313 for (int a = 0; a < 2; a++) {
1314 if (pat_min[a] < marker->search_min[a]) {
1315 for (int b = 0; b < 4; b++) {
1316 marker->pattern_corners[b][a] += marker->search_min[a] - pat_min[a];
1317 }
1318 }
1319 if (pat_max[a] > marker->search_max[a]) {
1320 for (int b = 0; b < 4; b++) {
1321 marker->pattern_corners[b][a] -= pat_max[a] - marker->search_max[a];
1322 }
1323 }
1324 }
1325}
1326
1328{
1329 float pat_min[2], pat_max[2];
1330 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1331
1332 for (int a = 0; a < 2; a++) {
1333 marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]);
1334 marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]);
1335 }
1336}
1337
1339{
1340 float pat_min[2], pat_max[2];
1341 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
1342
1343 float dim[2];
1344 sub_v2_v2v2(dim, marker->search_max, marker->search_min);
1345
1346 for (int a = 0; a < 2; a++) {
1347 if (marker->search_min[a] > pat_min[a]) {
1348 marker->search_min[a] = pat_min[a];
1349 marker->search_max[a] = marker->search_min[a] + dim[a];
1350 }
1351 if (marker->search_max[a] < pat_max[a]) {
1352 marker->search_max[a] = pat_max[a];
1353 marker->search_min[a] = marker->search_max[a] - dim[a];
1354 }
1355 }
1356}
1357
1359{
1360 const int num_markers = track->markersnr;
1361
1362 if (num_markers == 0) {
1363 BLI_assert_msg(0, "Detected degenerated track, should never happen.");
1364 return nullptr;
1365 }
1366
1367 int left_boundary = 0;
1368 int right_boundary = num_markers;
1369 while (left_boundary < right_boundary) {
1370 const int median_index = (left_boundary + right_boundary) / 2;
1371 MovieTrackingMarker *marker = &track->markers[median_index];
1372
1373 if (marker->framenr == framenr) {
1374 return marker;
1375 }
1376
1377 if (marker->framenr < framenr) {
1378 left_boundary = median_index + 1;
1379 }
1380 else {
1381 BLI_assert(marker->framenr > framenr);
1382 right_boundary = median_index - 1;
1383 }
1384 }
1385
1386 const int closest_index = clamp_i(right_boundary, 0, num_markers - 1);
1387
1388 return &track->markers[closest_index];
1389}
1390
1392{
1393 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1394
1395 if (marker->framenr != framenr) {
1396 return nullptr;
1397 }
1398
1399 return marker;
1400}
1401
1403{
1404 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1405
1406 if (marker->framenr != framenr) {
1407 MovieTrackingMarker marker_new;
1408
1409 marker_new = *marker;
1410 marker_new.framenr = framenr;
1411
1412 BKE_tracking_marker_insert(track, &marker_new);
1413 marker = BKE_tracking_marker_get(track, framenr);
1414 }
1415
1416 return marker;
1417}
1418
1420 MovieTrackingTrack *track, const MovieTrackingMarker *anchor_marker, const int direction)
1421{
1422 BLI_assert(ELEM(direction, -1, 1));
1423
1424 const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1;
1425 const MovieTrackingMarker *current_marker = anchor_marker;
1426
1427 while (current_marker >= track->markers && current_marker <= last_marker) {
1428 if ((current_marker->flag & MARKER_DISABLED) == 0) {
1429 return current_marker;
1430 }
1431 current_marker += direction;
1432 }
1433
1434 return nullptr;
1435}
1436
1438 const int framenr,
1439 MovieTrackingMarker *r_marker)
1440{
1441 const MovieTrackingMarker *closest_marker = BKE_tracking_marker_get(track, framenr);
1442 if (closest_marker == nullptr) {
1443 return false;
1444 }
1445 if (closest_marker->framenr == framenr && (closest_marker->flag & MARKER_DISABLED) == 0) {
1446 *r_marker = *closest_marker;
1447 return true;
1448 }
1449
1451 track, closest_marker, -1);
1452 if (left_marker == nullptr) {
1453 return false;
1454 }
1455
1457 track, closest_marker + 1, 1);
1458 if (right_marker == nullptr) {
1459 return false;
1460 }
1461
1462 if (left_marker == right_marker) {
1463 *r_marker = *left_marker;
1464 return true;
1465 }
1466
1467 const float factor = float(framenr - left_marker->framenr) /
1468 (right_marker->framenr - left_marker->framenr);
1469
1470 interp_v2_v2v2(r_marker->pos, left_marker->pos, right_marker->pos, factor);
1471
1472 for (int i = 0; i < 4; i++) {
1473 interp_v2_v2v2(r_marker->pattern_corners[i],
1474 left_marker->pattern_corners[i],
1475 right_marker->pattern_corners[i],
1476 factor);
1477 }
1478
1479 interp_v2_v2v2(r_marker->search_min, left_marker->search_min, right_marker->search_min, factor);
1480 interp_v2_v2v2(r_marker->search_max, left_marker->search_max, right_marker->search_max, factor);
1481
1482 r_marker->framenr = framenr;
1483 r_marker->flag = 0;
1484
1485 if (framenr == left_marker->framenr) {
1486 r_marker->flag = left_marker->flag;
1487 }
1488 else if (framenr == right_marker->framenr) {
1489 r_marker->flag = right_marker->flag;
1490 }
1491
1492 return true;
1493}
1494
1496 float min[2],
1497 float max[2])
1498{
1500
1501 minmax_v2v2_v2(min, max, marker->pattern_corners[0]);
1502 minmax_v2v2_v2(min, max, marker->pattern_corners[1]);
1503 minmax_v2v2_v2(min, max, marker->pattern_corners[2]);
1504 minmax_v2v2_v2(min, max, marker->pattern_corners[3]);
1505}
1506
1508 float framenr,
1509 float pos[2])
1510{
1511 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, int(framenr));
1512 MovieTrackingMarker *marker_last = track->markers + (track->markersnr - 1);
1513
1514 if (marker != marker_last) {
1515 MovieTrackingMarker *marker_next = marker + 1;
1516
1517 if (marker_next->framenr == marker->framenr + 1) {
1518 /* Currently only do sub-framing inside tracked ranges, do not extrapolate tracked segments
1519 * could be changed when / if mask parent would be interpolating position in-between
1520 * tracked segments. */
1521
1522 float fac = (framenr - int(framenr)) / (marker_next->framenr - marker->framenr);
1523
1524 interp_v2_v2v2(pos, marker->pos, marker_next->pos, fac);
1525 }
1526 else {
1527 copy_v2_v2(pos, marker->pos);
1528 }
1529 }
1530 else {
1531 copy_v2_v2(pos, marker->pos);
1532 }
1533
1534 /* currently track offset is always wanted to be applied here, could be made an option later */
1535 add_v2_v2(pos, track->offset);
1536}
1537
1538/* --------------------------------------------------------------------
1539 * Plane track.
1540 */
1541
1543 ListBase *plane_tracks_base,
1545 int framenr)
1546{
1547 MovieTrackingPlaneTrack *plane_track;
1548 MovieTrackingPlaneMarker plane_marker;
1549 float tracks_min[2], tracks_max[2];
1550 int num_selected_tracks = 0;
1551
1552 (void)tracking; /* Ignored. */
1553
1554 /* Use bounding box of selected markers as an initial size of plane. */
1555 INIT_MINMAX2(tracks_min, tracks_max);
1557 if (TRACK_SELECTED(track)) {
1558 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
1559 float pattern_min[2], pattern_max[2];
1560 BKE_tracking_marker_pattern_minmax(marker, pattern_min, pattern_max);
1561 add_v2_v2(pattern_min, marker->pos);
1562 add_v2_v2(pattern_max, marker->pos);
1563 minmax_v2v2_v2(tracks_min, tracks_max, pattern_min);
1564 minmax_v2v2_v2(tracks_min, tracks_max, pattern_max);
1565 num_selected_tracks++;
1566 }
1567 }
1568
1569 if (num_selected_tracks < 4) {
1570 return nullptr;
1571 }
1572
1573 /* Allocate new plane track. */
1574 plane_track = MEM_callocN<MovieTrackingPlaneTrack>("new plane track");
1575
1576 /* Use some default name. */
1577 STRNCPY_UTF8(plane_track->name, DATA_("Plane Track"));
1578
1579 plane_track->image_opacity = 1.0f;
1580
1581 /* Use selected tracks from given list as a plane. */
1582 plane_track->point_tracks = MEM_calloc_arrayN<MovieTrackingTrack *>(num_selected_tracks,
1583 "new plane tracks array");
1584 int track_index = 0;
1586 if (TRACK_SELECTED(track)) {
1587 plane_track->point_tracks[track_index] = track;
1588 track_index++;
1589 }
1590 }
1591 plane_track->point_tracksnr = num_selected_tracks;
1592
1593 /* Setup new plane marker and add it to the track. */
1594 plane_marker.framenr = framenr;
1595 plane_marker.flag = 0;
1596
1597 copy_v2_v2(plane_marker.corners[0], tracks_min);
1598 copy_v2_v2(plane_marker.corners[2], tracks_max);
1599
1600 plane_marker.corners[1][0] = tracks_max[0];
1601 plane_marker.corners[1][1] = tracks_min[1];
1602 plane_marker.corners[3][0] = tracks_min[0];
1603 plane_marker.corners[3][1] = tracks_max[1];
1604
1605 BKE_tracking_plane_marker_insert(plane_track, &plane_marker);
1606
1607 /* Put new plane track to the list, ensure its name is unique. */
1608 BLI_addtail(plane_tracks_base, plane_track);
1609 BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
1610
1611 return plane_track;
1612}
1613
1615 MovieTrackingPlaneTrack *plane_track)
1616{
1617 BLI_uniquename(plane_tracks_base,
1618 plane_track,
1620 '.',
1622 sizeof(plane_track->name));
1623}
1624
1626{
1627 if (plane_track->markers) {
1628 MEM_freeN(plane_track->markers);
1629 }
1630
1631 MEM_freeN(plane_track->point_tracks);
1632}
1633
1635{
1636 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
1637 plane_track->flag &= ~SELECT;
1638 }
1639}
1640
1642 MovieTrackingTrack *track)
1643{
1644 for (int i = 0; i < plane_track->point_tracksnr; i++) {
1645 if (plane_track->point_tracks[i] == track) {
1646 return true;
1647 }
1648 }
1649 return false;
1650}
1651
1653 MovieTrackingTrack *track)
1654{
1655 if (plane_track->point_tracksnr <= 4) {
1656 return false;
1657 }
1658
1660 plane_track->point_tracksnr - 1, "new point tracks array");
1661
1662 for (int i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
1663 if (plane_track->point_tracks[i] != track) {
1664 new_point_tracks[track_index++] = plane_track->point_tracks[i];
1665 }
1666 }
1667
1668 MEM_freeN(plane_track->point_tracks);
1669 plane_track->point_tracks = new_point_tracks;
1670 plane_track->point_tracksnr--;
1671
1672 return true;
1673}
1674
1676 MovieTrackingTrack *track)
1677{
1678 MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
1679 LISTBASE_FOREACH_MUTABLE (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks)
1680 {
1681 if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
1682 if (!BKE_tracking_plane_track_remove_point_track(plane_track, track)) {
1683 /* Delete planes with less than 3 point tracks in it. */
1684 BKE_tracking_plane_track_free(plane_track);
1685 BLI_freelinkN(&tracking_object->plane_tracks, plane_track);
1686 }
1687 }
1688 }
1689}
1690
1692 MovieTrackingTrack *old_track,
1693 MovieTrackingTrack *new_track)
1694{
1695 for (int i = 0; i < plane_track->point_tracksnr; i++) {
1696 if (plane_track->point_tracks[i] == old_track) {
1697 plane_track->point_tracks[i] = new_track;
1698 break;
1699 }
1700 }
1701}
1702
1704 MovieTrackingTrack *old_track,
1705 MovieTrackingTrack *new_track)
1706{
1707 const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
1708 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
1709 if (BKE_tracking_plane_track_has_point_track(plane_track, old_track)) {
1710 BKE_tracking_plane_track_replace_point_track(plane_track, old_track, new_track);
1711 }
1712 }
1713}
1714
1715/* --------------------------------------------------------------------
1716 * Plane marker.
1717 */
1718
1720 MovieTrackingPlaneMarker *plane_marker)
1721{
1722 MovieTrackingPlaneMarker *old_plane_marker = nullptr;
1723
1724 if (plane_track->markersnr) {
1725 old_plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, plane_marker->framenr);
1726 }
1727
1728 if (old_plane_marker) {
1729 /* Simply replace settings in existing marker. */
1730 *old_plane_marker = *plane_marker;
1731
1732 return old_plane_marker;
1733 }
1734
1735 int a = plane_track->markersnr;
1736
1737 /* Find position in array where to add new marker. */
1738 /* TODO(sergey): we could use bisect to speed things up. */
1739 while (a--) {
1740 if (plane_track->markers[a].framenr < plane_marker->framenr) {
1741 break;
1742 }
1743 }
1744
1745 plane_track->markersnr++;
1746 plane_track->markers = static_cast<MovieTrackingPlaneMarker *>(MEM_reallocN(
1747 plane_track->markers, sizeof(MovieTrackingPlaneMarker) * plane_track->markersnr));
1748
1749 /* Shift array to "free" space for new marker. */
1750 memmove(plane_track->markers + a + 2,
1751 plane_track->markers + a + 1,
1752 (plane_track->markersnr - a - 2) * sizeof(MovieTrackingPlaneMarker));
1753
1754 /* Put new marker to an array. */
1755 plane_track->markers[a + 1] = *plane_marker;
1756
1757 return &plane_track->markers[a + 1];
1758}
1759
1761{
1762 int a = 0;
1763
1764 while (a < plane_track->markersnr) {
1765 if (plane_track->markers[a].framenr == framenr) {
1766 if (plane_track->markersnr > 1) {
1767 memmove(plane_track->markers + a,
1768 plane_track->markers + a + 1,
1769 (plane_track->markersnr - a - 1) * sizeof(MovieTrackingPlaneMarker));
1770 plane_track->markersnr--;
1771 plane_track->markers = static_cast<MovieTrackingPlaneMarker *>(MEM_reallocN(
1772 plane_track->markers, sizeof(MovieTrackingMarker) * plane_track->markersnr));
1773 }
1774 else {
1775 MEM_freeN(plane_track->markers);
1776 plane_track->markers = nullptr;
1777 plane_track->markersnr = 0;
1778 }
1779
1780 break;
1781 }
1782
1783 a++;
1784 }
1785}
1786
1787/* TODO(sergey): The next couple of functions are really quite the same as point marker version,
1788 * would be nice to de-duplicate them somehow..
1789 */
1790
1792 int framenr)
1793{
1794 int a = plane_track->markersnr - 1;
1795
1796 if (!plane_track->markersnr) {
1797 return nullptr;
1798 }
1799
1800 /* Approximate pre-first framenr marker with first marker. */
1801 if (framenr < plane_track->markers[0].framenr) {
1802 return &plane_track->markers[0];
1803 }
1804
1805 if (plane_track->last_marker < plane_track->markersnr) {
1806 a = plane_track->last_marker;
1807 }
1808
1809 if (plane_track->markers[a].framenr <= framenr) {
1810 while (a < plane_track->markersnr && plane_track->markers[a].framenr <= framenr) {
1811 if (plane_track->markers[a].framenr == framenr) {
1812 plane_track->last_marker = a;
1813
1814 return &plane_track->markers[a];
1815 }
1816 a++;
1817 }
1818
1819 /* If there's no marker for exact position, use nearest marker from left side. */
1820 return &plane_track->markers[a - 1];
1821 }
1822
1823 while (a >= 0 && plane_track->markers[a].framenr >= framenr) {
1824 if (plane_track->markers[a].framenr == framenr) {
1825 plane_track->last_marker = a;
1826
1827 return &plane_track->markers[a];
1828 }
1829
1830 a--;
1831 }
1832
1833 /* If there's no marker for exact position, use nearest marker from left side. */
1834 return &plane_track->markers[a];
1835}
1836
1838 int framenr)
1839{
1840 MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
1841
1842 if (plane_marker->framenr != framenr) {
1843 return nullptr;
1844 }
1845
1846 return plane_marker;
1847}
1848
1850 int framenr)
1851{
1852 MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
1853
1854 if (plane_marker->framenr != framenr) {
1855 MovieTrackingPlaneMarker plane_marker_new;
1856
1857 plane_marker_new = *plane_marker;
1858 plane_marker_new.framenr = framenr;
1859
1860 plane_marker = BKE_tracking_plane_marker_insert(plane_track, &plane_marker_new);
1861 }
1862
1863 return plane_marker;
1864}
1865
1867 float framenr,
1868 float corners[4][2])
1869{
1870 MovieTrackingPlaneMarker *marker = BKE_tracking_plane_marker_get(plane_track, int(framenr));
1871 MovieTrackingPlaneMarker *marker_last = plane_track->markers + (plane_track->markersnr - 1);
1872 if (marker != marker_last) {
1873 MovieTrackingPlaneMarker *marker_next = marker + 1;
1874 if (marker_next->framenr == marker->framenr + 1) {
1875 float fac = (framenr - int(framenr)) / (marker_next->framenr - marker->framenr);
1876 for (int i = 0; i < 4; i++) {
1877 interp_v2_v2v2(corners[i], marker->corners[i], marker_next->corners[i], fac);
1878 }
1879 }
1880 else {
1881 for (int i = 0; i < 4; i++) {
1882 copy_v2_v2(corners[i], marker->corners[i]);
1883 }
1884 }
1885 }
1886 else {
1887 for (int i = 0; i < 4; i++) {
1888 copy_v2_v2(corners[i], marker->corners[i]);
1889 }
1890 }
1891}
1892
1893/* --------------------------------------------------------------------
1894 * Object.
1895 */
1896
1898{
1899 MovieTrackingObject *tracking_object = MEM_callocN<MovieTrackingObject>("tracking object");
1900
1901 if (tracking->tot_object == 0) {
1902 /* first object is always camera */
1903 STRNCPY_UTF8(tracking_object->name, "Camera");
1904
1905 tracking_object->flag |= TRACKING_OBJECT_CAMERA;
1906 }
1907 else {
1908 STRNCPY_UTF8(tracking_object->name, name);
1909 }
1910
1911 BLI_addtail(&tracking->objects, tracking_object);
1912
1913 tracking->tot_object++;
1914 tracking->objectnr = BLI_listbase_count(&tracking->objects) - 1;
1915
1916 tracking_object->scale = 1.0f;
1917 tracking_object->keyframe1 = 1;
1918 tracking_object->keyframe2 = 30;
1919
1920 BKE_tracking_object_unique_name(tracking, tracking_object);
1922
1923 return tracking_object;
1924}
1925
1927{
1928 const int index = BLI_findindex(&tracking->objects, tracking_object);
1929
1930 if (index == -1) {
1931 return false;
1932 }
1933
1934 if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1935 /* object used for camera solving can't be deleted */
1936 return false;
1937 }
1938
1939 tracking_object_free(tracking_object);
1940 BLI_freelinkN(&tracking->objects, tracking_object);
1941
1942 tracking->tot_object--;
1943
1944 if (index != 0) {
1945 tracking->objectnr = index - 1;
1946 }
1947 else {
1948 tracking->objectnr = 0;
1949 }
1950
1952
1953 return true;
1954}
1955
1957{
1958 BLI_uniquename(&tracking->objects,
1959 tracking_object,
1960 DATA_("Object"),
1961 '.',
1963 sizeof(tracking_object->name));
1964}
1965
1967{
1968 LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
1969 if (STREQ(tracking_object->name, name)) {
1970 return tracking_object;
1971 }
1972 }
1973
1974 return nullptr;
1975}
1976
1978{
1979 return static_cast<MovieTrackingObject *>(BLI_findlink(&tracking->objects, tracking->objectnr));
1980}
1981
1983{
1984 LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
1985 if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
1986 return tracking_object;
1987 }
1988 }
1989
1990 return nullptr;
1991}
1992
1994 const char *name)
1995{
1996 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
1997 if (STREQ(track->name, name)) {
1998 return track;
1999 }
2000 }
2001
2002 return nullptr;
2003}
2004
2006 MovieTrackingObject *tracking_object, const char *name)
2007{
2008 LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
2009 if (STREQ(plane_track->name, name)) {
2010 return plane_track;
2011 }
2012 }
2013
2014 return nullptr;
2015}
2016
2017/* --------------------------------------------------------------------
2018 * Camera.
2019 */
2020
2022 int framenr,
2023 bool nearest)
2024{
2025 MovieReconstructedCamera *cameras = reconstruction->cameras;
2026 int a = 0, d = 1;
2027
2028 if (!reconstruction->camnr) {
2029 return -1;
2030 }
2031
2032 if (framenr < cameras[0].framenr) {
2033 if (nearest) {
2034 return 0;
2035 }
2036
2037 return -1;
2038 }
2039
2040 if (framenr > cameras[reconstruction->camnr - 1].framenr) {
2041 if (nearest) {
2042 return reconstruction->camnr - 1;
2043 }
2044
2045 return -1;
2046 }
2047
2048 if (reconstruction->last_camera < reconstruction->camnr) {
2049 a = reconstruction->last_camera;
2050 }
2051
2052 if (cameras[a].framenr >= framenr) {
2053 d = -1;
2054 }
2055
2056 while (a >= 0 && a < reconstruction->camnr) {
2057 int cfra = cameras[a].framenr;
2058
2059 /* check if needed framenr was "skipped" -- no data for requested frame */
2060
2061 if (d > 0 && cfra > framenr) {
2062 /* interpolate with previous position */
2063 if (nearest) {
2064 return a - 1;
2065 }
2066
2067 break;
2068 }
2069
2070 if (d < 0 && cfra < framenr) {
2071 /* interpolate with next position */
2072 if (nearest) {
2073 return a;
2074 }
2075
2076 break;
2077 }
2078
2079 if (cfra == framenr) {
2080 reconstruction->last_camera = a;
2081
2082 return a;
2083 }
2084
2085 a += d;
2086 }
2087
2088 return -1;
2089}
2090
2091static void reconstructed_camera_scale_set(const MovieTrackingObject *tracking_object,
2092 float mat[4][4])
2093{
2094 if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
2095 float smat[4][4];
2096
2097 scale_m4_fl(smat, 1.0f / tracking_object->scale);
2098 mul_m4_m4m4(mat, mat, smat);
2099 }
2100}
2101
2103 MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
2104{
2105 float principal_px[2];
2107 tracking->camera.principal_point, winx, winy, principal_px);
2108
2109 /* Indeed in both of cases it should be winx -
2110 * it's just how camera shift works for blender's camera. */
2111 *shiftx = (0.5f * winx - principal_px[0]) / winx;
2112 *shifty = (0.5f * winy - principal_px[1]) / winx;
2113}
2114
2116 MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
2117{
2118 float focal = tracking->camera.focal;
2119
2120 camera->sensor_x = tracking->camera.sensor_width;
2122 camera->lens = focal * camera->sensor_x / width;
2123
2124 scene->r.xsch = width;
2125 scene->r.ysch = height;
2126
2127 scene->r.xasp = tracking->camera.pixel_aspect;
2128 scene->r.yasp = 1.0f;
2129
2130 BKE_tracking_camera_shift_get(tracking, width, height, &camera->shiftx, &camera->shifty);
2131}
2132
2134 MovieTracking * /*tracking*/, MovieTrackingObject *tracking_object, int framenr)
2135{
2136 MovieTrackingReconstruction *reconstruction = &tracking_object->reconstruction;
2137 int a = reconstructed_camera_index_get(reconstruction, framenr, false);
2138
2139 if (a == -1) {
2140 return nullptr;
2141 }
2142
2143 return &reconstruction->cameras[a];
2144}
2145
2147 MovieTrackingObject *tracking_object,
2148 float framenr,
2149 float mat[4][4])
2150{
2151 MovieTrackingReconstruction *reconstruction = &tracking_object->reconstruction;
2152 MovieReconstructedCamera *cameras = reconstruction->cameras;
2153
2154 int a = reconstructed_camera_index_get(reconstruction, int(framenr), true);
2155
2156 if (a == -1) {
2157 unit_m4(mat);
2158 return;
2159 }
2160
2161 if ((a < reconstruction->camnr - 1) && (cameras[a].framenr != framenr)) {
2162 float t = (framenr - cameras[a].framenr) / (cameras[a + 1].framenr - cameras[a].framenr);
2163 blend_m4_m4m4(mat, cameras[a].mat, cameras[a + 1].mat, t);
2164 }
2165 else {
2166 copy_m4_m4(mat, cameras[a].mat);
2167 }
2168
2169 reconstructed_camera_scale_set(tracking_object, mat);
2170}
2171
2173 float r_principal_point_pixel[2])
2174{
2175 const MovieTrackingCamera *camera = &clip->tracking.camera;
2176
2177 int frame_width, frame_height;
2179 BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
2180
2182 camera->principal_point, frame_width, frame_height, r_principal_point_pixel);
2183}
2184
2186 const float principal_point_pixel[2])
2187{
2188 MovieTrackingCamera *camera = &clip->tracking.camera;
2189
2190 int frame_width, frame_height;
2192 BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height);
2193
2195 principal_point_pixel, frame_width, frame_height, camera->principal_point);
2196}
2197
2199 const MovieTrackingCamera *b)
2200{
2201 if (a->pixel_aspect != b->pixel_aspect || a->focal != b->focal ||
2202 !equals_v2v2(a->principal_point, b->principal_point))
2203 {
2204 return false;
2205 }
2206
2207 if (a->distortion_model != b->distortion_model) {
2208 return false;
2209 }
2210
2211 switch (a->distortion_model) {
2213 return a->k1 == b->k1 && a->k2 == b->k2 && a->k3 == b->k3;
2215 return a->division_k1 == b->division_k1 && a->division_k2 == b->division_k2;
2217 return a->nuke_k1 == b->nuke_k1 && a->nuke_k2 == b->nuke_k2;
2219 return a->brown_k1 == b->brown_k1 && a->brown_k2 == b->brown_k2 &&
2220 a->brown_k3 == b->brown_k3 && a->brown_k4 == b->brown_k4 &&
2221 a->brown_p1 == b->brown_p1 && a->brown_p2 == b->brown_p2;
2222 }
2223
2225 return false;
2226}
2227
2229{
2230 using namespace blender;
2231 switch (camera->distortion_model) {
2233 return get_default_hash(camera->distortion_model,
2234 float2(camera->pixel_aspect, camera->focal),
2235 float2(camera->principal_point),
2236 float3(camera->k1, camera->k2, camera->k3));
2238 return get_default_hash(camera->distortion_model,
2239 float2(camera->pixel_aspect, camera->focal),
2240 float2(camera->principal_point),
2241 float2(camera->division_k1, camera->division_k2));
2243 return get_default_hash(camera->distortion_model,
2244 float2(camera->pixel_aspect, camera->focal),
2245 float2(camera->principal_point),
2246 float2(camera->nuke_k1, camera->nuke_k2));
2248 return get_default_hash(
2249 float2(camera->pixel_aspect, camera->focal),
2250 float2(camera->principal_point),
2251 float4(camera->brown_k1, camera->brown_k2, camera->brown_k3, camera->brown_k4),
2252 float2(camera->brown_p1, camera->brown_p2));
2253 }
2254
2256 return 0;
2257}
2258/* --------------------------------------------------------------------
2259 * (Un)distortion.
2260 */
2261
2263 int calibration_width,
2264 int calibration_height)
2265{
2266 MovieDistortion *distortion;
2267 libmv_CameraIntrinsicsOptions camera_intrinsics_options;
2268
2270 tracking, calibration_width, calibration_height, &camera_intrinsics_options);
2271
2272 distortion = MEM_callocN<MovieDistortion>("BKE_tracking_distortion_create");
2273 distortion->intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options);
2274
2275 const MovieTrackingCamera *camera = &tracking->camera;
2277 calibration_width,
2278 calibration_height,
2279 distortion->principal_px);
2280 distortion->pixel_aspect = camera->pixel_aspect;
2281 distortion->focal = camera->focal;
2282
2283 return distortion;
2284}
2285
2287 MovieTracking *tracking,
2288 int calibration_width,
2289 int calibration_height)
2290{
2291 libmv_CameraIntrinsicsOptions camera_intrinsics_options;
2292
2294 tracking, calibration_width, calibration_height, &camera_intrinsics_options);
2295
2296 const MovieTrackingCamera *camera = &tracking->camera;
2298 calibration_width,
2299 calibration_height,
2300 distortion->principal_px);
2301 distortion->pixel_aspect = camera->pixel_aspect;
2302 distortion->focal = camera->focal;
2303
2304 libmv_cameraIntrinsicsUpdate(&camera_intrinsics_options, distortion->intrinsics);
2305}
2306
2308{
2309 MovieDistortion *new_distortion;
2310
2311 new_distortion = MEM_callocN<MovieDistortion>("BKE_tracking_distortion_create");
2312 *new_distortion = *distortion;
2313 new_distortion->intrinsics = libmv_cameraIntrinsicsCopy(distortion->intrinsics);
2314
2315 return new_distortion;
2316}
2317
2319 MovieTracking *tracking,
2320 ImBuf *ibuf,
2321 int calibration_width,
2322 int calibration_height,
2323 float overscan,
2324 bool undistort)
2325{
2326 ImBuf *resibuf;
2327
2328 BKE_tracking_distortion_update(distortion, tracking, calibration_width, calibration_height);
2329
2330 resibuf = IMB_dupImBuf(ibuf);
2331
2332 if (ibuf->float_buffer.data) {
2333 if (undistort) {
2335 ibuf->float_buffer.data,
2336 ibuf->x,
2337 ibuf->y,
2338 overscan,
2339 ibuf->channels,
2340 resibuf->float_buffer.data);
2341 }
2342 else {
2344 ibuf->float_buffer.data,
2345 ibuf->x,
2346 ibuf->y,
2347 overscan,
2348 ibuf->channels,
2349 resibuf->float_buffer.data);
2350 }
2351
2353 }
2354 else {
2355 if (undistort) {
2357 ibuf->byte_buffer.data,
2358 ibuf->x,
2359 ibuf->y,
2360 overscan,
2361 ibuf->channels,
2362 resibuf->byte_buffer.data);
2363 }
2364 else {
2366 ibuf->byte_buffer.data,
2367 ibuf->x,
2368 ibuf->y,
2369 overscan,
2370 ibuf->channels,
2371 resibuf->byte_buffer.data);
2372 }
2373 }
2374
2375 return resibuf;
2376}
2377
2379 const float co[2],
2380 float r_co[2])
2381{
2382 const float aspy = 1.0f / distortion->pixel_aspect;
2383
2384 /* Normalize coords. */
2385 float inv_focal = 1.0f / distortion->focal;
2386 double x = (co[0] - distortion->principal_px[0]) * inv_focal,
2387 y = (co[1] - distortion->principal_px[1] * aspy) * inv_focal;
2388
2389 libmv_cameraIntrinsicsApply(distortion->intrinsics, x, y, &x, &y);
2390
2391 /* Result is in image coords already. */
2392 r_co[0] = x;
2393 r_co[1] = y;
2394}
2395
2397 const float co[2],
2398 float r_co[2])
2399{
2400 double x = co[0], y = co[1];
2401 libmv_cameraIntrinsicsInvert(distortion->intrinsics, x, y, &x, &y);
2402
2403 const float aspy = 1.0f / distortion->pixel_aspect;
2404 r_co[0] = float(x) * distortion->focal + distortion->principal_px[0];
2405 r_co[1] = float(y) * distortion->focal + distortion->principal_px[1] * aspy;
2406}
2407
2409{
2411
2412 MEM_freeN(distortion);
2413}
2414
2416 MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
2417{
2418 const MovieTrackingCamera *camera = &tracking->camera;
2419 const float aspy = 1.0f / tracking->camera.pixel_aspect;
2420
2421 libmv_CameraIntrinsicsOptions camera_intrinsics_options;
2423 tracking, image_width, image_height, &camera_intrinsics_options);
2424 libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options);
2425
2426 float principal_px[2];
2428 tracking->camera.principal_point, image_width, image_height, principal_px);
2429
2430 /* Normalize coordinates. */
2431 double x = (co[0] - principal_px[0]) / camera->focal,
2432 y = (co[1] - principal_px[1] * aspy) / camera->focal;
2433
2434 libmv_cameraIntrinsicsApply(intrinsics, x, y, &x, &y);
2436
2437 /* Result is in image coords already. */
2438 r_co[0] = x;
2439 r_co[1] = y;
2440}
2441
2443 MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
2444{
2445 const MovieTrackingCamera *camera = &tracking->camera;
2446 const float aspy = 1.0f / tracking->camera.pixel_aspect;
2447
2448 libmv_CameraIntrinsicsOptions camera_intrinsics_options;
2450 tracking, image_width, image_height, &camera_intrinsics_options);
2451 libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options);
2452
2453 double x = co[0], y = co[1];
2454 libmv_cameraIntrinsicsInvert(intrinsics, x, y, &x, &y);
2456
2457 float principal_px[2];
2459 tracking->camera.principal_point, image_width, image_height, principal_px);
2460
2461 r_co[0] = float(x) * camera->focal + principal_px[0];
2462 r_co[1] = float(y) * camera->focal + principal_px[1] * aspy;
2463}
2464
2466 ImBuf *ibuf,
2467 int calibration_width,
2468 int calibration_height,
2469 float overscan)
2470{
2471 MovieTrackingCamera *camera = &tracking->camera;
2472
2473 if (camera->intrinsics == nullptr) {
2475 tracking, calibration_width, calibration_height);
2476 }
2477
2478 return BKE_tracking_distortion_exec(static_cast<MovieDistortion *>(camera->intrinsics),
2479 tracking,
2480 ibuf,
2481 calibration_width,
2482 calibration_height,
2483 overscan,
2484 true);
2485}
2486
2488 ImBuf *ibuf,
2489 int calibration_width,
2490 int calibration_height,
2491 float overscan)
2492{
2493 MovieTrackingCamera *camera = &tracking->camera;
2494
2495 if (camera->intrinsics == nullptr) {
2497 tracking, calibration_width, calibration_height);
2498 }
2499
2500 return BKE_tracking_distortion_exec(static_cast<MovieDistortion *>(camera->intrinsics),
2501 tracking,
2502 ibuf,
2503 calibration_width,
2504 calibration_height,
2505 overscan,
2506 false);
2507}
2508
2509/* Reduces the given function in parallel over the given range, the reduction function should have
2510 * the given identity value. The given function gets as arguments the index of the element of the
2511 * range as well as a reference to the value where the result should be accumulated, while the
2512 * reduction function gets a reference to two values and returns their reduction. */
2513template<typename Value, typename Function, typename Reduction>
2514static Value parallel_reduce(const int range,
2515 const Value &identity,
2516 const Function &function,
2517 const Reduction &reduction)
2518{
2519 using namespace blender;
2521 IndexRange(range),
2522 32,
2523 identity,
2524 [&](const IndexRange sub_range, const Value &initial_value) {
2525 Value result = initial_value;
2526 for (const int64_t i : sub_range) {
2527 function(i, result);
2528 }
2529 return result;
2530 },
2531 reduction);
2532}
2533
2535 const int size[2],
2536 const int calibration_size[2],
2537 const bool undistort,
2538 int *r_right,
2539 int *r_left,
2540 int *r_bottom,
2541 int *r_top)
2542{
2543 using namespace blender;
2544
2545 auto distortion_function = [&](const float2 &position) {
2546 /* The tracking distortion functions expect the coordinates to be in the space of the image
2547 * where the tracking camera was calibrated. So we first remap the coordinates into that space,
2548 * apply the distortion, then remap back to the original coordinates space. This is done by
2549 * dividing by the size then multiplying by the calibration size, making sure to add 0.5 to
2550 * evaluate at the center of pixels. */
2551 float2 coordinates = ((position + 0.5f) / float2(size)) * float2(calibration_size);
2552 /* Notice that the condition is inverted, that's because when we are undistorting, we compute
2553 * the boundaries by distorting and vice versa. */
2554 float2 distorted_coordinates;
2555 if (undistort) {
2556 BKE_tracking_distortion_distort_v2(distortion, coordinates, distorted_coordinates);
2557 }
2558 else {
2559 BKE_tracking_distortion_undistort_v2(distortion, coordinates, distorted_coordinates);
2560 }
2561
2562 /* We remap the coordinates back into the original size by dividing by the calibration size and
2563 * multiplying by the size. */
2564 return (distorted_coordinates / float2(calibration_size)) * float2(size);
2565 };
2566
2567 /* Maximum distorted x location along the right edge of the image. */
2568 const float maximum_x = parallel_reduce(
2569 size[1],
2570 std::numeric_limits<float>::lowest(),
2571 [&](const int i, float &accumulated_value) {
2572 accumulated_value = math::max(accumulated_value,
2573 distortion_function(float2(size[0], i)).x);
2574 },
2575 [&](const float &a, const float &b) { return math::max(a, b); });
2576
2577 /* Minimum distorted x location along the left edge of the image. */
2578 const float minimum_x = parallel_reduce(
2579 size[1],
2580 std::numeric_limits<float>::max(),
2581 [&](const int i, float &accumulated_value) {
2582 accumulated_value = math::min(accumulated_value, distortion_function(float2(0.0f, i)).x);
2583 },
2584 [&](const float &a, const float &b) { return math::min(a, b); });
2585
2586 /* Minimum distorted y location along the bottom edge of the image. */
2587 const float minimum_y = parallel_reduce(
2588 size[0],
2589 std::numeric_limits<float>::max(),
2590 [&](const int i, float &accumulated_value) {
2591 accumulated_value = math::min(accumulated_value, distortion_function(float2(i, 0.0f)).y);
2592 },
2593 [&](const float &a, const float &b) { return math::min(a, b); });
2594
2595 /* Maximum distorted y location along the top edge of the image. */
2596 const float maximum_y = parallel_reduce(
2597 size[0],
2598 std::numeric_limits<float>::lowest(),
2599 [&](const int i, float &accumulated_value) {
2600 accumulated_value = math::max(accumulated_value,
2601 distortion_function(float2(i, size[1])).y);
2602 },
2603 [&](const float &a, const float &b) { return math::max(a, b); });
2604
2605 /* Compute the deltas from the image edges to the maximum/minimum distorted location along the
2606 * direction of that edge. */
2607 const float right_delta = maximum_x - size[0];
2608 const float left_delta = 0.0f - minimum_x;
2609 const float bottom_delta = 0.0f - minimum_y;
2610 const float top_delta = maximum_y - size[1];
2611
2612 /* Round the deltas away from zero. */
2613 *r_right = int(right_delta < 0.0f ? math::floor(right_delta) : math::ceil(right_delta));
2614 *r_left = int(left_delta < 0.0f ? math::floor(left_delta) : math::ceil(left_delta));
2615 *r_bottom = int(bottom_delta < 0.0f ? math::floor(bottom_delta) : math::ceil(bottom_delta));
2616 *r_top = int(top_delta < 0.0f ? math::floor(top_delta) : math::ceil(top_delta));
2617}
2618
2619/* --------------------------------------------------------------------
2620 * Image sampling.
2621 */
2622
2624 const MovieTrackingTrack *track,
2625 const bool grayscale)
2626{
2628 track->flag & TRACK_DISABLE_RED,
2629 track->flag & TRACK_DISABLE_GREEN,
2630 track->flag & TRACK_DISABLE_BLUE,
2631 grayscale);
2632}
2633
2634ImBuf *BKE_tracking_sample_pattern(const int frame_width,
2635 const int frame_height,
2636 const ImBuf *search_ibuf,
2637 const MovieTrackingTrack *track,
2638 const MovieTrackingMarker *marker,
2639 const bool from_anchor,
2640 const bool use_mask,
2641 const int num_samples_x,
2642 const int num_samples_y,
2643 float pos[2])
2644{
2645 ImBuf *pattern_ibuf;
2646 double src_pixel_x[5], src_pixel_y[5];
2647 double warped_position_x, warped_position_y;
2648 float *mask = nullptr;
2649
2650 if (num_samples_x <= 0 || num_samples_y <= 0) {
2651 return nullptr;
2652 }
2653
2654 pattern_ibuf = IMB_allocImBuf(num_samples_x,
2655 num_samples_y,
2656 32,
2657 search_ibuf->float_buffer.data ? IB_float_data : IB_byte_data);
2658
2660 frame_width, frame_height, marker, src_pixel_x, src_pixel_y);
2661
2662 /* from_anchor means search buffer was obtained for an anchored position,
2663 * which means applying track offset rounded to pixel space (we could not
2664 * store search buffer with sub-pixel precision)
2665 *
2666 * in this case we need to alter coordinates a bit, to compensate rounded
2667 * fractional part of offset
2668 */
2669 if (from_anchor) {
2670 for (int a = 0; a < 5; a++) {
2671 src_pixel_x[a] += double((track->offset[0] * frame_width) -
2672 int(track->offset[0] * frame_width));
2673 src_pixel_y[a] += double((track->offset[1] * frame_height) -
2674 int(track->offset[1] * frame_height));
2675
2676 /* when offset is negative, rounding happens in opposite direction */
2677 if (track->offset[0] < 0.0f) {
2678 src_pixel_x[a] += 1.0;
2679 }
2680 if (track->offset[1] < 0.0f) {
2681 src_pixel_y[a] += 1.0;
2682 }
2683 }
2684 }
2685
2686 if (use_mask) {
2687 mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
2688 }
2689
2690 if (search_ibuf->float_buffer.data) {
2692 search_ibuf->x,
2693 search_ibuf->y,
2694 4,
2695 src_pixel_x,
2696 src_pixel_y,
2697 num_samples_x,
2698 num_samples_y,
2699 mask,
2700 pattern_ibuf->float_buffer.data,
2701 &warped_position_x,
2702 &warped_position_y);
2703 }
2704 else {
2706 search_ibuf->x,
2707 search_ibuf->y,
2708 4,
2709 src_pixel_x,
2710 src_pixel_y,
2711 num_samples_x,
2712 num_samples_y,
2713 mask,
2714 pattern_ibuf->byte_buffer.data,
2715 &warped_position_x,
2716 &warped_position_y);
2717 }
2718
2719 if (pos) {
2720 pos[0] = warped_position_x;
2721 pos[1] = warped_position_y;
2722 }
2723
2724 if (mask) {
2725 MEM_freeN(mask);
2726 }
2727
2728 return pattern_ibuf;
2729}
2730
2732 const MovieTrackingTrack *track,
2733 const MovieTrackingMarker *marker,
2734 const bool anchored,
2735 const bool disable_channels)
2736{
2737 ImBuf *pattern_ibuf, *search_ibuf;
2738 float pat_min[2], pat_max[2];
2739 int num_samples_x, num_samples_y;
2740
2741 BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
2742
2743 num_samples_x = (pat_max[0] - pat_min[0]) * ibuf->x;
2744 num_samples_y = (pat_max[1] - pat_min[1]) * ibuf->y;
2745
2746 search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels);
2747
2748 if (search_ibuf) {
2749 pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x,
2750 ibuf->y,
2751 search_ibuf,
2752 track,
2753 marker,
2754 anchored,
2755 false,
2756 num_samples_x,
2757 num_samples_y,
2758 nullptr);
2759
2760 IMB_freeImBuf(search_ibuf);
2761 }
2762 else {
2763 pattern_ibuf = nullptr;
2764 }
2765
2766 return pattern_ibuf;
2767}
2768
2770 const MovieTrackingTrack *track,
2771 const MovieTrackingMarker *marker,
2772 const bool anchored,
2773 const bool disable_channels)
2774{
2775 ImBuf *searchibuf;
2776 int x, y, w, h;
2777 float search_origin[2];
2778
2779 tracking_get_search_origin_frame_pixel(ibuf->x, ibuf->y, marker, search_origin);
2780
2781 x = search_origin[0];
2782 y = search_origin[1];
2783
2784 if (anchored) {
2785 x += track->offset[0] * ibuf->x;
2786 y += track->offset[1] * ibuf->y;
2787 }
2788
2789 w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x;
2790 h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y;
2791
2792 if (w <= 0 || h <= 0) {
2793 return nullptr;
2794 }
2795
2796 searchibuf = IMB_allocImBuf(w, h, 32, ibuf->float_buffer.data ? IB_float_data : IB_byte_data);
2797
2798 IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h);
2799
2800 if (disable_channels) {
2801 if ((track->flag & TRACK_PREVIEW_GRAYSCALE) || (track->flag & TRACK_DISABLE_RED) ||
2802 (track->flag & TRACK_DISABLE_GREEN) || (track->flag & TRACK_DISABLE_BLUE))
2803 {
2804 disable_imbuf_channels(searchibuf, track, true);
2805 }
2806 }
2807
2808 return searchibuf;
2809}
2810
2812 const float b[2],
2813 const int frame_width,
2814 const int frame_height)
2815{
2816 const float a_px[2] = {a[0] * frame_width, a[1] * frame_height};
2817 const float b_px[2] = {b[0] * frame_width, b[1] * frame_height};
2818
2819 return ceilf(len_v2v2(a_px, b_px));
2820}
2821
2823 const MovieTrackingPlaneMarker *plane_marker)
2824{
2825 /* Alias for corners, allowing shorter access to coordinates. */
2826 const float (*corners)[2] = plane_marker->corners;
2827
2828 /* Dimensions of the frame image in pixels. */
2829 const int frame_width = frame_ibuf->x;
2830 const int frame_height = frame_ibuf->y;
2831
2832 /* Lengths of left and right edges of the plane marker, in pixels. */
2833 const int left_side_len_px = plane_marker_size_len_in_pixels(
2834 corners[0], corners[3], frame_width, frame_height);
2835 const int right_side_len_px = plane_marker_size_len_in_pixels(
2836 corners[1], corners[2], frame_width, frame_height);
2837
2838 /* Lengths of top and bottom edges of the plane marker, in pixels. */
2839 const int top_side_len_px = plane_marker_size_len_in_pixels(
2840 corners[3], corners[2], frame_width, frame_height);
2841 const int bottom_side_len_px = plane_marker_size_len_in_pixels(
2842 corners[0], corners[1], frame_width, frame_height);
2843
2844 /* Choose the number of samples as a maximum of the corresponding sides in pixels. */
2845 const int num_samples_x = max_ii(top_side_len_px, bottom_side_len_px);
2846 const int num_samples_y = max_ii(left_side_len_px, right_side_len_px);
2847
2848 /* Create new result image with the same type of content as the original. */
2849 ImBuf *plane_ibuf = IMB_allocImBuf(num_samples_x,
2850 num_samples_y,
2851 32,
2853
2854 /* Calculate corner coordinates in pixel space, as separate X/Y arrays. */
2855 const double src_pixel_x[4] = {corners[0][0] * frame_width,
2856 corners[1][0] * frame_width,
2857 corners[2][0] * frame_width,
2858 corners[3][0] * frame_width};
2859 const double src_pixel_y[4] = {corners[0][1] * frame_height,
2860 corners[1][1] * frame_height,
2861 corners[2][1] * frame_height,
2862 corners[3][1] * frame_height};
2863
2864 /* Warped Position is unused but is expected to be provided by the API. */
2865 double warped_position_x, warped_position_y;
2866
2867 /* Actual sampling. */
2868 if (frame_ibuf->float_buffer.data != nullptr) {
2870 frame_ibuf->x,
2871 frame_ibuf->y,
2872 4,
2873 src_pixel_x,
2874 src_pixel_y,
2875 num_samples_x,
2876 num_samples_y,
2877 nullptr,
2878 plane_ibuf->float_buffer.data,
2879 &warped_position_x,
2880 &warped_position_y);
2881 }
2882 else {
2884 frame_ibuf->x,
2885 frame_ibuf->y,
2886 4,
2887 src_pixel_x,
2888 src_pixel_y,
2889 num_samples_x,
2890 num_samples_y,
2891 nullptr,
2892 plane_ibuf->byte_buffer.data,
2893 &warped_position_x,
2894 &warped_position_y);
2895 }
2896
2897 plane_ibuf->byte_buffer.colorspace = frame_ibuf->byte_buffer.colorspace;
2898 plane_ibuf->float_buffer.colorspace = frame_ibuf->float_buffer.colorspace;
2899
2900 return plane_ibuf;
2901}
2902
2904 ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale)
2905{
2906 if (!disable_red && !disable_green && !disable_blue && !grayscale) {
2907 return;
2908 }
2909
2910 /* if only some components are selected, it's important to rescale the result
2911 * appropriately so that e.g. if only blue is selected, it's not zeroed out.
2912 */
2913 float scale = (disable_red ? 0.0f : 0.2126f) + (disable_green ? 0.0f : 0.7152f) +
2914 (disable_blue ? 0.0f : 0.0722f);
2915
2916 for (int y = 0; y < ibuf->y; y++) {
2917 for (int x = 0; x < ibuf->x; x++) {
2918 int pixel = ibuf->x * y + x;
2919
2920 if (ibuf->float_buffer.data) {
2921 float *rrgbf = ibuf->float_buffer.data + pixel * 4;
2922 float r = disable_red ? 0.0f : rrgbf[0];
2923 float g = disable_green ? 0.0f : rrgbf[1];
2924 float b = disable_blue ? 0.0f : rrgbf[2];
2925
2926 if (grayscale) {
2927 float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
2928
2929 rrgbf[0] = rrgbf[1] = rrgbf[2] = gray;
2930 }
2931 else {
2932 rrgbf[0] = r;
2933 rrgbf[1] = g;
2934 rrgbf[2] = b;
2935 }
2936 }
2937 else {
2938 uchar *rrgb = ibuf->byte_buffer.data + pixel * 4;
2939 uchar r = disable_red ? 0 : rrgb[0];
2940 uchar g = disable_green ? 0 : rrgb[1];
2941 uchar b = disable_blue ? 0 : rrgb[2];
2942
2943 if (grayscale) {
2944 float gray = (0.2126f * r + 0.7152f * g + 0.0722f * b) / scale;
2945
2946 rrgb[0] = rrgb[1] = rrgb[2] = gray;
2947 }
2948 else {
2949 rrgb[0] = r;
2950 rrgb[1] = g;
2951 rrgb[2] = b;
2952 }
2953 }
2954 }
2955 }
2956
2957 if (ibuf->float_buffer.data) {
2958 ibuf->userflags |= IB_RECT_INVALID;
2959 }
2960}
2961
2962/* --------------------------------------------------------------------
2963 * Dope-sheet functions.
2964 */
2965
2966/* ** Channels sort comparators ** */
2967
2968static int channels_alpha_sort(const void *a, const void *b)
2969{
2970 const MovieTrackingDopesheetChannel *channel_a =
2971 static_cast<const MovieTrackingDopesheetChannel *>(a);
2972 const MovieTrackingDopesheetChannel *channel_b =
2973 static_cast<const MovieTrackingDopesheetChannel *>(b);
2974
2975 if (BLI_strcasecmp(channel_a->track->name, channel_b->track->name) > 0) {
2976 return 1;
2977 }
2978
2979 return 0;
2980}
2981
2982static int channels_total_track_sort(const void *a, const void *b)
2983{
2984 const MovieTrackingDopesheetChannel *channel_a =
2985 static_cast<const MovieTrackingDopesheetChannel *>(a);
2986 const MovieTrackingDopesheetChannel *channel_b =
2987 static_cast<const MovieTrackingDopesheetChannel *>(b);
2988
2989 if (channel_a->total_frames > channel_b->total_frames) {
2990 return 1;
2991 }
2992
2993 return 0;
2994}
2995
2996static int channels_longest_segment_sort(const void *a, const void *b)
2997{
2998 const MovieTrackingDopesheetChannel *channel_a =
2999 static_cast<const MovieTrackingDopesheetChannel *>(a);
3000 const MovieTrackingDopesheetChannel *channel_b =
3001 static_cast<const MovieTrackingDopesheetChannel *>(b);
3002
3003 if (channel_a->max_segment > channel_b->max_segment) {
3004 return 1;
3005 }
3006
3007 return 0;
3008}
3009
3010static int channels_average_error_sort(const void *a, const void *b)
3011{
3012 const MovieTrackingDopesheetChannel *channel_a =
3013 static_cast<const MovieTrackingDopesheetChannel *>(a);
3014 const MovieTrackingDopesheetChannel *channel_b =
3015 static_cast<const MovieTrackingDopesheetChannel *>(b);
3016
3017 if (channel_a->track->error > channel_b->track->error) {
3018 return 1;
3019 }
3020
3021 if (channel_a->track->error == channel_b->track->error) {
3022 return channels_alpha_sort(a, b);
3023 }
3024
3025 return 0;
3026}
3027
3029 bool inverse, bool a_markerless, int a_value, bool b_markerless, int b_value)
3030{
3031 if (a_markerless && b_markerless) {
3032 /* Neither channel has not-disabled markers, return whatever. */
3033 return 0;
3034 }
3035 if (a_markerless) {
3036 /* Put the markerless channel first. */
3037 return 0;
3038 }
3039 if (b_markerless) {
3040 /* Put the markerless channel first. */
3041 return 1;
3042 }
3043
3044 /* Both channels have markers. */
3045
3046 if (inverse) {
3047 if (a_value < b_value) {
3048 return 1;
3049 }
3050 return 0;
3051 }
3052
3053 if (a_value > b_value) {
3054 return 1;
3055 }
3056 return 0;
3057}
3058
3059static int channels_start_sort(const void *a, const void *b)
3060{
3061 const MovieTrackingDopesheetChannel *channel_a =
3062 static_cast<const MovieTrackingDopesheetChannel *>(a);
3063 const MovieTrackingDopesheetChannel *channel_b =
3064 static_cast<const MovieTrackingDopesheetChannel *>(b);
3065
3067 channel_a->tot_segment == 0,
3069 channel_b->tot_segment == 0,
3071}
3072
3073static int channels_end_sort(const void *a, const void *b)
3074{
3075 const MovieTrackingDopesheetChannel *channel_a =
3076 static_cast<const MovieTrackingDopesheetChannel *>(a);
3077 const MovieTrackingDopesheetChannel *channel_b =
3078 static_cast<const MovieTrackingDopesheetChannel *>(b);
3079
3081 channel_a->tot_segment == 0,
3083 channel_b->tot_segment == 0,
3085}
3086
3087static int channels_alpha_inverse_sort(const void *a, const void *b)
3088{
3089 if (channels_alpha_sort(a, b)) {
3090 return 0;
3091 }
3092
3093 return 1;
3094}
3095
3096static int channels_total_track_inverse_sort(const void *a, const void *b)
3097{
3098 if (channels_total_track_sort(a, b)) {
3099 return 0;
3100 }
3101
3102 return 1;
3103}
3104
3105static int channels_longest_segment_inverse_sort(const void *a, const void *b)
3106{
3108 return 0;
3109 }
3110
3111 return 1;
3112}
3113
3114static int channels_average_error_inverse_sort(const void *a, const void *b)
3115{
3116 const MovieTrackingDopesheetChannel *channel_a =
3117 static_cast<const MovieTrackingDopesheetChannel *>(a);
3118 const MovieTrackingDopesheetChannel *channel_b =
3119 static_cast<const MovieTrackingDopesheetChannel *>(b);
3120
3121 if (channel_a->track->error < channel_b->track->error) {
3122 return 1;
3123 }
3124
3125 return 0;
3126}
3127
3128static int channels_start_inverse_sort(const void *a, const void *b)
3129{
3130 const MovieTrackingDopesheetChannel *channel_a =
3131 static_cast<const MovieTrackingDopesheetChannel *>(a);
3132 const MovieTrackingDopesheetChannel *channel_b =
3133 static_cast<const MovieTrackingDopesheetChannel *>(b);
3134
3136 channel_a->tot_segment == 0,
3138 channel_b->tot_segment == 0,
3140}
3141
3142static int channels_end_inverse_sort(const void *a, const void *b)
3143{
3144 const MovieTrackingDopesheetChannel *channel_a =
3145 static_cast<const MovieTrackingDopesheetChannel *>(a);
3146 const MovieTrackingDopesheetChannel *channel_b =
3147 static_cast<const MovieTrackingDopesheetChannel *>(b);
3148
3150 channel_a->tot_segment == 0,
3152 channel_b->tot_segment == 0,
3154}
3155
3156/* Calculate frames segments at which track is tracked continuously. */
3158{
3159 MovieTrackingTrack *track = channel->track;
3160 int i, segment;
3161 bool first_not_disabled_marker_framenr_set;
3162
3163 channel->tot_segment = 0;
3164 channel->max_segment = 0;
3165 channel->total_frames = 0;
3166
3169
3170 /* TODO(sergey): looks a bit code-duplicated, need to look into
3171 * logic de-duplication here.
3172 */
3173
3174 /* count */
3175 i = 0;
3176 first_not_disabled_marker_framenr_set = false;
3177 while (i < track->markersnr) {
3178 MovieTrackingMarker *marker = &track->markers[i];
3179
3180 if ((marker->flag & MARKER_DISABLED) == 0) {
3181 int prev_fra = marker->framenr, len = 0;
3182
3183 i++;
3184 while (i < track->markersnr) {
3185 marker = &track->markers[i];
3186
3187 if (marker->framenr != prev_fra + 1) {
3188 break;
3189 }
3190 if (marker->flag & MARKER_DISABLED) {
3191 break;
3192 }
3193
3194 if (!first_not_disabled_marker_framenr_set) {
3195 channel->first_not_disabled_marker_framenr = marker->framenr;
3196 first_not_disabled_marker_framenr_set = true;
3197 }
3198 channel->last_not_disabled_marker_framenr = marker->framenr;
3199
3200 prev_fra = marker->framenr;
3201 len++;
3202 i++;
3203 }
3204
3205 channel->tot_segment++;
3206 (void)len; /* Quiet set-but-unused warning (may be removed). */
3207 }
3208
3209 i++;
3210 }
3211
3212 if (!channel->tot_segment) {
3213 return;
3214 }
3215
3216 channel->segments = MEM_calloc_arrayN<int>(2 * channel->tot_segment,
3217 "tracking channel segments");
3218
3219 /* create segments */
3220 i = 0;
3221 segment = 0;
3222 while (i < track->markersnr) {
3223 MovieTrackingMarker *marker = &track->markers[i];
3224
3225 if ((marker->flag & MARKER_DISABLED) == 0) {
3226 MovieTrackingMarker *start_marker = marker;
3227 int prev_fra = marker->framenr, len = 0;
3228
3229 i++;
3230 while (i < track->markersnr) {
3231 marker = &track->markers[i];
3232
3233 if (marker->framenr != prev_fra + 1) {
3234 break;
3235 }
3236 if (marker->flag & MARKER_DISABLED) {
3237 break;
3238 }
3239
3240 prev_fra = marker->framenr;
3241 channel->total_frames++;
3242 len++;
3243 i++;
3244 }
3245
3246 channel->segments[2 * segment] = start_marker->framenr;
3247 channel->segments[2 * segment + 1] = start_marker->framenr + len;
3248
3249 channel->max_segment = max_ii(channel->max_segment, len);
3250 segment++;
3251 }
3252
3253 i++;
3254 }
3255}
3256
3257/* Create channels for tracks and calculate tracked segments for them. */
3259{
3260 MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
3261 MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
3262 MovieTrackingReconstruction *reconstruction = &tracking_object->reconstruction;
3263
3264 bool sel_only = (dopesheet->flag & TRACKING_DOPE_SELECTED_ONLY) != 0;
3265 bool show_hidden = (dopesheet->flag & TRACKING_DOPE_SHOW_HIDDEN) != 0;
3266
3267 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
3268 if (!show_hidden && (track->flag & TRACK_HIDDEN) != 0) {
3269 continue;
3270 }
3271
3272 if (sel_only && !TRACK_SELECTED(track)) {
3273 continue;
3274 }
3275
3277 "tracking dopesheet channel");
3278 channel->track = track;
3279
3280 if (reconstruction->flag & TRACKING_RECONSTRUCTED) {
3281 SNPRINTF_UTF8(channel->name, "%s (%.4f)", track->name, track->error);
3282 }
3283 else {
3284 STRNCPY_UTF8(channel->name, track->name);
3285 }
3286
3288
3289 BLI_addtail(&dopesheet->channels, channel);
3290 dopesheet->tot_channel++;
3291 }
3292}
3293
3294/* Sot dopesheet channels using given method (name, average error, total coverage,
3295 * longest tracked segment) and could also inverse the list if it's enabled.
3296 */
3298 int sort_method,
3299 bool inverse)
3300{
3301 MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
3302
3303 if (inverse) {
3304 if (sort_method == TRACKING_DOPE_SORT_NAME) {
3306 }
3307 else if (sort_method == TRACKING_DOPE_SORT_LONGEST) {
3309 }
3310 else if (sort_method == TRACKING_DOPE_SORT_TOTAL) {
3312 }
3313 else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) {
3315 }
3316 else if (sort_method == TRACKING_DOPE_SORT_START) {
3318 }
3319 else if (sort_method == TRACKING_DOPE_SORT_END) {
3321 }
3322 }
3323 else {
3324 if (sort_method == TRACKING_DOPE_SORT_NAME) {
3326 }
3327 else if (sort_method == TRACKING_DOPE_SORT_LONGEST) {
3329 }
3330 else if (sort_method == TRACKING_DOPE_SORT_TOTAL) {
3332 }
3333 else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) {
3335 }
3336 else if (sort_method == TRACKING_DOPE_SORT_START) {
3338 }
3339 else if (sort_method == TRACKING_DOPE_SORT_END) {
3341 }
3342 }
3343}
3344
3346{
3347 /* Values are actually arbitrary here, probably need to be tweaked. */
3348 if (count < 8) {
3349 return TRACKING_COVERAGE_BAD;
3350 }
3351 if (count < 16) {
3353 }
3354 return TRACKING_COVERAGE_OK;
3355}
3356
3357/* Calculate coverage of frames with tracks, this information
3358 * is used to highlight dopesheet background depending on how
3359 * many tracks exists on the frame.
3360 */
3362{
3363 MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
3364 MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
3365 int frames, start_frame = INT_MAX, end_frame = -INT_MAX;
3366 int *per_frame_counter;
3367 int prev_coverage, last_segment_frame;
3368
3369 /* find frame boundaries */
3370 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
3371 start_frame = min_ii(start_frame, track->markers[0].framenr);
3372 end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr);
3373 }
3374
3375 if (start_frame > end_frame) {
3376 /* There are no markers at all, nothing to calculate coverage from. */
3377 return;
3378 }
3379
3380 frames = end_frame - start_frame + 1;
3381
3382 /* this is a per-frame counter of markers (how many markers belongs to the same frame) */
3383 per_frame_counter = MEM_calloc_arrayN<int>(frames, "per frame track counter");
3384
3385 /* find per-frame markers count */
3386 LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
3387 for (int i = 0; i < track->markersnr; i++) {
3388 MovieTrackingMarker *marker = &track->markers[i];
3389
3390 /* TODO: perhaps we need to add check for non-single-frame track here */
3391 if ((marker->flag & MARKER_DISABLED) == 0) {
3392 per_frame_counter[marker->framenr - start_frame]++;
3393 }
3394 }
3395 }
3396
3397 /* convert markers count to coverage and detect segments with the same coverage */
3398 prev_coverage = coverage_from_count(per_frame_counter[0]);
3399 last_segment_frame = start_frame;
3400
3401 /* means only disabled tracks in the beginning, could be ignored */
3402 if (!per_frame_counter[0]) {
3403 prev_coverage = TRACKING_COVERAGE_OK;
3404 }
3405
3406 for (int i = 1; i < frames; i++) {
3407 int coverage = coverage_from_count(per_frame_counter[i]);
3408
3409 /* means only disabled tracks in the end, could be ignored */
3410 if (i == frames - 1 && !per_frame_counter[i]) {
3411 coverage = TRACKING_COVERAGE_OK;
3412 }
3413
3414 if (coverage != prev_coverage || i == frames - 1) {
3415 MovieTrackingDopesheetCoverageSegment *coverage_segment;
3416 int end_segment_frame = i - 1 + start_frame;
3417
3418 if (end_segment_frame == last_segment_frame) {
3419 end_segment_frame++;
3420 }
3421
3423 "tracking coverage segment");
3424 coverage_segment->coverage = prev_coverage;
3425 coverage_segment->start_frame = last_segment_frame;
3426 coverage_segment->end_frame = end_segment_frame;
3427
3428 BLI_addtail(&dopesheet->coverage_segments, coverage_segment);
3429
3430 last_segment_frame = end_segment_frame;
3431 }
3432
3433 prev_coverage = coverage;
3434 }
3435
3436 MEM_freeN(per_frame_counter);
3437}
3438
3440{
3441 MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
3442
3443 dopesheet->ok = false;
3444}
3445
3447{
3448 MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
3449
3450 short sort_method = dopesheet->sort_method;
3451 bool inverse = (dopesheet->flag & TRACKING_DOPE_SORT_INVERSE) != 0;
3452
3453 if (dopesheet->ok) {
3454 return;
3455 }
3456
3457 tracking_dopesheet_free(dopesheet);
3458
3459 /* channels */
3461 tracking_dopesheet_channels_sort(tracking, sort_method, inverse);
3462
3463 /* frame coverage */
3465
3466 dopesheet->ok = true;
3467}
3468
3470 const MovieTrackingTrack *track)
3471{
3472 LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
3473 if (BLI_findindex(&tracking_object->tracks, track) != -1) {
3474 return tracking_object;
3475 }
3476 }
3477 return nullptr;
3478}
3479
3481 const MovieTracking *tracking, const MovieTrackingPlaneTrack *plane_track)
3482{
3483 LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
3484 if (BLI_findindex(&tracking_object->plane_tracks, plane_track) != -1) {
3485 return tracking_object;
3486 }
3487 }
3488 return nullptr;
3489}
3490
3492 const MovieTrackingTrack *track,
3493 char *rna_path,
3494 size_t rna_path_maxncpy)
3495{
3496 MovieTrackingObject *tracking_object = BKE_tracking_find_object_for_track(tracking, track);
3497 char track_name_esc[MAX_NAME * 2];
3498 BLI_str_escape(track_name_esc, track->name, sizeof(track_name_esc));
3499 if (tracking_object == nullptr) {
3500 BLI_snprintf_utf8(rna_path, rna_path_maxncpy, "tracking.tracks[\"%s\"]", track_name_esc);
3501 }
3502 else {
3503 char object_name_esc[MAX_NAME * 2];
3504 BLI_str_escape(object_name_esc, tracking_object->name, sizeof(object_name_esc));
3505 BLI_snprintf_utf8(rna_path,
3506 rna_path_maxncpy,
3507 "tracking.objects[\"%s\"].tracks[\"%s\"]",
3508 object_name_esc,
3509 track_name_esc);
3510 }
3511}
3512
3514 const MovieTrackingTrack *track,
3515 char *rna_path,
3516 size_t rna_path_maxncpy)
3517{
3518 MovieTrackingObject *tracking_object = BKE_tracking_find_object_for_track(tracking, track);
3519 if (tracking_object == nullptr) {
3520 BLI_strncpy_utf8(rna_path, "tracking.tracks", rna_path_maxncpy);
3521 }
3522 else {
3523 char object_name_esc[MAX_NAME * 2];
3524 BLI_str_escape(object_name_esc, tracking_object->name, sizeof(object_name_esc));
3525 BLI_snprintf_utf8(rna_path, rna_path_maxncpy, "tracking.objects[\"%s\"]", object_name_esc);
3526 }
3527}
3528
3530 const MovieTrackingPlaneTrack *plane_track,
3531 char *rna_path,
3532 size_t rna_path_maxncpy)
3533{
3535 plane_track);
3536 char track_name_esc[MAX_NAME * 2];
3537 BLI_str_escape(track_name_esc, plane_track->name, sizeof(track_name_esc));
3538 if (tracking_object == nullptr) {
3539 BLI_snprintf_utf8(rna_path, rna_path_maxncpy, "tracking.plane_tracks[\"%s\"]", track_name_esc);
3540 }
3541 else {
3542 char object_name_esc[MAX_NAME * 2];
3543 BLI_str_escape(object_name_esc, tracking_object->name, sizeof(object_name_esc));
3544 BLI_snprintf_utf8(rna_path,
3545 rna_path_maxncpy,
3546 "tracking.objects[\"%s\"].plane_tracks[\"%s\"]",
3547 object_name_esc,
3548 track_name_esc);
3549 }
3550}
3551
3553 const MovieTrackingPlaneTrack *plane_track,
3554 char *rna_path,
3555 size_t rna_path_maxncpy)
3556{
3558 plane_track);
3559 if (tracking_object == nullptr) {
3560 BLI_strncpy_utf8(rna_path, "tracking.plane_tracks", rna_path_maxncpy);
3561 }
3562 else {
3563 char object_name_esc[MAX_NAME * 2];
3564 BLI_str_escape(object_name_esc, tracking_object->name, sizeof(object_name_esc));
3566 rna_path, rna_path_maxncpy, "tracking.objects[\"%s\"].plane_tracks", object_name_esc);
3567 }
3568}
float evaluate_fcurve(const FCurve *fcu, float evaltime)
FCurve * id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, bool *r_driven)
void id_us_plus(ID *id)
Definition lib_id.cc:358
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
float BKE_movieclip_remap_clip_to_scene_frame(const struct MovieClip *clip, float framenr)
General operations, lookup, etc. for blender objects.
void BKE_object_where_is_calc_mat4(const Object *ob, float r_obmat[4][4])
@ TRACK_AREA_POINT
@ TRACK_AREA_ALL
@ TRACK_AREA_PAT
@ TRACK_AREA_SEARCH
@ TRACK_AREA_NONE
#define TRACK_SELECTED(track)
eTrackClearAction
@ TRACK_CLEAR_ALL
@ TRACK_CLEAR_REMAINED
@ TRACK_CLEAR_UPTO
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
void BLI_bitmap_draw_2d_poly_v2i_n(int xmin, int ymin, int xmax, int ymax, blender::Span< blender::int2 > verts, void(*callback)(int x, int x_end, int y, void *), void *user_data)
#define BLI_INLINE
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE int clamp_i(int value, int min, int max)
void perspective_m4(float mat[4][4], float left, float right, float bottom, float top, float nearClip, float farClip)
static constexpr int image_width
static constexpr int image_height
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], float srcweight)
void scale_m4_fl(float R[4][4], float scale)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void unit_m4(float m[4][4])
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v2_fl(float r[2], float f)
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], float t)
MINLINE void copy_v2_v2(float r[2], const float a[2])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void negate_v2_v2(float r[2], const float a[2])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void zero_v2(float r[2])
MINLINE bool is_finite_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t size_t size_t BLI_snprintf_utf8(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define SNPRINTF_UTF8(dst, format,...)
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
unsigned char uchar
#define INIT_MINMAX2(min, max)
#define ELEM(...)
#define STREQ(a, b)
#define CTX_DATA_(context, msgid)
#define BLT_I18NCONTEXT_ID_MOVIECLIP
#define DATA_(msgid)
@ CAMERA_SENSOR_FIT_HOR
#define DNA_struct_default_get(struct_name)
#define MAX_NAME
Definition DNA_defs.h:50
Object is a sort of wrapper for general info.
@ CAMERA_UNITS_MM
@ TRACKING_DOPE_SELECTED_ONLY
@ TRACKING_DOPE_SORT_INVERSE
@ TRACKING_DOPE_SHOW_HIDDEN
@ REFINE_NO_INTRINSICS
@ TRACK_DISABLE_BLUE
@ TRACK_HIDDEN
@ TRACK_PREVIEW_GRAYSCALE
@ TRACK_USE_2D_STAB
@ TRACK_HAS_BUNDLE
@ TRACK_USE_2D_STAB_ROT
@ TRACK_DISABLE_RED
@ TRACK_DISABLE_GREEN
@ TRACK_MOTION_MODEL_TRANSLATION
@ TRACKING_DOPE_SORT_START
@ TRACKING_DOPE_SORT_AVERAGE_ERROR
@ TRACKING_DOPE_SORT_LONGEST
@ TRACKING_DOPE_SORT_NAME
@ TRACKING_DOPE_SORT_END
@ TRACKING_DOPE_SORT_TOTAL
@ TRACKING_SHOW_STAB_TRACKS
@ TRACKING_DISTORTION_MODEL_DIVISION
@ TRACKING_DISTORTION_MODEL_POLYNOMIAL
@ TRACKING_DISTORTION_MODEL_NUKE
@ TRACKING_DISTORTION_MODEL_BROWN
@ TRACKING_FILTER_BILINEAR
@ TRACKING_RECONSTRUCTED
@ MARKER_TRACKED
@ MARKER_DISABLED
@ TRACK_ALGORITHM_FLAG_USE_BRUTE
@ TRACKING_COVERAGE_BAD
@ TRACKING_COVERAGE_OK
@ TRACKING_COVERAGE_ACCEPTABLE
@ TRACKING_OBJECT_CAMERA
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
void IMB_free_byte_pixels(ImBuf *ibuf)
void IMB_rectcpy(ImBuf *dbuf, const ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height)
Definition rectop.cc:444
@ IB_RECT_INVALID
@ IB_float_data
@ IB_byte_data
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
IndexRange index_range() const
Definition BLI_array.hh:360
nullptr float
#define SELECT
#define offsetof(t, d)
uint pos
uint top
MatBase< C, R > inverse(MatBase< C, R >) RET
VecBase< float, 2 > float2
int count
void libmv_cameraIntrinsicsUndistortFloat(const libmv_CameraIntrinsics *libmv_intrinsics, const float *source_image, int width, int height, float overscan, int channels, float *destination_image)
void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics *libmv_intrinsics)
libmv_CameraIntrinsics * libmv_cameraIntrinsicsCopy(const libmv_CameraIntrinsics *libmv_intrinsics)
void libmv_cameraIntrinsicsUndistortByte(const libmv_CameraIntrinsics *libmv_intrinsics, const unsigned char *source_image, int width, int height, float overscan, int channels, unsigned char *destination_image)
void libmv_cameraIntrinsicsDistortByte(const struct libmv_CameraIntrinsics *libmv_intrinsics, const unsigned char *source_image, int width, int height, float overscan, int channels, unsigned char *destination_image)
void libmv_cameraIntrinsicsApply(const struct libmv_CameraIntrinsics *libmv_intrinsics, double x, double y, double *x1, double *y1)
void libmv_cameraIntrinsicsDistortFloat(const libmv_CameraIntrinsics *libmv_intrinsics, float *source_image, int width, int height, float overscan, int channels, float *destination_image)
void libmv_cameraIntrinsicsUpdate(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, libmv_CameraIntrinsics *libmv_intrinsics)
void libmv_cameraIntrinsicsInvert(const struct libmv_CameraIntrinsics *libmv_intrinsics, double x, double y, double *x1, double *y1)
libmv_CameraIntrinsics * libmv_cameraIntrinsicsNew(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options)
struct libmv_CameraIntrinsics libmv_CameraIntrinsics
void libmv_samplePlanarPatchFloat(const float *image, int width, int height, int channels, const double *xs, const double *ys, int num_samples_x, int num_samples_y, const float *mask, float *patch, double *warped_position_x, double *warped_position_y)
void libmv_samplePlanarPatchByte(const unsigned char *image, int width, int height, int channels, const double *xs, const double *ys, int num_samples_x, int num_samples_y, const float *mask, unsigned char *patch, double *warped_position_x, double *warped_position_y)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static int left
T floor(const T &a)
T min(const T &a, const T &b)
T ceil(const T &a)
T max(const T &a, const T &b)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:151
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< int32_t, 2 > int2
const char * name
#define ceilf
#define min(a, b)
Definition sort.cc:36
char sensor_fit
float sensor_x
const ColorSpace * colorspace
const ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
void * first
struct MovieTracking tracking
float pixel_aspect
Definition tracking.cc:66
libmv_CameraIntrinsics * intrinsics
Definition tracking.cc:63
float principal_px[2]
Definition tracking.cc:65
struct MovieTrackingDopesheetChannel * next
MovieTrackingPlaneTrack * active_plane_track
MovieTrackingReconstruction reconstruction
MovieTrackingTrack * active_track
MovieTrackingTrack ** point_tracks
MovieTrackingPlaneMarker * markers
struct MovieReconstructedCamera * cameras
MovieTrackingMarker * markers
struct MovieTrackingTrack * next
struct MovieTrackingTrack * prev
MovieTrackingDopesheet dopesheet
MovieTrackingStats * stats
MovieTrackingStabilization stabilization
MovieTrackingCamera camera
MovieTrackingSettings settings
struct RenderData r
GHash * old_to_new_plane_track_map
Definition tracking.cc:175
GHash * old_to_new_track_map
Definition tracking.cc:174
struct bGPDframe * next
struct bGPDlayer * next
struct bGPDstroke * next
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
int BKE_tracking_count_selected_tracks_in_list(const ListBase *tracks_list)
Definition tracking.cc:629
static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
Definition tracking.cc:3361
static void tracking_tracks_free(ListBase *tracks)
Definition tracking.cc:79
void BKE_tracking_distortion_undistort_v2(MovieDistortion *distortion, const float co[2], float r_co[2])
Definition tracking.cc:2396
uint64_t BKE_tracking_camera_distortion_hash(const MovieTrackingCamera *camera)
Definition tracking.cc:2228
static const MovieTrackingMarker * get_usable_marker_for_interpolation(MovieTrackingTrack *track, const MovieTrackingMarker *anchor_marker, const int direction)
Definition tracking.cc:1419
MovieTrackingPlaneMarker * BKE_tracking_plane_marker_get_exact(MovieTrackingPlaneTrack *plane_track, int framenr)
Definition tracking.cc:1837
MovieTrackingTrack * BKE_tracking_track_get_for_selection_index(MovieTracking *tracking, int selection_index, ListBase **r_tracksbase)
Definition tracking.cc:1025
bool BKE_tracking_camera_distortion_equal(const MovieTrackingCamera *a, const MovieTrackingCamera *b)
Definition tracking.cc:2198
float BKE_tracking_track_get_weight_for_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker)
Definition tracking.cc:1172
static void tracking_tracks_copy(TrackingCopyContext *ctx, ListBase *tracks_dst, const ListBase *tracks_src, const int flag)
Definition tracking.cc:193
static void reconstructed_camera_scale_set(const MovieTrackingObject *tracking_object, float mat[4][4])
Definition tracking.cc:2091
void BKE_tracking_plane_marker_get_subframe_corners(MovieTrackingPlaneTrack *plane_track, float framenr, float corners[4][2])
Definition tracking.cc:1866
MovieTrackingPlaneMarker * BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track, MovieTrackingPlaneMarker *plane_marker)
Definition tracking.cc:1719
void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area)
Definition tracking.cc:1217
static void tracking_object_copy(MovieTrackingObject *tracking_object_dst, const MovieTrackingObject *tracking_object_src, const int flag)
Definition tracking.cc:268
void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *, MovieTrackingObject *tracking_object, float framenr, float mat[4][4])
Definition tracking.cc:2146
ImBuf * BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width, int calibration_height, float overscan)
Definition tracking.cc:2487
static void tracking_plane_tracks_free(ListBase *plane_tracks)
Definition tracking.cc:89
MovieTrackingPlaneTrack * BKE_tracking_plane_track_add(MovieTracking *tracking, ListBase *plane_tracks_base, ListBase *tracks, int framenr)
Definition tracking.cc:1542
void BKE_tracking_distortion_free(MovieDistortion *distortion)
Definition tracking.cc:2408
int BKE_tracking_count_selected_tracks_in_active_object(MovieTracking *tracking)
Definition tracking.cc:640
void BKE_tracking_get_rna_path_for_track(const MovieTracking *tracking, const MovieTrackingTrack *track, char *rna_path, size_t rna_path_maxncpy)
Definition tracking.cc:3491
static void tracking_copy_context_delete(TrackingCopyContext *ctx)
Definition tracking.cc:186
void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *tracking_object)
Definition tracking.cc:1956
MovieTrackingMarker * BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker)
Definition tracking.cc:1235
void BKE_tracking_get_camera_object_matrix(const Object *camera_object, float mat[4][4])
Definition tracking.cc:371
void BKE_tracking_track_first_last_frame_get(const MovieTrackingTrack *track, int *r_first_frame, int *r_last_frame)
Definition tracking.cc:603
void BKE_tracking_settings_init(MovieTracking *tracking)
Definition tracking.cc:330
ImBuf * BKE_tracking_get_pattern_imbuf(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, const bool anchored, const bool disable_channels)
Definition tracking.cc:2731
void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2])
Definition tracking.cc:1495
MovieTrackingTrack ** BKE_tracking_selected_tracks_in_active_object(MovieTracking *tracking, int *r_num_tracks)
Definition tracking.cc:646
void BKE_tracking_marker_clamp_pattern_position(MovieTrackingMarker *marker)
Definition tracking.cc:1308
void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, bool extend)
Definition tracking.cc:1190
void BKE_tracking_camera_to_blender(MovieTracking *tracking, Scene *scene, Camera *camera, int width, int height)
Definition tracking.cc:2115
void BKE_tracking_disable_channels(ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, bool grayscale)
Definition tracking.cc:2903
static int channels_alpha_inverse_sort(const void *a, const void *b)
Definition tracking.cc:3087
float * BKE_tracking_track_get_mask(const int frame_width, const int frame_height, const MovieTrackingTrack *track, const MovieTrackingMarker *marker)
Definition tracking.cc:1154
static void tracking_objects_free(ListBase *objects)
Definition tracking.cc:123
static int channels_average_error_sort(const void *a, const void *b)
Definition tracking.cc:3010
ImBuf * BKE_tracking_get_plane_imbuf(const ImBuf *frame_ibuf, const MovieTrackingPlaneMarker *plane_marker)
Definition tracking.cc:2822
static TrackingCopyContext tracking_copy_context_new()
Definition tracking.cc:178
MovieTrackingTrack * BKE_tracking_track_add_empty(MovieTracking *tracking, ListBase *tracks_list)
Definition tracking.cc:502
void BKE_tracking_track_flag_set(MovieTrackingTrack *track, int area, int flag)
Definition tracking.cc:675
ImBuf * BKE_tracking_sample_pattern(const int frame_width, const int frame_height, const ImBuf *search_ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, const bool from_anchor, const bool use_mask, const int num_samples_x, const int num_samples_y, float pos[2])
Definition tracking.cc:2634
static void tracking_objects_copy(ListBase *tracking_objects_dst, const ListBase *tracking_objects_src, const int flag)
Definition tracking.cc:297
static void multiply_marker(MovieTrackingMarker *marker, const float multiplier)
Definition tracking.cc:932
void BKE_tracking_track_path_clear(MovieTrackingTrack *track, const int ref_frame, const eTrackClearAction action)
Definition tracking.cc:776
ImBuf * BKE_tracking_get_search_imbuf(const ImBuf *ibuf, const MovieTrackingTrack *track, const MovieTrackingMarker *marker, const bool anchored, const bool disable_channels)
Definition tracking.cc:2769
static void tracking_dopesheet_channels_sort(MovieTracking *tracking, int sort_method, bool inverse)
Definition tracking.cc:3297
static void path_clear_all(MovieTrackingTrack *track, const int ref_frame)
Definition tracking.cc:759
static int channels_end_inverse_sort(const void *a, const void *b)
Definition tracking.cc:3142
static int channels_total_track_sort(const void *a, const void *b)
Definition tracking.cc:2982
MovieTrackingTrack * BKE_tracking_track_duplicate(MovieTrackingTrack *track)
Definition tracking.cc:566
MovieTrackingMarker * BKE_tracking_marker_ensure(MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1402
static void path_clear_remained(MovieTrackingTrack *track, const int ref_frame)
Definition tracking.cc:721
bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_track, MovieTrackingTrack *track)
Definition tracking.cc:1641
bool BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *tracking_object)
Definition tracking.cc:1926
void BKE_tracking_clipboard_free()
Definition tracking.cc:444
static void path_clear_up_to(MovieTrackingTrack *track, const int ref_frame)
Definition tracking.cc:738
static struct @163017152225275155122031115054340341101213077336 tracking_clipboard
static void tracking_average_markers(MovieTrackingTrack *dst_track, MovieTrackingTrack **src_tracks, const int num_src_tracks)
Definition tracking.cc:944
static void tracking_object_free(MovieTrackingObject *tracking_object)
Definition tracking.cc:115
static void accumulate_marker(MovieTrackingMarker *dst_marker, const MovieTrackingMarker *src_marker)
Definition tracking.cc:907
void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float framenr, float pos[2])
Definition tracking.cc:1507
static int channels_start_sort(const void *a, const void *b)
Definition tracking.cc:3059
void BKE_tracking_track_free(MovieTrackingTrack *track)
Definition tracking.cc:596
void BKE_tracking_camera_principal_point_pixel_get(MovieClip *clip, float r_principal_point_pixel[2])
Definition tracking.cc:2172
MovieTrackingObject * BKE_tracking_find_object_for_track(const MovieTracking *tracking, const MovieTrackingTrack *track)
Definition tracking.cc:3469
MovieTrackingMarker * BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1391
void BKE_tracking_free(MovieTracking *tracking)
Definition tracking.cc:161
static void tracking_reconstruction_copy(TrackingCopyContext *, MovieTrackingReconstruction *reconstruction_dst, const MovieTrackingReconstruction *reconstruction_src, const int)
Definition tracking.cc:247
void BKE_tracking_track_unique_name(ListBase *tracksbase, MovieTrackingTrack *track)
Definition tracking.cc:586
void BKE_tracking_plane_track_unique_name(ListBase *plane_tracks_base, MovieTrackingPlaneTrack *plane_track)
Definition tracking.cc:1614
bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr)
Definition tracking.cc:714
void BKE_tracking_undistort_v2(MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
Definition tracking.cc:2442
void BKE_tracking_plane_tracks_replace_point_track(MovieTracking *tracking, MovieTrackingTrack *old_track, MovieTrackingTrack *new_track)
Definition tracking.cc:1703
static void tracking_dopesheet_channels_calc(MovieTracking *tracking)
Definition tracking.cc:3258
void BKE_tracking_tracks_average(MovieTrackingTrack *dst_track, MovieTrackingTrack **src_tracks, const int num_src_tracks)
Definition tracking.cc:1013
MovieTrackingTrack * BKE_tracking_track_add(MovieTracking *tracking, ListBase *tracksbase, float x, float y, int framenr, int width, int height)
Definition tracking.cc:526
MovieTrackingPlaneMarker * BKE_tracking_plane_marker_get(MovieTrackingPlaneTrack *plane_track, int framenr)
Definition tracking.cc:1791
void BKE_tracking_plane_track_replace_point_track(MovieTrackingPlaneTrack *plane_track, MovieTrackingTrack *old_track, MovieTrackingTrack *new_track)
Definition tracking.cc:1691
static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
Definition tracking.cc:137
void BKE_tracking_distort_v2(MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
Definition tracking.cc:2415
void BKE_tracking_camera_principal_point_pixel_set(MovieClip *clip, const float principal_point_pixel[2])
Definition tracking.cc:2185
MovieTrackingObject * BKE_tracking_find_object_for_plane_track(const MovieTracking *tracking, const MovieTrackingPlaneTrack *plane_track)
Definition tracking.cc:3480
static int channels_end_sort(const void *a, const void *b)
Definition tracking.cc:3073
MovieDistortion * BKE_tracking_distortion_new(MovieTracking *tracking, int calibration_width, int calibration_height)
Definition tracking.cc:2262
static bGPDlayer * track_mask_gpencil_layer_get(const MovieTrackingTrack *track)
Definition tracking.cc:1049
void BKE_tracking_marker_clamp_search_size(MovieTrackingMarker *marker)
Definition tracking.cc:1327
void BKE_tracking_tracks_join(MovieTracking *tracking, MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track)
Definition tracking.cc:793
static int channels_longest_segment_sort(const void *a, const void *b)
Definition tracking.cc:2996
static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruction)
Definition tracking.cc:103
void BKE_tracking_get_rna_path_for_plane_track(const MovieTracking *tracking, const MovieTrackingPlaneTrack *plane_track, char *rna_path, size_t rna_path_maxncpy)
Definition tracking.cc:3529
static void tracking_dopesheet_channels_segments_calc(MovieTrackingDopesheetChannel *channel)
Definition tracking.cc:3157
void BKE_tracking_clipboard_copy_tracks(MovieTracking *, MovieTrackingObject *tracking_object)
Definition tracking.cc:461
float * tracking_track_get_mask_for_region(const int frame_width, const int frame_height, const float region_min[2], const float region_max[2], const MovieTrackingTrack *track)
Definition tracking.cc:1136
MovieTrackingTrack * BKE_tracking_object_find_track_with_name(MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:1993
void BKE_tracking_get_rna_path_prefix_for_plane_track(const MovieTracking *tracking, const MovieTrackingPlaneTrack *plane_track, char *rna_path, size_t rna_path_maxncpy)
Definition tracking.cc:3552
MovieTrackingPlaneTrack * BKE_tracking_object_find_plane_track_with_name(MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:2005
MovieTrackingObject * BKE_tracking_object_get_camera(const MovieTracking *tracking)
Definition tracking.cc:1982
void BKE_tracking_camera_shift_get(MovieTracking *tracking, int winx, int winy, float *shiftx, float *shifty)
Definition tracking.cc:2102
static void tracking_average_tracks(MovieTrackingTrack *dst_track, MovieTrackingTrack **src_tracks, const int num_src_tracks)
Definition tracking.cc:1001
bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_track, MovieTrackingTrack *track)
Definition tracking.cc:1652
static int channels_alpha_sort(const void *a, const void *b)
Definition tracking.cc:2968
MovieTrackingPlaneMarker * BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTrack *plane_track, int framenr)
Definition tracking.cc:1849
ImBuf * BKE_tracking_undistort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width, int calibration_height, float overscan)
Definition tracking.cc:2465
void BKE_tracking_distortion_distort_v2(MovieDistortion *distortion, const float co[2], float r_co[2])
Definition tracking.cc:2378
static void track_mask_set_pixel_cb(int x, int x_end, int y, void *user_data)
Definition tracking.cc:1090
void BKE_tracking_clipboard_paste_tracks(MovieTracking *, MovieTrackingObject *tracking_object)
Definition tracking.cc:482
bool BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr)
Definition tracking.cc:709
void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag)
Definition tracking.cc:692
void BKE_tracking_tracks_deselect_all(ListBase *tracksbase)
Definition tracking.cc:1222
static int compare_firstlast_putting_undefined_first(bool inverse, bool a_markerless, int a_value, bool b_markerless, int b_value)
Definition tracking.cc:3028
bool BKE_tracking_clipboard_has_tracks()
Definition tracking.cc:477
void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int calibration_width, int calibration_height)
Definition tracking.cc:2286
static void disable_imbuf_channels(ImBuf *ibuf, const MovieTrackingTrack *track, const bool grayscale)
Definition tracking.cc:2623
bool BKE_tracking_marker_get_interpolated(MovieTrackingTrack *track, const int framenr, MovieTrackingMarker *r_marker)
Definition tracking.cc:1437
static int reconstructed_camera_index_get(MovieTrackingReconstruction *reconstruction, int framenr, bool nearest)
Definition tracking.cc:2021
static int coverage_from_count(int count)
Definition tracking.cc:3345
void BKE_tracking_marker_delete(MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1281
void BKE_tracking_marker_clamp_search_position(MovieTrackingMarker *marker)
Definition tracking.cc:1338
static int channels_start_inverse_sort(const void *a, const void *b)
Definition tracking.cc:3128
static Value parallel_reduce(const int range, const Value &identity, const Function &function, const Reduction &reduction)
Definition tracking.cc:2514
MovieTrackingObject * BKE_tracking_object_get_active(const MovieTracking *tracking)
Definition tracking.cc:1977
static int channels_longest_segment_inverse_sort(const void *a, const void *b)
Definition tracking.cc:3105
static void track_mask_gpencil_layer_rasterize(const int frame_width, const int frame_height, const float region_min[2], const bGPDlayer *layer, float *mask, const int mask_width, const int mask_height)
Definition tracking.cc:1100
void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingObject *tracking_object, int framenr, int winx, int winy, float mat[4][4])
Definition tracking.cc:387
MovieDistortion * BKE_tracking_distortion_copy(MovieDistortion *distortion)
Definition tracking.cc:2307
static void tracking_plane_tracks_copy(TrackingCopyContext *ctx, ListBase *plane_tracks_list_dst, const ListBase *plane_tracks_list_src, const int flag)
Definition tracking.cc:217
void BKE_tracking_tracks_first_last_frame_minmax(MovieTrackingTrack **tracks, const int num_tracks, int *r_first_frame, int *r_last_frame)
Definition tracking.cc:613
MovieTrackingObject * BKE_tracking_object_add(MovieTracking *tracking, const char *name)
Definition tracking.cc:1897
void BKE_tracking_plane_marker_delete(MovieTrackingPlaneTrack *plane_track, int framenr)
Definition tracking.cc:1760
void BKE_tracking_copy(MovieTracking *tracking_dst, const MovieTracking *tracking_src, const int flag)
Definition tracking.cc:310
MovieReconstructedCamera * BKE_tracking_camera_get_reconstructed(MovieTracking *, MovieTrackingObject *tracking_object, int framenr)
Definition tracking.cc:2133
void BKE_tracking_dopesheet_update(MovieTracking *tracking)
Definition tracking.cc:3446
MovieTrackingMarker * BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr)
Definition tracking.cc:1358
void BKE_tracking_distortion_bounds_deltas(MovieDistortion *distortion, const int size[2], const int calibration_size[2], const bool undistort, int *r_right, int *r_left, int *r_bottom, int *r_top)
Definition tracking.cc:2534
void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking, MovieTrackingTrack *track)
Definition tracking.cc:1675
void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
Definition tracking.cc:1634
void BKE_tracking_plane_track_free(MovieTrackingPlaneTrack *plane_track)
Definition tracking.cc:1625
static int channels_average_error_inverse_sort(const void *a, const void *b)
Definition tracking.cc:3114
MovieTrackingObject * BKE_tracking_object_get_named(MovieTracking *tracking, const char *name)
Definition tracking.cc:1966
static void tracking_stabilization_copy(MovieTrackingStabilization *stabilization_dst, const MovieTrackingStabilization *stabilization_src, const int)
Definition tracking.cc:260
void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking)
Definition tracking.cc:3439
void BKE_tracking_get_rna_path_prefix_for_track(const MovieTracking *tracking, const MovieTrackingTrack *track, char *rna_path, size_t rna_path_maxncpy)
Definition tracking.cc:3513
BLI_INLINE int plane_marker_size_len_in_pixels(const float a[2], const float b[2], const int frame_width, const int frame_height)
Definition tracking.cc:2811
ListBase tracks
Definition tracking.cc:71
ImBuf * BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, ImBuf *ibuf, int calibration_width, int calibration_height, float overscan, bool undistort)
Definition tracking.cc:2318
static int channels_total_track_inverse_sort(const void *a, const void *b)
Definition tracking.cc:3096
void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker, bool before, bool overwrite)
void tracking_principal_point_pixel_to_normalized(const float principal_point_pixel[2], const int frame_width, const int frame_height, float r_principal_point_normalized[2])
void tracking_cameraIntrinscisOptionsFromTracking(MovieTracking *tracking, const int calibration_width, const int calibration_height, libmv_CameraIntrinsicsOptions *camera_intrinsics_options)
void tracking_get_marker_coords_for_tracking(int frame_width, int frame_height, const MovieTrackingMarker *marker, double search_pixel_x[5], double search_pixel_y[5])
void tracking_get_search_origin_frame_pixel(int frame_width, int frame_height, const MovieTrackingMarker *marker, float frame_pixel[2])
void tracking_principal_point_normalized_to_pixel(const float principal_point_normalized[2], const int frame_width, const int frame_height, float r_principal_point_pixel[2])
uint len
uint8_t flag
Definition wm_window.cc:145