Blender  V3.3
node_fn_align_euler_to_vector.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_math_vector.h"
4 #include "BLI_task.hh"
5 
6 #include "RNA_enum_types.h"
7 
8 #include "UI_interface.h"
9 #include "UI_resources.h"
10 
11 #include "node_function_util.hh"
12 
14 
16 {
17  b.is_function_node();
18  b.add_input<decl::Vector>(N_("Rotation")).subtype(PROP_EULER).hide_value();
19  b.add_input<decl::Float>(N_("Factor"))
20  .default_value(1.0f)
21  .min(0.0f)
22  .max(1.0f)
23  .subtype(PROP_FACTOR);
24  b.add_input<decl::Vector>(N_("Vector")).default_value({0.0, 0.0, 1.0});
25  b.add_output<decl::Vector>(N_("Rotation")).subtype(PROP_EULER);
26 }
27 
29  bContext *UNUSED(C),
30  PointerRNA *ptr)
31 {
32  uiItemR(layout, ptr, "axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
33  uiLayoutSetPropSep(layout, true);
34  uiLayoutSetPropDecorate(layout, false);
35  uiItemR(layout, ptr, "pivot_axis", 0, IFACE_("Pivot"), ICON_NONE);
36 }
37 
39  const VArray<float3> &input_rotations,
40  const VArray<float3> &vectors,
41  const VArray<float> &factors,
42  const float3 local_main_axis,
43  const MutableSpan<float3> output_rotations)
44 {
45  threading::parallel_for(mask.index_range(), 512, [&](IndexRange mask_range) {
46  for (const int maski : mask_range) {
47  const int64_t i = mask[maski];
48  const float3 vector = vectors[i];
49  if (is_zero_v3(vector)) {
50  output_rotations[i] = input_rotations[i];
51  continue;
52  }
53 
54  float old_rotation[3][3];
55  eul_to_mat3(old_rotation, input_rotations[i]);
56  float3 old_axis;
57  mul_v3_m3v3(old_axis, old_rotation, local_main_axis);
58 
59  const float3 new_axis = math::normalize(vector);
60  float3 rotation_axis = math::cross_high_precision(old_axis, new_axis);
61  if (is_zero_v3(rotation_axis)) {
62  /* The vectors are linearly dependent, so we fall back to another axis. */
63  rotation_axis = math::cross_high_precision(old_axis, float3(1, 0, 0));
64  if (is_zero_v3(rotation_axis)) {
65  /* This is now guaranteed to not be zero. */
66  rotation_axis = math::cross_high_precision(old_axis, float3(0, 1, 0));
67  }
68  }
69 
70  const float full_angle = angle_normalized_v3v3(old_axis, new_axis);
71  const float angle = factors[i] * full_angle;
72 
73  float rotation[3][3];
74  axis_angle_to_mat3(rotation, rotation_axis, angle);
75 
76  float new_rotation_matrix[3][3];
77  mul_m3_m3m3(new_rotation_matrix, rotation, old_rotation);
78 
79  float3 new_rotation;
80  mat3_to_eul(new_rotation, new_rotation_matrix);
81 
82  output_rotations[i] = new_rotation;
83  }
84  });
85 }
86 
88  const VArray<float3> &input_rotations,
89  const VArray<float3> &vectors,
90  const VArray<float> &factors,
91  const float3 local_main_axis,
92  const float3 local_pivot_axis,
93  const MutableSpan<float3> output_rotations)
94 {
95  threading::parallel_for(mask.index_range(), 512, [&](IndexRange mask_range) {
96  for (const int64_t maski : mask_range) {
97  const int64_t i = mask[maski];
98  if (local_main_axis == local_pivot_axis) {
99  /* Can't compute any meaningful rotation angle in this case. */
100  output_rotations[i] = input_rotations[i];
101  continue;
102  }
103 
104  const float3 vector = vectors[i];
105  if (is_zero_v3(vector)) {
106  output_rotations[i] = input_rotations[i];
107  continue;
108  }
109 
110  float old_rotation[3][3];
111  eul_to_mat3(old_rotation, input_rotations[i]);
112  float3 old_axis;
113  mul_v3_m3v3(old_axis, old_rotation, local_main_axis);
114  float3 pivot_axis;
115  mul_v3_m3v3(pivot_axis, old_rotation, local_pivot_axis);
116 
117  float full_angle = angle_signed_on_axis_v3v3_v3(vector, old_axis, pivot_axis);
118  if (full_angle > M_PI) {
119  /* Make sure the point is rotated as little as possible. */
120  full_angle -= 2.0f * M_PI;
121  }
122  const float angle = factors[i] * full_angle;
123 
124  float rotation[3][3];
125  axis_angle_to_mat3(rotation, pivot_axis, angle);
126 
127  float new_rotation_matrix[3][3];
128  mul_m3_m3m3(new_rotation_matrix, rotation, old_rotation);
129 
130  float3 new_rotation;
131  mat3_to_eul(new_rotation, new_rotation_matrix);
132 
133  output_rotations[i] = new_rotation;
134  }
135  });
136 }
137 
139  private:
140  int main_axis_mode_;
141  int pivot_axis_mode_;
142 
143  public:
144  MF_AlignEulerToVector(int main_axis_mode, int pivot_axis_mode)
145  : main_axis_mode_(main_axis_mode), pivot_axis_mode_(pivot_axis_mode)
146  {
147  static fn::MFSignature signature = create_signature();
148  this->set_signature(&signature);
149  }
150 
152  {
153  fn::MFSignatureBuilder signature{"Align Euler to Vector"};
154  signature.single_input<float3>("Rotation");
155  signature.single_input<float>("Factor");
156  signature.single_input<float3>("Vector");
157 
158  signature.single_output<float3>("Rotation");
159  return signature.build();
160  }
161 
163  {
164  const VArray<float3> &input_rotations = params.readonly_single_input<float3>(0, "Rotation");
165  const VArray<float> &factors = params.readonly_single_input<float>(1, "Factor");
166  const VArray<float3> &vectors = params.readonly_single_input<float3>(2, "Vector");
167 
168  auto output_rotations = params.uninitialized_single_output<float3>(3, "Rotation");
169 
170  float3 local_main_axis = {0.0f, 0.0f, 0.0f};
171  local_main_axis[main_axis_mode_] = 1;
172 
173  if (pivot_axis_mode_ == FN_NODE_ALIGN_EULER_TO_VECTOR_PIVOT_AXIS_AUTO) {
175  mask, input_rotations, vectors, factors, local_main_axis, output_rotations);
176  }
177  else {
178  float3 local_pivot_axis = {0.0f, 0.0f, 0.0f};
179  local_pivot_axis[pivot_axis_mode_ - 1] = 1;
181  input_rotations,
182  vectors,
183  factors,
184  local_main_axis,
185  local_pivot_axis,
186  output_rotations);
187  }
188  }
189 };
190 
192 {
193  bNode &node = builder.node();
195 }
196 
197 } // namespace blender::nodes::node_fn_align_euler_to_vector_cc
198 
200 {
202 
203  static bNodeType ntype;
204 
206  &ntype, FN_NODE_ALIGN_EULER_TO_VECTOR, "Align Euler to Vector", NODE_CLASS_CONVERTER);
210  nodeRegisterType(&ntype);
211 }
#define NODE_CLASS_CONVERTER
Definition: BKE_node.h:351
#define FN_NODE_ALIGN_EULER_TO_VECTOR
Definition: BKE_node.h:1531
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define UNUSED(x)
#define IFACE_(msgid)
@ FN_NODE_ALIGN_EULER_TO_VECTOR_PIVOT_AXIS_AUTO
@ PROP_EULER
Definition: RNA_types.h:159
@ PROP_FACTOR
Definition: RNA_types.h:144
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
@ UI_ITEM_R_EXPAND
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
OperationNode * node
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static void fn_node_align_euler_to_vector_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void fn_node_align_euler_to_vector_declare(NodeDeclarationBuilder &b)
static void align_rotations_fixed_pivot(IndexMask mask, const VArray< float3 > &input_rotations, const VArray< float3 > &vectors, const VArray< float > &factors, const float3 local_main_axis, const float3 local_pivot_axis, const MutableSpan< float3 > output_rotations)
static void fn_node_align_euler_to_vector_build_multi_function(NodeMultiFunctionBuilder &builder)
static void align_rotations_auto_pivot(IndexMask mask, const VArray< float3 > &input_rotations, const VArray< float3 > &vectors, const VArray< float > &factors, const float3 local_main_axis, const MutableSpan< float3 > output_rotations)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Definition: BLI_task.hh:51
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void register_node_type_fn_align_euler_to_vector()
void fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
Defines a node type.
Definition: BKE_node.h:226
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:244
NodeMultiFunctionBuildFunction build_multi_function
Definition: BKE_node.h:313
NodeDeclareFunction declare
Definition: BKE_node.h:324
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480