Blender V4.3
COM_RotateOperation.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "BLI_math_rotation.h"
8
9namespace blender::compositor {
10
12{
17 do_degree2_rad_conversion_ = false;
18 is_degree_set_ = false;
19 sampler_ = PixelSampler::Bilinear;
21}
22
23void RotateOperation::get_rotation_center(const rcti &area, float &r_x, float &r_y)
24{
25 r_x = BLI_rcti_size_x(&area) / 2.0;
26 r_y = BLI_rcti_size_y(&area) / 2.0;
27}
28
30 const rcti &rotate_canvas,
31 float &r_offset_x,
32 float &r_offset_y)
33{
34 r_offset_x = (BLI_rcti_size_x(&input_canvas) - BLI_rcti_size_x(&rotate_canvas)) / 2.0f;
35 r_offset_y = (BLI_rcti_size_y(&input_canvas) - BLI_rcti_size_y(&rotate_canvas)) / 2.0f;
36}
37
39 const float center_x,
40 const float center_y,
41 const float sine,
42 const float cosine,
43 rcti &r_bounds)
44{
45 const float dxmin = area.xmin - center_x;
46 const float dymin = area.ymin - center_y;
47 const float dxmax = area.xmax - center_x;
48 const float dymax = area.ymax - center_y;
49
50 const float x1 = center_x + (cosine * dxmin + (-sine) * dymin);
51 const float x2 = center_x + (cosine * dxmax + (-sine) * dymin);
52 const float x3 = center_x + (cosine * dxmin + (-sine) * dymax);
53 const float x4 = center_x + (cosine * dxmax + (-sine) * dymax);
54 const float y1 = center_y + (sine * dxmin + cosine * dymin);
55 const float y2 = center_y + (sine * dxmax + cosine * dymin);
56 const float y3 = center_y + (sine * dxmin + cosine * dymax);
57 const float y4 = center_y + (sine * dxmax + cosine * dymax);
58 const float minx = std::min(x1, std::min(x2, std::min(x3, x4)));
59 const float maxx = std::max(x1, std::max(x2, std::max(x3, x4)));
60 const float miny = std::min(y1, std::min(y2, std::min(y3, y4)));
61 const float maxy = std::max(y1, std::max(y2, std::max(y3, y4)));
62
63 r_bounds.xmin = floor(minx);
64 r_bounds.xmax = ceil(maxx);
65 r_bounds.ymin = floor(miny);
66 r_bounds.ymax = ceil(maxy);
67}
68
70 const float center_x,
71 const float center_y,
72 const float sine,
73 const float cosine,
74 rcti &r_bounds)
75{
76 get_area_rotation_bounds(area, center_x, center_y, -sine, cosine, r_bounds);
77}
78
80 const rcti &rotate_canvas,
81 const float sine,
82 const float cosine,
83 const rcti &output_area,
84 rcti &r_input_area)
85{
86 float center_x, center_y;
87 get_rotation_center(input_canvas, center_x, center_y);
88
89 float rotate_offset_x, rotate_offset_y;
90 get_rotation_offset(input_canvas, rotate_canvas, rotate_offset_x, rotate_offset_y);
91
92 r_input_area = output_area;
93 BLI_rcti_translate(&r_input_area, rotate_offset_x, rotate_offset_y);
94 get_area_rotation_bounds_inverted(r_input_area, center_x, center_y, sine, cosine, r_input_area);
95}
96
98 const float sine,
99 const float cosine,
100 rcti &r_canvas)
101{
102 float center_x, center_y;
103 get_rotation_center(input_canvas, center_x, center_y);
104
105 rcti rot_bounds;
106 get_area_rotation_bounds(input_canvas, center_x, center_y, sine, cosine, rot_bounds);
107
108 float offset_x, offset_y;
109 get_rotation_offset(input_canvas, rot_bounds, offset_x, offset_y);
110 r_canvas = rot_bounds;
111 BLI_rcti_translate(&r_canvas, -offset_x, -offset_y);
112}
113
115
117{
118 if (!is_degree_set_) {
119 float degree = get_input_operation(DEGREE_INPUT_INDEX)->get_constant_value_default(0.0f);
120
121 double rad;
122 if (do_degree2_rad_conversion_) {
123 rad = DEG2RAD(double(degree));
124 }
125 else {
126 rad = degree;
127 }
128 cosine_ = cos(rad);
129 sine_ = sin(rad);
130
131 is_degree_set_ = true;
132 }
133}
134
135void RotateOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
136{
137 const bool image_determined =
138 get_input_socket(IMAGE_INPUT_INDEX)->determine_canvas(preferred_area, r_area);
139 if (image_determined) {
140 rcti input_canvas = r_area;
141 rcti unused = COM_AREA_NONE;
142 get_input_socket(DEGREE_INPUT_INDEX)->determine_canvas(input_canvas, unused);
143
145
146 get_rotation_canvas(input_canvas, sine_, cosine_, r_area);
147 }
148}
149
151 const rcti &output_area,
152 rcti &r_input_area)
153{
154 if (input_idx == DEGREE_INPUT_INDEX) {
156 return;
157 }
158
160
161 const rcti &input_image_canvas = get_input_operation(IMAGE_INPUT_INDEX)->get_canvas();
163 input_image_canvas, this->get_canvas(), sine_, cosine_, output_area, r_input_area);
164 expand_area_for_sampler(r_input_area, sampler_);
165}
166
168 const rcti &area,
170{
171 const MemoryBuffer *input_img = inputs[IMAGE_INPUT_INDEX];
172
173 NodeOperation *image_op = get_input_operation(IMAGE_INPUT_INDEX);
174 float center_x, center_y;
175 get_rotation_center(image_op->get_canvas(), center_x, center_y);
176 float rotate_offset_x, rotate_offset_y;
178 image_op->get_canvas(), this->get_canvas(), rotate_offset_x, rotate_offset_y);
179
180 for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
181 float x = rotate_offset_x + it.x + canvas_.xmin + 0.5f;
182 float y = rotate_offset_y + it.y + canvas_.ymin + 0.5f;
183 rotate_coords(x, y, center_x, center_y, sine_, cosine_);
184 input_img->read_elem_sampled(
185 x - canvas_.xmin - 0.5f, y - canvas_.ymin - 0.5f, sampler_, it.out);
186 }
187}
188
189} // namespace blender::compositor
#define DEG2RAD(_deg)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition rct.c:560
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
a MemoryBuffer contains access to the data
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)
void set_canvas_input_index(unsigned int index)
set the index of the input socket that will determine the canvas of this operation
void determine_canvas(const rcti &preferred_area, rcti &r_area) override
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_area_rotation_bounds_inverted(const rcti &area, float center_x, float center_y, float sine, float cosine, rcti &r_bounds)
static void get_area_rotation_bounds(const rcti &area, float center_x, float center_y, float sine, float cosine, rcti &r_bounds)
static void get_rotation_canvas(const rcti &input_canvas, float sine, float cosine, rcti &r_canvas)
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
static void get_rotation_center(const rcti &area, float &r_x, float &r_y)
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.
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
ccl_device_inline float3 cos(float3 v)
void expand_area_for_sampler(rcti &area, PixelSampler sampler)
Definition COM_Enums.cc:9
constexpr rcti COM_CONSTANT_INPUT_AREA_OF_INTEREST
Definition COM_defines.h:90
constexpr rcti COM_AREA_NONE
Definition COM_defines.h:89
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
int ymin
int ymax
int xmin
int xmax