Blender  V2.93
COM_PlaneDistortCommonOperation.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2013, Blender Foundation.
17  */
18 
20 
21 #include "MEM_guardedalloc.h"
22 
23 #include "BLI_jitter_2d.h"
24 #include "BLI_listbase.h"
25 #include "BLI_math.h"
26 #include "BLI_math_color.h"
27 
28 #include "BKE_movieclip.h"
29 #include "BKE_node.h"
30 #include "BKE_tracking.h"
31 
32 namespace blender::compositor {
33 
34 /* ******** PlaneDistort WarpImage ******** */
35 
36 BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2])
37 {
38  float vec[3] = {x, y, 1.0f};
39  mul_m3_v3(matrix, vec);
40  uv[0] = vec[0] / vec[2];
41  uv[1] = vec[1] / vec[2];
42 
43  deriv[0][0] = (matrix[0][0] - matrix[0][2] * uv[0]) / vec[2];
44  deriv[1][0] = (matrix[0][1] - matrix[0][2] * uv[1]) / vec[2];
45  deriv[0][1] = (matrix[1][0] - matrix[1][2] * uv[0]) / vec[2];
46  deriv[1][1] = (matrix[1][1] - matrix[1][2] * uv[1]) / vec[2];
47 }
48 
50 {
53  this->m_pixelReader = nullptr;
54  this->m_motion_blur_samples = 1;
55  this->m_motion_blur_shutter = 0.5f;
56  this->flags.complex = true;
57 }
58 
59 void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2],
60  bool normalized,
61  int sample)
62 {
63  BLI_assert(sample < this->m_motion_blur_samples);
64  const int width = this->m_pixelReader->getWidth();
65  const int height = this->m_pixelReader->getHeight();
66  float frame_corners[4][2] = {
67  {0.0f, 0.0f}, {(float)width, 0.0f}, {(float)width, (float)height}, {0.0f, (float)height}};
68  MotionSample *sample_data = &this->m_samples[sample];
69  if (normalized) {
70  for (int i = 0; i < 4; i++) {
71  sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
72  sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
73  }
74  }
75  else {
76  for (int i = 0; i < 4; i++) {
77  sample_data->frameSpaceCorners[i][0] = corners[i][0];
78  sample_data->frameSpaceCorners[i][1] = corners[i][1];
79  }
80  }
82  sample_data->frameSpaceCorners, frame_corners, sample_data->perspectiveMatrix);
83 }
84 
86 {
87  this->m_pixelReader = this->getInputSocketReader(0);
88 }
89 
91 {
92  this->m_pixelReader = nullptr;
93 }
94 
96  float x,
97  float y,
98  PixelSampler /*sampler*/)
99 {
100  float uv[2];
101  float deriv[2][2];
102  if (this->m_motion_blur_samples == 1) {
103  warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv);
104  m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]);
105  }
106  else {
107  zero_v4(output);
108  for (int sample = 0; sample < this->m_motion_blur_samples; sample++) {
109  float color[4];
110  warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv);
111  m_pixelReader->readFiltered(color, uv[0], uv[1], deriv[0], deriv[1]);
112  add_v4_v4(output, color);
113  }
114  mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples);
115  }
116 }
117 
119  rcti *input, ReadBufferOperation *readOperation, rcti *output)
120 {
121  float min[2], max[2];
122  INIT_MINMAX2(min, max);
123 
124  for (int sample = 0; sample < this->m_motion_blur_samples; sample++) {
125  float UVs[4][2];
126  float deriv[2][2];
127  MotionSample *sample_data = &this->m_samples[sample];
128  /* TODO(sergey): figure out proper way to do this. */
129  warpCoord(input->xmin - 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv);
130  warpCoord(input->xmax + 2, input->ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv);
131  warpCoord(input->xmax + 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv);
132  warpCoord(input->xmin - 2, input->ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv);
133  for (int i = 0; i < 4; i++) {
134  minmax_v2v2_v2(min, max, UVs[i]);
135  }
136  }
137 
138  rcti newInput;
139 
140  newInput.xmin = min[0] - 1;
141  newInput.ymin = min[1] - 1;
142  newInput.xmax = max[0] + 1;
143  newInput.ymax = max[1] + 1;
144 
145  return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
146 }
147 
148 /* ******** PlaneDistort Mask ******** */
149 
151 {
153 
154  /* Currently hardcoded to 8 samples. */
155  m_osa = 8;
156  this->m_motion_blur_samples = 1;
157  this->m_motion_blur_shutter = 0.5f;
158 }
159 
160 void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2],
161  bool normalized,
162  int sample)
163 {
164  BLI_assert(sample < this->m_motion_blur_samples);
165  MotionSample *sample_data = &this->m_samples[sample];
166  if (normalized) {
167  for (int i = 0; i < 4; i++) {
168  sample_data->frameSpaceCorners[i][0] = corners[i][0] * this->getWidth();
169  sample_data->frameSpaceCorners[i][1] = corners[i][1] * this->getHeight();
170  }
171  }
172  else {
173  for (int i = 0; i < 4; i++) {
174  sample_data->frameSpaceCorners[i][0] = corners[i][0];
175  sample_data->frameSpaceCorners[i][1] = corners[i][1];
176  }
177  }
178 }
179 
181 {
183 }
184 
186  float x,
187  float y,
188  PixelSampler /*sampler*/)
189 {
190  float point[2];
191  int inside_counter = 0;
192  if (this->m_motion_blur_samples == 1) {
193  MotionSample *sample_data = &this->m_samples[0];
194  for (int sample = 0; sample < this->m_osa; sample++) {
195  point[0] = x + this->m_jitter[sample][0];
196  point[1] = y + this->m_jitter[sample][1];
197  if (isect_point_tri_v2(point,
198  sample_data->frameSpaceCorners[0],
199  sample_data->frameSpaceCorners[1],
200  sample_data->frameSpaceCorners[2]) ||
201  isect_point_tri_v2(point,
202  sample_data->frameSpaceCorners[0],
203  sample_data->frameSpaceCorners[2],
204  sample_data->frameSpaceCorners[3])) {
205  inside_counter++;
206  }
207  }
208  output[0] = (float)inside_counter / this->m_osa;
209  }
210  else {
211  for (int motion_sample = 0; motion_sample < this->m_motion_blur_samples; motion_sample++) {
212  MotionSample *sample_data = &this->m_samples[motion_sample];
213  for (int osa_sample = 0; osa_sample < this->m_osa; osa_sample++) {
214  point[0] = x + this->m_jitter[osa_sample][0];
215  point[1] = y + this->m_jitter[osa_sample][1];
216  if (isect_point_tri_v2(point,
217  sample_data->frameSpaceCorners[0],
218  sample_data->frameSpaceCorners[1],
219  sample_data->frameSpaceCorners[2]) ||
220  isect_point_tri_v2(point,
221  sample_data->frameSpaceCorners[0],
222  sample_data->frameSpaceCorners[2],
223  sample_data->frameSpaceCorners[3])) {
224  inside_counter++;
225  }
226  }
227  }
228  output[0] = (float)inside_counter / (this->m_osa * this->m_motion_blur_samples);
229  }
230 }
231 
232 } // namespace blender::compositor
typedef float(TangentPoint)[2]
void BKE_tracking_homography_between_two_quads(float reference_corners[4][2], float corners[4][2], float H[3][3])
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
void BLI_jitter_init(float(*jitarr)[2], int num)
Definition: jitter_2d.c:142
int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
Definition: math_geom.c:1595
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void add_v4_v4(float r[4], const float a[4])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
Definition: math_vector.c:1043
MINLINE void zero_v4(float r[4])
#define INIT_MINMAX2(min, max)
_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 width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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 y
Read Guarded memory(de)allocation.
#define output
SIMD_FORCE_INLINE btVector3 normalized() const
Return a normalized version of this vector.
void addInputSocket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void addOutputSocket(DataType datatype)
void readFiltered(float result[4], float x, float y, float dx[2], float dy[2])
SocketReader * getInputSocketReader(unsigned int inputSocketindex)
virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void calculateCorners(const float corners[4][2], bool normalized, int sample)
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) override
void calculateCorners(const float corners[4][2], bool normalized, int sample)
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
@ None
The bottom left of the input image is the bottom left of the working area of the node,...
static void sample(SocketReader *reader, int x, int y, float color[4])
BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2])
#define min(a, b)
Definition: sort.c:51
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79
float max