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