Geometry Nodes: Initial basic rotation socket nodes
This PR adds an initial set of nodes using the new rotation socket. 6 nodes build rotations or convert them to other formats, a 7th rotates a vector with a rotation, and the last inverts rotations. The design task #109965 describes the choice to use separate nodes for the rotation construction and separation operations. In the future, a "Switch Node" operator (#111438) will help to make working with these separated nodes faster. - **Axis Angle to Rotation** - **Rotation to Axis Angle** - **Combine Quaternion** - **Separate Quaternion** - **Euler to Rotation** - **Rotation to Euler** - **Rotate Vector** - **Invert Rotation** See #92967 Pull Request: https://projects.blender.org/blender/blender/pulls/109030
This commit is contained in:
parent
81eb7edc8b
commit
45d8a8b0c3
|
@ -564,7 +564,15 @@ class NODE_MT_category_GEO_UTILITIES_ROTATION(Menu):
|
|||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeAlignEulerToVector")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeAxisAngleToRotation")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeEulerToRotation")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeInvertRotation")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotateVector")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotationToAxisAngle")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotationToEuler")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeRotationToQuaternion")
|
||||
node_add_menu.add_node_type(layout, "FunctionNodeQuaternionToRotation")
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
|
|
|
@ -1348,6 +1348,15 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define FN_NODE_INPUT_INT 1220
|
||||
#define FN_NODE_SEPARATE_COLOR 1221
|
||||
#define FN_NODE_COMBINE_COLOR 1222
|
||||
#define FN_NODE_AXIS_ANGLE_TO_ROTATION 1223
|
||||
#define FN_NODE_EULER_TO_ROTATION 1224
|
||||
#define FN_NODE_QUATERNION_TO_ROTATION 1225
|
||||
#define FN_NODE_ROTATION_TO_AXIS_ANGLE 1226
|
||||
#define FN_NODE_ROTATION_TO_EULER 1227
|
||||
#define FN_NODE_ROTATION_TO_QUATERNION 1228
|
||||
#define FN_NODE_ROTATE_VECTOR 1229
|
||||
#define FN_NODE_ROTATE_ROTATION 1230
|
||||
#define FN_NODE_INVERT_ROTATION 1231
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -264,9 +264,12 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_ST
|
|||
DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" )
|
||||
|
||||
DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, 0, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler to Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_AXIS_ANGLE_TO_ROTATION, 0, "AXIS_ANGLE_TO_ROTATION", AxisAngleToRotation, "Axis Angle to Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, 0, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMBINE_COLOR, 0, "COMBINE_COLOR", CombineColor, "Combine Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_QUATERNION_TO_ROTATION, 0, "QUATERNION_TO_ROTATION", QuaternionToRotation, "Quaternion to Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_COMPARE, 0, "COMPARE", Compare, "Compare", "")
|
||||
DefNode(FunctionNode, FN_NODE_EULER_TO_ROTATION, 0, "EULER_TO_ROTATION", EulerToRotation, "Euler to Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_FLOAT_TO_INT, def_float_to_int, "FLOAT_TO_INT", FloatToInt, "Float to Integer", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_BOOL, def_fn_input_bool, "INPUT_BOOL", InputBool, "Boolean", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_COLOR, def_fn_input_color, "INPUT_COLOR", InputColor, "Color", "")
|
||||
|
@ -274,10 +277,15 @@ DefNode(FunctionNode, FN_NODE_INPUT_INT, def_fn_input_int, "INPUT_INT", InputInt
|
|||
DefNode(FunctionNode, FN_NODE_INPUT_SPECIAL_CHARACTERS, 0, "INPUT_SPECIAL_CHARACTERS", InputSpecialCharacters, "Special Characters", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_STRING, def_fn_input_string, "INPUT_STRING", InputString, "String", "")
|
||||
DefNode(FunctionNode, FN_NODE_INPUT_VECTOR, def_fn_input_vector, "INPUT_VECTOR", InputVector, "Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_INVERT_ROTATION, 0, "INVERT_ROTATION", InvertRotation, "Invert Rotation", "")
|
||||
DefNode(FunctionNode, FN_NODE_RANDOM_VALUE, def_fn_random_value, "RANDOM_VALUE", RandomValue, "Random Value", "")
|
||||
DefNode(FunctionNode, FN_NODE_REPLACE_STRING, 0, "REPLACE_STRING", ReplaceString, "Replace String", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATE_EULER, def_fn_rotate_euler, "ROTATE_EULER", RotateEuler, "Rotate Euler", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATE_VECTOR, 0, "ROTATE_VECTOR", RotateVector, "Rotate Vector", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_AXIS_ANGLE, 0, "ROTATION_TO_AXIS_ANGLE", RotationToAxisAngle, "Rotation to Axis Angle", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_EULER, 0, "ROTATION_TO_EULER", RotationToEuler, "Rotation to Euler", "")
|
||||
DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, 0, "SEPARATE_COLOR", SeparateColor, "Separate Color", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATION_TO_QUATERNION, 0, "ROTATION_TO_QUATERNION", RotationToQuaternion, "Rotation to Quaternion", "")
|
||||
DefNode(FunctionNode, FN_NODE_SLICE_STRING, 0, "SLICE_STRING", SliceString, "Slice String", "")
|
||||
DefNode(FunctionNode, FN_NODE_STRING_LENGTH, 0, "STRING_LENGTH", StringLength, "String Length", "")
|
||||
DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
|
||||
|
|
|
@ -19,9 +19,11 @@ set(INC_SYS
|
|||
|
||||
set(SRC
|
||||
nodes/node_fn_align_euler_to_vector.cc
|
||||
nodes/node_fn_axis_angle_to_rotation.cc
|
||||
nodes/node_fn_boolean_math.cc
|
||||
nodes/node_fn_combine_color.cc
|
||||
nodes/node_fn_compare.cc
|
||||
nodes/node_fn_euler_to_rotation.cc
|
||||
nodes/node_fn_float_to_int.cc
|
||||
nodes/node_fn_input_bool.cc
|
||||
nodes/node_fn_input_color.cc
|
||||
|
@ -29,9 +31,15 @@ set(SRC
|
|||
nodes/node_fn_input_special_characters.cc
|
||||
nodes/node_fn_input_string.cc
|
||||
nodes/node_fn_input_vector.cc
|
||||
nodes/node_fn_invert_rotation.cc
|
||||
nodes/node_fn_quaternion_to_rotation.cc
|
||||
nodes/node_fn_random_value.cc
|
||||
nodes/node_fn_replace_string.cc
|
||||
nodes/node_fn_rotate_euler.cc
|
||||
nodes/node_fn_rotate_vector.cc
|
||||
nodes/node_fn_rotation_to_axis_angle.cc
|
||||
nodes/node_fn_rotation_to_euler.cc
|
||||
nodes/node_fn_rotation_to_quaternion.cc
|
||||
nodes/node_fn_separate_color.cc
|
||||
nodes/node_fn_slice_string.cc
|
||||
nodes/node_fn_string_length.cc
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_axis_angle.hh"
|
||||
#include "BLI_math_quaternion.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_axis_angle_to_rotation_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Axis").default_value({0.0f, 0.0f, 1.0f});
|
||||
b.add_input<decl::Float>("Angle").subtype(PROP_ANGLE);
|
||||
b.add_output<decl::Rotation>("Rotation");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float3, float, math::Quaternion>(
|
||||
"Axis Angle to Quaternion", [](float3 axis, float angle) {
|
||||
if (UNLIKELY(math::is_zero(axis))) {
|
||||
return math::Quaternion::identity();
|
||||
}
|
||||
const float3 axis_normalized = math::normalize(axis);
|
||||
const math::AxisAngle axis_angle = math::AxisAngle(axis_normalized, angle);
|
||||
return math::to_quaternion(axis_angle);
|
||||
});
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_AXIS_ANGLE_TO_ROTATION, "Axis Angle to Rotation", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_axis_angle_to_rotation_cc
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_euler.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_euler_to_rotation_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Euler").subtype(PROP_EULER);
|
||||
b.add_output<decl::Rotation>("Rotation");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<float3, math::Quaternion>(
|
||||
"Euler XYZ to Quaternion",
|
||||
[](float3 euler) { return math::to_quaternion(math::EulerXYZ(euler)); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_EULER_TO_ROTATION, "Euler to Rotation", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_euler_to_rotation_cc
|
|
@ -0,0 +1,35 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_quaternion.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_invert_rotation_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Rotation>("Rotation");
|
||||
b.add_output<decl::Rotation>("Rotation");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<math::Quaternion, math::Quaternion>(
|
||||
"Invert Quaternion", [](math::Quaternion quat) { return math::invert(quat); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_INVERT_ROTATION, "Invert Rotation", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_invert_rotation_cc
|
|
@ -0,0 +1,42 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_quaternion.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_quaternion_to_rotation_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Float>("W").default_value(1.0f);
|
||||
b.add_input<decl::Float>("X").default_value(0.0f);
|
||||
b.add_input<decl::Float>("Y").default_value(0.0f);
|
||||
b.add_input<decl::Float>("Z").default_value(0.0f);
|
||||
b.add_output<decl::Rotation>("Rotation");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI4_SO<float, float, float, float, math::Quaternion>(
|
||||
"Quaternion to Rotation", [](float w, float x, float y, float z) {
|
||||
math::Quaternion combined(w, x, y, z);
|
||||
return math::normalize(combined);
|
||||
});
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_QUATERNION_TO_ROTATION, "Quaternion to Rotation", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_quaternion_to_rotation_cc
|
|
@ -0,0 +1,37 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_quaternion.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_rotate_vector_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Vector");
|
||||
b.add_input<decl::Rotation>("Rotation");
|
||||
b.add_output<decl::Vector>("Vector");
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI2_SO<float3, math::Quaternion, float3>(
|
||||
"Rotate Vector",
|
||||
[](float3 vector, math::Quaternion quat) { return math::transform_point(quat, vector); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_ROTATE_VECTOR, "Rotate Vector", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_rotate_vector_cc
|
|
@ -0,0 +1,63 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_axis_angle.hh"
|
||||
#include "BLI_math_quaternion.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_rotation_to_axis_angle_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Rotation>("Rotation");
|
||||
b.add_output<decl::Vector>("Axis");
|
||||
b.add_output<decl::Float>("Angle").subtype(PROP_ANGLE);
|
||||
};
|
||||
|
||||
class QuaterniontoAxisAngleFunction : public mf::MultiFunction {
|
||||
public:
|
||||
QuaterniontoAxisAngleFunction()
|
||||
{
|
||||
static mf::Signature signature_;
|
||||
mf::SignatureBuilder builder{"Quaternion to Axis Angle", signature_};
|
||||
builder.single_input<math::Quaternion>("Quaternion");
|
||||
builder.single_output<float3>("Axis");
|
||||
builder.single_output<float>("Angle");
|
||||
this->set_signature(&signature_);
|
||||
}
|
||||
|
||||
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArraySpan<math::Quaternion> quaternions =
|
||||
params.readonly_single_input<math::Quaternion>(0, "Quaternion");
|
||||
MutableSpan<float3> axes = params.uninitialized_single_output<float3>(1, "Axis");
|
||||
MutableSpan<float> angles = params.uninitialized_single_output<float>(2, "Angle");
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const math::AxisAngle axis_angle = math::to_axis_angle(quaternions[i]);
|
||||
axes[i] = axis_angle.axis();
|
||||
angles[i] = axis_angle.angle().radian();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static QuaterniontoAxisAngleFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_ROTATION_TO_AXIS_ANGLE, "Rotation to Axis Angle", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_rotation_to_axis_angle_cc
|
|
@ -0,0 +1,35 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_euler.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_rotation_to_euler_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Rotation>("Rotation");
|
||||
b.add_output<decl::Vector>("Euler").subtype(PROP_EULER);
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto fn = mf::build::SI1_SO<math::Quaternion, float3>(
|
||||
"Quaternion to Euler XYZ", [](math::Quaternion quat) { return math::to_euler(quat); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_ROTATION_TO_EULER, "Rotation to Euler", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_rotation_to_euler_cc
|
|
@ -0,0 +1,70 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_quaternion_types.hh"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes::node_fn_rotation_to_quaternion_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Rotation>("Rotation");
|
||||
b.add_output<decl::Float>("W");
|
||||
b.add_output<decl::Float>("X");
|
||||
b.add_output<decl::Float>("Y");
|
||||
b.add_output<decl::Float>("Z");
|
||||
};
|
||||
|
||||
class SeparateQuaternionFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateQuaternionFunction()
|
||||
{
|
||||
static mf::Signature signature_;
|
||||
mf::SignatureBuilder builder{"Rotation to Quaternion", signature_};
|
||||
builder.single_input<math::Quaternion>("Quaternion");
|
||||
builder.single_output<float>("W");
|
||||
builder.single_output<float>("X");
|
||||
builder.single_output<float>("Y");
|
||||
builder.single_output<float>("Z");
|
||||
this->set_signature(&signature_);
|
||||
}
|
||||
|
||||
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArraySpan<math::Quaternion> quats = params.readonly_single_input<math::Quaternion>(
|
||||
0, "Quaternion");
|
||||
MutableSpan<float> w = params.uninitialized_single_output<float>(1, "W");
|
||||
MutableSpan<float> x = params.uninitialized_single_output<float>(2, "X");
|
||||
MutableSpan<float> y = params.uninitialized_single_output<float>(3, "Y");
|
||||
MutableSpan<float> z = params.uninitialized_single_output<float>(4, "Z");
|
||||
mask.foreach_index([&](const int64_t i) {
|
||||
const math::Quaternion quat = quats[i];
|
||||
w[i] = quat.w;
|
||||
x[i] = quat.x;
|
||||
y[i] = quat.y;
|
||||
z[i] = quat.z;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static SeparateQuaternionFunction fn;
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(
|
||||
&ntype, FN_NODE_ROTATION_TO_QUATERNION, "Rotation to Quaternion", NODE_CLASS_CONVERTER);
|
||||
ntype.declare = node_declare;
|
||||
ntype.build_multi_function = node_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(node_register)
|
||||
|
||||
} // namespace blender::nodes::node_fn_rotation_to_quaternion_cc
|
Loading…
Reference in New Issue