Blender V5.0
distortion_grid.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cstdint>
6#include <memory>
7
8#include "BLI_hash.hh"
10
11#include "DNA_defaults.h"
12#include "DNA_movieclip_types.h"
13#include "DNA_tracking_types.h"
14
15#include "BKE_movieclip.h"
16#include "BKE_tracking.h"
17
18#include "COM_context.hh"
20#include "COM_result.hh"
21#include "COM_utilities.hh"
22
23namespace blender::compositor {
24
25/* --------------------------------------------------------------------
26 * Distortion Grid Key.
27 */
28
36
42
44{
45 return BKE_tracking_camera_distortion_equal(&a.camera, &b.camera) && a.size == b.size &&
46 a.type == b.type && a.calibration_size == b.calibration_size;
47}
48
49/* --------------------------------------------------------------------
50 * Distortion Grid.
51 */
52
54 Context &context, MovieClip *movie_clip, int2 size, DistortionType type, int2 calibration_size)
55 : result(context.create_result(ResultType::Float2, ResultPrecision::Full))
56{
58 &movie_clip->tracking, calibration_size.x, calibration_size.y);
59
60 /* Compute how much the image would extend outside each of its bounds due to distortion. */
61 int right_delta;
62 int left_delta;
63 int bottom_delta;
64 int top_delta;
66 size,
67 calibration_size,
69 &right_delta,
70 &left_delta,
71 &bottom_delta,
72 &top_delta);
73
74 /* Clamp deltas to avoid excessive memory requirements in case of extreme distortion. */
75 right_delta = math::min(right_delta, size.x);
76 left_delta = math::min(left_delta, size.x);
77 bottom_delta = math::min(bottom_delta, size.y);
78 top_delta = math::min(top_delta, size.y);
79
80 /* Extend the size by the deltas of the bounds. */
81 const int2 extended_size = size + int2(right_delta + left_delta, bottom_delta + top_delta);
82
83 this->result.allocate_texture(extended_size, false, ResultStorageType::CPU);
84
85 parallel_for(extended_size, [&](const int2 texel) {
86 /* The tracking distortion functions expect the coordinates to be in the space of the image
87 * where the tracking camera was calibrated. So we first remap the coordinates into that space,
88 * apply the distortion, then remap back to the original coordinates space. This is done by
89 * dividing by the size then multiplying by the calibration size, making sure to add 0.5 to
90 * evaluate at the center of pixels.
91 *
92 * Subtract the lower left bounds delta since we are looping over the extended domain. */
93 float2 coordinates = ((float2(texel - int2(left_delta, bottom_delta)) + 0.5f) / float2(size)) *
94 float2(calibration_size);
95
96 if (type == DistortionType::Undistort) {
97 BKE_tracking_distortion_undistort_v2(distortion, coordinates, coordinates);
98 }
99 else {
100 BKE_tracking_distortion_distort_v2(distortion, coordinates, coordinates);
101 }
102
103 /* Note that we should remap the coordinates back into the original size by dividing by the
104 * calibration size and multiplying by the size, however, we skip the latter to store the
105 * coordinates in normalized form, since this is what the shader expects. */
106 this->result.store_pixel(texel, coordinates / float2(calibration_size));
107 });
108
110
111 if (context.use_gpu()) {
112 const Result gpu_result = this->result.upload_to_gpu(false);
113 this->result.release();
114 this->result = gpu_result;
115 }
116}
117
119{
120 this->result.release();
121}
122
123/* --------------------------------------------------------------------
124 * Distortion Grid Container.
125 */
126
128{
129 /* First, delete all resources that are no longer needed. */
130 map_.remove_if([](auto item) { return !item.value->needed; });
131
132 /* Second, reset the needed status of the remaining resources to false to ready them to track
133 * their needed status for the next evaluation. */
134 for (auto &value : map_.values()) {
135 value->needed = false;
136 }
137}
138
139static int2 get_movie_clip_size(MovieClip *movie_clip, int frame_number)
140{
142 BKE_movieclip_user_set_frame(&user, frame_number);
143
144 int2 size;
145 BKE_movieclip_get_size(movie_clip, &user, &size.x, &size.y);
146
147 return size;
148}
149
151 Context &context, MovieClip *movie_clip, int2 size, DistortionType type, int frame_number)
152{
153 const int2 calibration_size = get_movie_clip_size(movie_clip, frame_number);
154
155 const DistortionGridKey key(movie_clip->tracking.camera, size, type, calibration_size);
156
157 auto &distortion_grid = *map_.lookup_or_add_cb(key, [&]() {
158 return std::make_unique<DistortionGrid>(context, movie_clip, size, type, calibration_size);
159 });
160
161 distortion_grid.needed = true;
162 return distortion_grid.result;
163}
164
165} // namespace blender::compositor
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
void BKE_movieclip_get_size(struct MovieClip *clip, const struct MovieClipUser *user, int *r_width, int *r_height)
void BKE_tracking_distortion_undistort_v2(struct MovieDistortion *distortion, const float co[2], float r_co[2])
Definition tracking.cc:2396
void BKE_tracking_distortion_distort_v2(struct MovieDistortion *distortion, const float co[2], float r_co[2])
Definition tracking.cc:2378
bool BKE_tracking_camera_distortion_equal(const struct MovieTrackingCamera *a, const struct MovieTrackingCamera *b)
void BKE_tracking_distortion_free(struct MovieDistortion *distortion)
Definition tracking.cc:2408
uint64_t BKE_tracking_camera_distortion_hash(const struct MovieTrackingCamera *camera)
struct MovieDistortion * BKE_tracking_distortion_new(struct MovieTracking *tracking, int calibration_width, int calibration_height)
Definition tracking.cc:2262
void BKE_tracking_distortion_bounds_deltas(MovieDistortion *distortion, const int size[2], const int calibration_size[2], const bool undistort, int *r_right, int *r_left, int *r_bottom, int *r_top)
Definition tracking.cc:2534
#define DNA_struct_default_get(struct_name)
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
Result & get(Context &context, MovieClip *movie_clip, int2 size, DistortionType type, int frame_number)
DistortionGridKey(const MovieTrackingCamera &camera, int2 size, DistortionType type, int2 calibration_size)
DistortionGrid(Context &context, MovieClip *movie_clip, int2 size, DistortionType type, int2 calibration_size)
bool operator==(const BokehKernelKey &a, const BokehKernelKey &b)
static int2 get_movie_clip_size(MovieClip *movie_clip, int frame_number)
void parallel_for(const int2 range, const Function &function)
T min(const T &a, const T &b)
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
struct MovieTracking tracking
MovieTrackingCamera camera