Blender  V3.3
COM_PlaneCornerPinOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2014 Blender Foundation. */
3 
6 
7 namespace blender::compositor {
8 
9 constexpr int LOWER_LEFT_CORNER_INDEX = 0;
10 constexpr int LOWER_RIGHT_CORNER_INDEX = 1;
11 constexpr int UPPER_RIGHT_CORNER_INDEX = 2;
12 constexpr int UPPER_LEFT_CORNER_INDEX = 3;
13 
14 static bool check_corners(float corners[4][2])
15 {
16  int i, next, prev;
17  float cross = 0.0f;
18 
19  for (i = 0; i < 4; i++) {
20  float v1[2], v2[2], cur_cross;
21 
22  next = (i + 1) % 4;
23  prev = (4 + i - 1) % 4;
24 
25  sub_v2_v2v2(v1, corners[i], corners[prev]);
26  sub_v2_v2v2(v2, corners[next], corners[i]);
27 
28  cur_cross = cross_v2v2(v1, v2);
29  if (fabsf(cur_cross) <= FLT_EPSILON) {
30  return false;
31  }
32 
33  if (cross == 0.0f) {
34  cross = cur_cross;
35  }
36  else if (cross * cur_cross < 0.0f) {
37  return false;
38  }
39  }
40 
41  return true;
42 }
43 
44 /* TODO(manzanilla): to be removed with tiled implementation. */
45 static void read_corners_from_sockets(rcti *rect, SocketReader *readers[4], float corners[4][2])
46 {
47  for (int i = 0; i < 4; i++) {
48  float result[4] = {0.0f, 0.0f, 0.0f, 0.0f};
49  readers[i]->read_sampled(result, rect->xmin, rect->ymin, PixelSampler::Nearest);
50  corners[i][0] = result[0];
51  corners[i][1] = result[1];
52  }
53 
54  /* convexity check:
55  * concave corners need to be prevented, otherwise
56  * BKE_tracking_homography_between_two_quads will freeze
57  */
58  if (!check_corners(corners)) {
59  /* simply revert to default corners
60  * there could be a more elegant solution,
61  * this prevents freezing at least.
62  */
63  corners[0][0] = 0.0f;
64  corners[0][1] = 0.0f;
65  corners[1][0] = 1.0f;
66  corners[1][1] = 0.0f;
67  corners[2][0] = 1.0f;
68  corners[2][1] = 1.0f;
69  corners[3][0] = 0.0f;
70  corners[3][1] = 1.0f;
71  }
72 }
73 
74 static void set_default_corner(const int corner_idx, float r_corner[2])
75 {
76  BLI_assert(corner_idx >= 0 && corner_idx < 4);
77  switch (corner_idx) {
79  r_corner[0] = 0.0f;
80  r_corner[1] = 0.0f;
81  break;
83  r_corner[0] = 1.0f;
84  r_corner[1] = 0.0f;
85  break;
87  r_corner[0] = 1.0f;
88  r_corner[1] = 1.0f;
89  break;
91  r_corner[0] = 0.0f;
92  r_corner[1] = 1.0f;
93  break;
94  }
95 }
96 
97 static void read_input_corners(NodeOperation *op, const int first_input_idx, float r_corners[4][2])
98 {
99  for (const int i : IndexRange(4)) {
100  NodeOperation *input = op->get_input_operation(i + first_input_idx);
101  if (input->get_flags().is_constant_operation) {
102  ConstantOperation *corner_input = static_cast<ConstantOperation *>(input);
103  copy_v2_v2(r_corners[i], corner_input->get_constant_elem());
104  }
105  else {
106  set_default_corner(i, r_corners[i]);
107  }
108  }
109 
110  /* Convexity check: concave corners need to be prevented, otherwise
111  * #BKE_tracking_homography_between_two_quads will freeze. */
112  if (!check_corners(r_corners)) {
113  /* Revert to default corners. There could be a more elegant solution,
114  * this prevents freezing at least. */
115  for (const int i : IndexRange(4)) {
116  set_default_corner(i, r_corners[i]);
117  }
118  }
119 }
120 
121 /* ******** PlaneCornerPinMaskOperation ******** */
122 
124 {
129 
130  /* XXX this is stupid: we need to make this "complex",
131  * so we can use the initialize_tile_data function
132  * to read corners from input sockets ...
133  */
134  flags_.complex = true;
135 }
136 
138 {
140  float corners[4][2];
141  read_input_corners(this, 0, corners);
142  calculate_corners(corners, true, 0);
143  }
144 }
145 
146 /* TODO(manzanilla): to be removed with tiled implementation. Same for #deinit_execution and do the
147  * same on #PlaneCornerPinWarpImageOperation. */
149 {
151 
152  init_mutex();
153 }
154 
156 {
158 
159  deinit_mutex();
160 }
161 
163 {
165 
166  /* get corner values once, by reading inputs at (0,0)
167  * XXX this assumes invariable values (no image inputs),
168  * we don't have a nice generic system for that yet
169  */
170  lock_mutex();
171  if (!corners_ready_) {
172  SocketReader *readers[4] = {
177  };
178  float corners[4][2];
179  read_corners_from_sockets(rect, readers, corners);
180  calculate_corners(corners, true, 0);
181 
182  corners_ready_ = true;
183  }
184  unlock_mutex();
185 
186  return data;
187 }
188 
189 void PlaneCornerPinMaskOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
190 {
192  /* Determine input canvases. */
193  PlaneDistortMaskOperation::determine_canvas(preferred_area, r_area);
194  }
195  r_area = preferred_area;
196 }
197 
199  const rcti &UNUSED(output_area),
200  rcti &r_input_area)
201 {
202  /* All corner inputs are used as constants. */
204 }
205 
206 /* ******** PlaneCornerPinWarpImageOperation ******** */
207 
209 {
214 }
215 
217 {
219  float corners[4][2];
220  read_input_corners(this, 1, corners);
221  calculate_corners(corners, true, 0);
222  }
223 }
224 
226 {
228 
229  init_mutex();
230 }
231 
233 {
235 
236  deinit_mutex();
237 }
238 
240 {
242 
243  /* get corner values once, by reading inputs at (0,0)
244  * XXX this assumes invariable values (no image inputs),
245  * we don't have a nice generic system for that yet
246  */
247  lock_mutex();
248  if (!corners_ready_) {
249  /* corner sockets start at index 1 */
250  SocketReader *readers[4] = {
255  };
256  float corners[4][2];
257  read_corners_from_sockets(rect, readers, corners);
258  calculate_corners(corners, true, 0);
259 
260  corners_ready_ = true;
261  }
262  unlock_mutex();
263 
264  return data;
265 }
266 
268  rcti *input, ReadBufferOperation *read_operation, rcti *output)
269 {
270  for (int i = 0; i < 4; i++) {
272  input, read_operation, output)) {
273  return true;
274  }
275  }
276 
277  /* XXX this is bad, but unavoidable with the current design:
278  * we don't know the actual corners and matrix at this point,
279  * so all we can do is get the full input image
280  */
281  output->xmin = 0;
282  output->ymin = 0;
283  output->xmax = get_input_operation(0)->get_width();
284  output->ymax = get_input_operation(0)->get_height();
285  return true;
286 #if 0
288  input, read_operation, output);
289 #endif
290 }
291 
293  const rcti &output_area,
294  rcti &r_input_area)
295 {
296  if (input_idx == 0) {
297  PlaneDistortWarpImageOperation::get_area_of_interest(input_idx, output_area, r_input_area);
298  }
299  else {
300  /* Corner inputs are used as constants. */
302  }
303 }
304 
305 } // namespace blender::compositor
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
#define UNUSED(x)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
ATTR_WARN_UNUSED_RESULT const BMVert * v2
virtual const float * get_constant_elem()=0
NodeOperation contains calculation logic.
SocketReader * get_input_socket_reader(unsigned int index)
NodeOperation * get_input_operation(int index)
void read_sampled(float result[4], float x, float y, PixelSampler sampler)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
virtual void * initialize_tile_data(rcti *)
virtual void determine_canvas(const rcti &preferred_area, rcti &r_area)
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override
Get input operation area being read by this operation on rendering given output area.
void determine_canvas(const rcti &preferred_area, rcti &r_area) override
bool determine_depending_area_of_interest(rcti *input, ReadBufferOperation *read_operation, rcti *output) override
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override
Get input operation area being read by this operation on rendering given output area.
virtual void calculate_corners(const float corners[4][2], bool normalized, int sample)
void calculate_corners(const float corners[4][2], bool normalized, int sample) override
void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override
Get input operation area being read by this operation on rendering given output area.
bool determine_depending_area_of_interest(rcti *input, ReadBufferOperation *read_operation, rcti *output) override
@ Vector
Vector data type.
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
static ulong * next
#define fabsf(x)
Definition: metal/compat.h:219
static void read_corners_from_sockets(rcti *rect, SocketReader *readers[4], float corners[4][2])
constexpr rcti COM_CONSTANT_INPUT_AREA_OF_INTEREST
Definition: COM_defines.h:113
static void read_input_corners(NodeOperation *op, const int first_input_idx, float r_corners[4][2])
static bool check_corners(float corners[4][2])
static void set_default_corner(const int corner_idx, float r_corner[2])
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
int ymin
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63