WIP: Geometry Nodes: Rotation type #107954
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -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", "")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue