Blender  V3.3
COM_TransformOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. */
3 
5 #include "COM_RotateOperation.h"
6 #include "COM_ScaleOperation.h"
7 
8 namespace blender::compositor {
9 
11 {
18  translate_factor_x_ = 1.0f;
19  translate_factor_y_ = 1.0f;
20  convert_degree_to_rad_ = false;
21  sampler_ = PixelSampler::Bilinear;
22  invert_ = false;
23  max_scale_canvas_size_ = {ScaleOperation::DEFAULT_MAX_SCALE_CANVAS_SIZE,
25 }
26 
28 {
29  max_scale_canvas_size_ = size;
30 }
31 
33 {
34 
35  translate_x_ = get_input_operation(X_INPUT_INDEX)->get_constant_value_default(0.0f) *
36  translate_factor_x_;
37  translate_y_ = get_input_operation(Y_INPUT_INDEX)->get_constant_value_default(0.0f) *
38  translate_factor_y_;
39 
40  const float degree = get_input_operation(DEGREE_INPUT_INDEX)->get_constant_value_default(0.0f);
41  const double rad = convert_degree_to_rad_ ? DEG2RAD((double)degree) : degree;
42  rotate_cosine_ = cos(rad);
43  rotate_sine_ = sin(rad);
44 
45  scale_ = get_input_operation(SCALE_INPUT_INDEX)->get_constant_value_default(1.0f);
46 }
47 
49  const rcti &output_area,
50  rcti &r_input_area)
51 {
52  switch (input_idx) {
53  case IMAGE_INPUT_INDEX: {
54  NodeOperation *image_op = get_input_operation(IMAGE_INPUT_INDEX);
55  const rcti &image_canvas = image_op->get_canvas();
56  if (invert_) {
57  /* Scale -> Rotate -> Translate. */
58  r_input_area = output_area;
59  BLI_rcti_translate(&r_input_area, -translate_x_, -translate_y_);
61  rotate_canvas_,
62  rotate_sine_,
63  rotate_cosine_,
64  r_input_area,
65  r_input_area);
67  image_canvas, scale_canvas_, scale_, scale_, r_input_area, r_input_area);
68  }
69  else {
70  /* Translate -> Rotate -> Scale. */
72  rotate_canvas_, scale_canvas_, scale_, scale_, output_area, r_input_area);
74  rotate_canvas_,
75  rotate_sine_,
76  rotate_cosine_,
77  r_input_area,
78  r_input_area);
79  BLI_rcti_translate(&r_input_area, -translate_x_, -translate_y_);
80  }
81  expand_area_for_sampler(r_input_area, sampler_);
82  break;
83  }
84  case X_INPUT_INDEX:
85  case Y_INPUT_INDEX:
86  case DEGREE_INPUT_INDEX:
87  case SCALE_INPUT_INDEX: {
89  break;
90  }
91  }
92 }
93 
95  const rcti &area,
97 {
98  const MemoryBuffer *input_img = inputs[IMAGE_INPUT_INDEX];
99  BuffersIterator<float> it = output->iterate_with({}, area);
100  if (invert_) {
101  transform_inverted(it, input_img);
102  }
103  else {
104  transform(it, input_img);
105  }
106 }
107 
108 void TransformOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
109 {
110  const bool image_determined =
111  get_input_socket(IMAGE_INPUT_INDEX)->determine_canvas(preferred_area, r_area);
112  if (image_determined) {
113  rcti image_canvas = r_area;
114  rcti unused = COM_AREA_NONE;
115  get_input_socket(X_INPUT_INDEX)->determine_canvas(image_canvas, unused);
116  get_input_socket(Y_INPUT_INDEX)->determine_canvas(image_canvas, unused);
117  get_input_socket(DEGREE_INPUT_INDEX)->determine_canvas(image_canvas, unused);
118  get_input_socket(SCALE_INPUT_INDEX)->determine_canvas(image_canvas, unused);
119 
120  init_data();
121  if (invert_) {
122  /* Scale -> Rotate -> Translate. */
123  scale_canvas_ = image_canvas;
124  ScaleOperation::scale_area(scale_canvas_, scale_, scale_);
125  const Size2f max_scale_size = {
126  MAX2(BLI_rcti_size_x(&image_canvas), max_scale_canvas_size_.x),
127  MAX2(BLI_rcti_size_y(&image_canvas), max_scale_canvas_size_.y)};
128  ScaleOperation::clamp_area_size_max(scale_canvas_, max_scale_size);
129 
131  scale_canvas_, rotate_sine_, rotate_cosine_, rotate_canvas_);
132 
133  translate_canvas_ = rotate_canvas_;
134  BLI_rcti_translate(&translate_canvas_, translate_x_, translate_y_);
135 
136  r_area = translate_canvas_;
137  }
138  else {
139  /* Translate -> Rotate -> Scale. */
140  translate_canvas_ = image_canvas;
141  BLI_rcti_translate(&translate_canvas_, translate_x_, translate_y_);
142 
144  translate_canvas_, rotate_sine_, rotate_cosine_, rotate_canvas_);
145 
146  scale_canvas_ = rotate_canvas_;
147  ScaleOperation::scale_area(scale_canvas_, scale_, scale_);
148 
149  const Size2f max_scale_size = {
150  MAX2(BLI_rcti_size_x(&rotate_canvas_), max_scale_canvas_size_.x),
151  MAX2(BLI_rcti_size_y(&rotate_canvas_), max_scale_canvas_size_.y)};
152  ScaleOperation::clamp_area_size_max(scale_canvas_, max_scale_size);
153 
154  r_area = scale_canvas_;
155  }
156  }
157 }
158 
159 void TransformOperation::transform(BuffersIterator<float> &it, const MemoryBuffer *input_img)
160 {
161  float rotate_center_x, rotate_center_y;
162  RotateOperation::get_rotation_center(translate_canvas_, rotate_center_x, rotate_center_y);
163  float rotate_offset_x, rotate_offset_y;
165  translate_canvas_, rotate_canvas_, rotate_offset_x, rotate_offset_y);
166 
167  const float scale_center_x = BLI_rcti_size_x(&rotate_canvas_) / 2.0f;
168  const float scale_center_y = BLI_rcti_size_y(&rotate_canvas_) / 2.0f;
169  float scale_offset_x, scale_offset_y;
170  ScaleOperation::get_scale_offset(rotate_canvas_, scale_canvas_, scale_offset_x, scale_offset_y);
171 
172  for (; !it.is_end(); ++it) {
173  float x = ScaleOperation::scale_coord_inverted(it.x + scale_offset_x, scale_center_x, scale_);
174  float y = ScaleOperation::scale_coord_inverted(it.y + scale_offset_y, scale_center_y, scale_);
175 
176  x = rotate_offset_x + x;
177  y = rotate_offset_y + y;
179  x, y, rotate_center_x, rotate_center_y, rotate_sine_, rotate_cosine_);
180 
181  input_img->read_elem_sampled(x - translate_x_, y - translate_y_, sampler_, it.out);
182  }
183 }
184 
185 void TransformOperation::transform_inverted(BuffersIterator<float> &it,
186  const MemoryBuffer *input_img)
187 {
188  const rcti &image_canvas = get_input_operation(IMAGE_INPUT_INDEX)->get_canvas();
189  const float scale_center_x = BLI_rcti_size_x(&image_canvas) / 2.0f - translate_x_;
190  const float scale_center_y = BLI_rcti_size_y(&image_canvas) / 2.0f - translate_y_;
191  float scale_offset_x, scale_offset_y;
192  ScaleOperation::get_scale_offset(image_canvas, scale_canvas_, scale_offset_x, scale_offset_y);
193 
194  float rotate_center_x, rotate_center_y;
195  RotateOperation::get_rotation_center(translate_canvas_, rotate_center_x, rotate_center_y);
196  rotate_center_x -= translate_x_;
197  rotate_center_y -= translate_y_;
198  float rotate_offset_x, rotate_offset_y;
200  scale_canvas_, rotate_canvas_, rotate_offset_x, rotate_offset_y);
201 
202  for (; !it.is_end(); ++it) {
203  float x = rotate_offset_x + (it.x - translate_x_);
204  float y = rotate_offset_y + (it.y - translate_y_);
206  x, y, rotate_center_x, rotate_center_y, rotate_sine_, rotate_cosine_);
207 
208  x = ScaleOperation::scale_coord_inverted(x + scale_offset_x, scale_center_x, scale_);
209  y = ScaleOperation::scale_coord_inverted(y + scale_offset_y, scale_center_y, scale_);
210 
211  input_img->read_elem_sampled(x, y, sampler_, it.out);
212  }
213 }
214 
215 } // namespace blender::compositor
#define DEG2RAD(_deg)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:559
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
#define MAX2(a, b)
_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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static constexpr float DEFAULT_MAX_SCALE_CANVAS_SIZE
a MemoryBuffer contains access to the data of a chunk
void read_elem_sampled(float x, float y, PixelSampler sampler, float *out) const
bool determine_canvas(const rcti &preferred_area, rcti &r_area)
NodeOperation contains calculation logic.
void add_output_socket(DataType datatype)
float get_constant_value_default(float default_value)
NodeOperation * get_input_operation(int index)
NodeOperationInput * get_input_socket(unsigned int index)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
static void get_rotation_offset(const rcti &input_canvas, const rcti &rotate_canvas, float &r_offset_x, float &r_offset_y)
static void rotate_coords(float &x, float &y, float center_x, float center_y, float sine, float cosine)
static void get_rotation_area_of_interest(const rcti &input_canvas, const rcti &rotate_canvas, float sine, float cosine, const rcti &output_area, rcti &r_input_area)
static void get_rotation_canvas(const rcti &input_canvas, float sine, float cosine, rcti &r_canvas)
static void get_rotation_center(const rcti &area, float &r_x, float &r_y)
static void get_scale_offset(const rcti &input_canvas, const rcti &scale_canvas, float &r_scale_offset_x, float &r_scale_offset_y)
static void get_scale_area_of_interest(const rcti &input_canvas, const rcti &scale_canvas, float relative_scale_x, float relative_scale_y, const rcti &output_area, rcti &r_input_area)
static void scale_area(rcti &area, float relative_scale_x, float relative_scale_y)
static float scale_coord_inverted(const float coord, const float center, const float relative_scale)
static void clamp_area_size_max(rcti &area, Size2f max_size)
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
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
ccl_global KernelShaderEvalInput ccl_global float * output
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:311
static void area(int d1, int d2, int e1, int e2, float weights[2])
void expand_area_for_sampler(rcti &area, PixelSampler sampler)
Definition: COM_Enums.cc:8
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
constexpr rcti COM_CONSTANT_INPUT_AREA_OF_INTEREST
Definition: COM_defines.h:113
constexpr rcti COM_AREA_NONE
Definition: COM_defines.h:112
static bNodeSocketTemplate inputs[]