WIP: Geometry Nodes: Rotation type #107954

Closed
Hans Goudey wants to merge 4 commits from HooglyBoogly:geometry-nodes-rotation-type into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
8 changed files with 226 additions and 0 deletions
Showing only changes of commit e3c2f57099 - Show all commits

View File

@ -550,7 +550,9 @@ 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, "FunctionNodeCombineRotation")
node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler")
node_add_menu.add_node_type(layout, "FunctionNodeSeparateRotation")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)

View File

@ -1337,6 +1337,8 @@ 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_COMBINE_ROTATION 1223
#define FN_NODE_SEPARATE_ROTATION 1224
/** \} */

View File

@ -266,6 +266,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI
DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, def_fn_align_euler_to_vector, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler to Vector", "")
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
DefNode(FunctionNode, FN_NODE_COMBINE_COLOR, def_fn_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "")
DefNode(FunctionNode, FN_NODE_COMBINE_ROTATION, def_fn_combine_rotation, "COMBINE_ROTATION", CombineRotation, "Combine Rotation", "")
DefNode(FunctionNode, FN_NODE_COMPARE, def_compare, "COMPARE", Compare, "Compare", "")
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", "")
@ -278,6 +279,7 @@ DefNode(FunctionNode, FN_NODE_RANDOM_VALUE, def_fn_random_value, "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_SEPARATE_COLOR, def_fn_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "")
DefNode(FunctionNode, FN_NODE_SEPARATE_ROTATION, def_fn_separate_rotation, "SEPARATE_ROTATION", SeparateRotation, "Separate Rotation", "")
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", "")

View File

@ -24,6 +24,7 @@ set(SRC
nodes/node_fn_align_euler_to_vector.cc
nodes/node_fn_boolean_math.cc
nodes/node_fn_combine_color.cc
nodes/node_fn_combine_rotation.cc
nodes/node_fn_compare.cc
nodes/node_fn_float_to_int.cc
nodes/node_fn_input_bool.cc
@ -36,6 +37,7 @@ set(SRC
nodes/node_fn_replace_string.cc
nodes/node_fn_rotate_euler.cc
nodes/node_fn_separate_color.cc
nodes/node_fn_separate_rotation.cc
nodes/node_fn_slice_string.cc
nodes/node_fn_string_length.cc
nodes/node_fn_value_to_string.cc

View File

@ -11,6 +11,7 @@ void register_function_nodes()
register_node_type_fn_align_euler_to_vector();
register_node_type_fn_boolean_math();
register_node_type_fn_combine_color();
register_node_type_fn_combine_rotation();
register_node_type_fn_compare();
register_node_type_fn_float_to_int();
register_node_type_fn_input_bool();
@ -23,6 +24,7 @@ void register_function_nodes()
register_node_type_fn_replace_string();
register_node_type_fn_rotate_euler();
register_node_type_fn_separate_color();
register_node_type_fn_separate_rotation();
register_node_type_fn_slice_string();
register_node_type_fn_string_length();
register_node_type_fn_value_to_string();

View File

@ -7,6 +7,7 @@
void register_node_type_fn_align_euler_to_vector();
void register_node_type_fn_boolean_math();
void register_node_type_fn_combine_color();
void register_node_type_fn_combine_rotation();
void register_node_type_fn_compare();
void register_node_type_fn_float_to_int();
void register_node_type_fn_input_bool();
@ -19,6 +20,7 @@ void register_node_type_fn_random_value();
void register_node_type_fn_replace_string();
void register_node_type_fn_rotate_euler();
void register_node_type_fn_separate_color();
void register_node_type_fn_separate_rotation();
void register_node_type_fn_slice_string();
void register_node_type_fn_string_length();
void register_node_type_fn_value_to_string();

View File

@ -0,0 +1,96 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_math_axis_angle.hh"
#include "BLI_math_euler.hh"
#include "UI_interface.h"
#include "UI_resources.h"
#include "node_function_util.hh"
namespace blender::nodes::node_fn_combine_rotation_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.is_function_node();
b.add_input<decl::Vector>(N_("Euler")).subtype(PROP_EULER).make_available([](bNode &node) {
node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ;
});
b.add_input<decl::Vector>(N_("Axis"))
.default_value({0.0f, 0.0f, 1.0f})
.make_available(
[](bNode &node) { node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE; });
b.add_input<decl::Float>(N_("Angle")).subtype(PROP_ANGLE).make_available([](bNode &node) {
node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE;
});
b.add_output<decl::Rotation>(N_("Rotation"));
};
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
node->custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ;
}
static void node_update(bNodeTree *tree, bNode *node)
{
bke::nodeSetSocketAvailability(tree,
static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 0)),
node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ);
bke::nodeSetSocketAvailability(tree,
static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1)),
node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE);
bke::nodeSetSocketAvailability(tree,
static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2)),
node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE);
}
static const mf::MultiFunction *get_multi_function(const bNode &bnode)
{
const auto mode = NodeCombineSeparateRotatioNMode(bnode.custom1);
static auto euler_xyz_fn = mf::build::SI1_SO<float3, math::Quaternion>(
"Euler XYZ to Quaternion",
[](float3 euler) { return math::to_quaternion(math::EulerXYZ(euler)); });
static auto axis_angle_fn = mf::build::SI2_SO<float3, float, math::Quaternion>(
"Axis Angle to Quaternion", [](float3 axis, float angle) {
return math::normalize(math::to_quaternion(math::AxisAngle(math::normalize(axis), angle)));
});
switch (mode) {
case NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ:
return &euler_xyz_fn;
case NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE:
return &axis_angle_fn;
}
BLI_assert_unreachable();
return nullptr;
}
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{
const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn);
}
} // namespace blender::nodes::node_fn_combine_rotation_cc
void register_node_type_fn_combine_rotation(void)
{
namespace file_ns = blender::nodes::node_fn_combine_rotation_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_COMBINE_ROTATION, "Combine Rotation", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::node_declare;
ntype.initfunc = file_ns::node_init;
ntype.updatefunc = file_ns::node_update;
ntype.build_multi_function = file_ns::node_build_multi_function;
ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}

View File

@ -0,0 +1,118 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_math_axis_angle.hh"
#include "BLI_math_euler.hh"
#include "UI_interface.h"
#include "UI_resources.h"
#include "node_function_util.hh"
namespace blender::nodes::node_fn_separate_rotation_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.is_function_node();
b.add_input<decl::Rotation>(N_("Rotation"));
b.add_output<decl::Vector>(N_("Euler")).subtype(PROP_EULER).make_available([](bNode &node) {
node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ;
});
b.add_output<decl::Vector>(N_("Axis")).make_available([](bNode &node) {
node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE;
});
b.add_output<decl::Float>(N_("Angle")).subtype(PROP_ANGLE).make_available([](bNode &node) {
node.custom1 = NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE;
});
};
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
node->custom1 = NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ;
}
static void node_update(bNodeTree *tree, bNode *node)
{
bke::nodeSetSocketAvailability(tree,
static_cast<bNodeSocket *>(BLI_findlink(&node->outputs, 0)),
node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ);
bke::nodeSetSocketAvailability(tree,
static_cast<bNodeSocket *>(BLI_findlink(&node->outputs, 1)),
node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE);
bke::nodeSetSocketAvailability(tree,
static_cast<bNodeSocket *>(BLI_findlink(&node->outputs, 2)),
node->custom1 == NODE_COMBINE_SEPARATE_ROTATION_AXIS_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>(2, "Axis");
MutableSpan<float> angles = params.uninitialized_single_output<float>(3, "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 const mf::MultiFunction *get_multi_function(const bNode &bnode)
{
const auto mode = NodeCombineSeparateRotatioNMode(bnode.custom1);
static auto euler_xyz_fn = mf::build::SI1_SO<math::Quaternion, float3>(
"Quaternion to Euler XYZ",
[](const math::Quaternion quaternion) { return math::to_euler(quaternion); });
static QuaterniontoAxisAngleFunction axis_angle_fn;
switch (mode) {
case NODE_COMBINE_SEPARATE_ROTATION_EULER_XYZ:
return &euler_xyz_fn;
case NODE_COMBINE_SEPARATE_ROTATION_AXIS_ANGLE:
return &axis_angle_fn;
}
BLI_assert_unreachable();
return nullptr;
}
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{
const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn);
}
} // namespace blender::nodes::node_fn_separate_rotation_cc
void register_node_type_fn_separate_rotation(void)
{
namespace file_ns = blender::nodes::node_fn_separate_rotation_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_SEPARATE_ROTATION, "Separate Rotation", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::node_declare;
ntype.initfunc = file_ns::node_init;
ntype.updatefunc = file_ns::node_update;
ntype.build_multi_function = file_ns::node_build_multi_function;
ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}