Blender V4.5
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_array.hh"
9#include "BLI_hash.hh"
11
12#include "DNA_defaults.h"
13#include "DNA_movieclip_types.h"
14#include "DNA_tracking_types.h"
15
16#include "GPU_texture.hh"
17
18#include "BKE_movieclip.h"
19#include "BKE_tracking.h"
20
21#include "COM_context.hh"
23#include "COM_result.hh"
24#include "COM_utilities.hh"
25
26namespace blender::compositor {
27
28/* --------------------------------------------------------------------
29 * Distortion Grid Key.
30 */
31
39
45
47{
48 return BKE_tracking_camera_distortion_equal(&a.camera, &b.camera) && a.size == b.size &&
49 a.type == b.type && a.calibration_size == b.calibration_size;
50}
51
52/* --------------------------------------------------------------------
53 * Distortion Grid.
54 */
55
57 Context &context, MovieClip *movie_clip, int2 size, DistortionType type, int2 calibration_size)
58 : result(context.create_result(ResultType::Float2, ResultPrecision::Full))
59{
61 &movie_clip->tracking, calibration_size.x, calibration_size.y);
62
63 /* Compute how much the image would extend outside each of its bounds due to distortion. */
64 int right_delta;
65 int left_delta;
66 int bottom_delta;
67 int top_delta;
69 size,
70 calibration_size,
72 &right_delta,
73 &left_delta,
74 &bottom_delta,
75 &top_delta);
76
77 /* Clamp deltas to avoid excessive memory requirements in case of extreme distortion. */
78 right_delta = math::min(right_delta, size.x);
79 left_delta = math::min(left_delta, size.x);
80 bottom_delta = math::min(bottom_delta, size.y);
81 top_delta = math::min(top_delta, size.y);
82
83 /* Extend the size by the deltas of the bounds. */
84 const int2 extended_size = size + int2(right_delta + left_delta, bottom_delta + top_delta);
85
86 distortion_grid_ = Array<float2>(int64_t(extended_size.x) * extended_size.y);
87 parallel_for(extended_size, [&](const int2 texel) {
88 /* The tracking distortion functions expect the coordinates to be in the space of the image
89 * where the tracking camera was calibrated. So we first remap the coordinates into that space,
90 * apply the distortion, then remap back to the original coordinates space. This is done by
91 * dividing the by the size then multiplying by the calibration size, making sure to add 0.5 to
92 * evaluate at the center of pixels.
93 *
94 * Subtract the lower left bounds delta since we are looping over the extended domain. */
95 float2 coordinates = ((float2(texel - int2(left_delta, bottom_delta)) + 0.5f) / float2(size)) *
96 float2(calibration_size);
97
98 if (type == DistortionType::Undistort) {
99 BKE_tracking_distortion_undistort_v2(distortion, coordinates, coordinates);
100 }
101 else {
102 BKE_tracking_distortion_distort_v2(distortion, coordinates, coordinates);
103 }
104
105 /* Note that we should remap the coordinates back into the original size by dividing by the
106 * calibration size and multiplying by the size, however, we skip the latter to store the
107 * coordinates in normalized form, since this is what the shader expects. */
108 distortion_grid_[texel.y * int64_t(extended_size.x) + texel.x] = coordinates /
109 float2(calibration_size);
110 });
111
113
114 if (context.use_gpu()) {
115 this->result.allocate_texture(Domain(extended_size), false);
116 GPU_texture_update(this->result, GPU_DATA_FLOAT, distortion_grid_.data());
117
118 /* CPU-side data no longer needed, so free it. */
119 distortion_grid_ = Array<float2>();
120 }
121 else {
122 this->result.wrap_external(&distortion_grid_[0].x, extended_size);
123 }
124}
125
127{
128 this->result.release();
129}
130
131/* --------------------------------------------------------------------
132 * Distortion Grid Container.
133 */
134
136{
137 /* First, delete all resources that are no longer needed. */
138 map_.remove_if([](auto item) { return !item.value->needed; });
139
140 /* Second, reset the needed status of the remaining resources to false to ready them to track
141 * their needed status for the next evaluation. */
142 for (auto &value : map_.values()) {
143 value->needed = false;
144 }
145}
146
147static int2 get_movie_clip_size(MovieClip *movie_clip, int frame_number)
148{
150 BKE_movieclip_user_set_frame(&user, frame_number);
151
152 int2 size;
153 BKE_movieclip_get_size(movie_clip, &user, &size.x, &size.y);
154
155 return size;
156}
157
159 Context &context, MovieClip *movie_clip, int2 size, DistortionType type, int frame_number)
160{
161 const int2 calibration_size = get_movie_clip_size(movie_clip, frame_number);
162
163 const DistortionGridKey key(movie_clip->tracking.camera, size, type, calibration_size);
164
165 auto &distortion_grid = *map_.lookup_or_add_cb(key, [&]() {
166 return std::make_unique<DistortionGrid>(context, movie_clip, size, type, calibration_size);
167 });
168
169 distortion_grid.needed = true;
170 return distortion_grid.result;
171}
172
173} // 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:2395
void BKE_tracking_distortion_distort_v2(struct MovieDistortion *distortion, const float co[2], float r_co[2])
Definition tracking.cc:2377
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:2407
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:2261
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
#define DNA_struct_default_get(struct_name)
@ GPU_DATA_FLOAT
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const 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
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