Geometry Nodes: Add Rotate Euler Node
This commit introduces the Rotate Euler function node which modifies an input euler rotation. The node replaces the "Point Rotate" node. Addresses T91375. Differential Revision: https://developer.blender.org/D12531
This commit is contained in:
parent
34cf33eb12
commit
c5c94e3eae
|
@ -624,6 +624,7 @@ geometry_node_categories = [
|
|||
NodeItem("ShaderNodeClamp"),
|
||||
NodeItem("ShaderNodeMath"),
|
||||
NodeItem("FunctionNodeBooleanMath"),
|
||||
NodeItem("FunctionNodeRotateEuler"),
|
||||
NodeItem("FunctionNodeFloatCompare"),
|
||||
NodeItem("FunctionNodeFloatToInt"),
|
||||
NodeItem("GeometryNodeSwitch"),
|
||||
|
|
|
@ -1529,6 +1529,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
|||
#define FN_NODE_STRING_SUBSTRING 1212
|
||||
#define FN_NODE_INPUT_SPECIAL_CHARACTERS 1213
|
||||
#define FN_NODE_RANDOM_VALUE 1214
|
||||
#define FN_NODE_ROTATE_EULER 1215
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -5824,6 +5824,7 @@ static void registerFunctionNodes()
|
|||
register_node_type_fn_input_string();
|
||||
register_node_type_fn_input_vector();
|
||||
register_node_type_fn_random_value();
|
||||
register_node_type_fn_rotate_euler();
|
||||
register_node_type_fn_string_length();
|
||||
register_node_type_fn_string_substring();
|
||||
register_node_type_fn_value_to_string();
|
||||
|
|
|
@ -2032,6 +2032,11 @@ typedef enum GeometryNodeRotatePointsType {
|
|||
GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE = 1,
|
||||
} GeometryNodeRotatePointsType;
|
||||
|
||||
typedef enum FunctionNodeRotatePointsType {
|
||||
FN_NODE_ROTATE_EULER_TYPE_EULER = 0,
|
||||
FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE = 1,
|
||||
} FunctionNodeRotatePointsType;
|
||||
|
||||
typedef enum GeometryNodeAttributeVectorRotateMode {
|
||||
GEO_NODE_VECTOR_ROTATE_TYPE_AXIS = 0,
|
||||
GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X = 1,
|
||||
|
@ -2052,6 +2057,11 @@ typedef enum GeometryNodeRotatePointsSpace {
|
|||
GEO_NODE_POINT_ROTATE_SPACE_POINT = 1,
|
||||
} GeometryNodeRotatePointsSpace;
|
||||
|
||||
typedef enum FunctionNodeRotateEulerSpace {
|
||||
FN_NODE_ROTATE_EULER_SPACE_OBJECT = 0,
|
||||
FN_NODE_ROTATE_EULER_SPACE_POINT = 1,
|
||||
} FunctionNodeRotateEulerSpace;
|
||||
|
||||
typedef enum GeometryNodeAlignRotationToVectorAxis {
|
||||
GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_X = 0,
|
||||
GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_Y = 1,
|
||||
|
|
|
@ -9818,6 +9818,51 @@ static void def_geo_point_rotate(StructRNA *srna)
|
|||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static void def_fn_rotate_euler(StructRNA *srna)
|
||||
{
|
||||
static const EnumPropertyItem type_items[] = {
|
||||
{FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE,
|
||||
"AXIS_ANGLE",
|
||||
ICON_NONE,
|
||||
"Axis Angle",
|
||||
"Rotate around an axis by an angle"},
|
||||
{FN_NODE_ROTATE_EULER_TYPE_EULER,
|
||||
"EULER",
|
||||
ICON_NONE,
|
||||
"Euler",
|
||||
"Rotate around the X, Y, and Z axes"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem space_items[] = {
|
||||
{FN_NODE_ROTATE_EULER_SPACE_OBJECT,
|
||||
"OBJECT",
|
||||
ICON_NONE,
|
||||
"Object",
|
||||
"Rotate the input rotation in the local space of the object"},
|
||||
{FN_NODE_ROTATE_EULER_SPACE_POINT,
|
||||
"POINT",
|
||||
ICON_NONE,
|
||||
"Point",
|
||||
"Rotate the input rotation in its local space"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||
RNA_def_property_enum_items(prop, type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "Method used to describe the rotation");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
|
||||
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "custom2");
|
||||
RNA_def_property_enum_items(prop, space_items);
|
||||
RNA_def_property_ui_text(prop, "Space", "Base orientation of the points");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_geo_align_rotation_to_vector(StructRNA *srna)
|
||||
{
|
||||
static const EnumPropertyItem axis_items[] = {
|
||||
|
|
|
@ -142,6 +142,7 @@ set(SRC
|
|||
function/nodes/node_fn_input_string.cc
|
||||
function/nodes/node_fn_input_vector.cc
|
||||
function/nodes/node_fn_random_value.cc
|
||||
function/nodes/node_fn_rotate_euler.cc
|
||||
function/nodes/node_fn_string_length.cc
|
||||
function/nodes/node_fn_string_substring.cc
|
||||
function/nodes/node_fn_value_to_string.cc
|
||||
|
|
|
@ -29,6 +29,7 @@ void register_node_type_fn_input_special_characters(void);
|
|||
void register_node_type_fn_input_string(void);
|
||||
void register_node_type_fn_input_vector(void);
|
||||
void register_node_type_fn_random_value(void);
|
||||
void register_node_type_fn_rotate_euler(void);
|
||||
void register_node_type_fn_string_length(void);
|
||||
void register_node_type_fn_string_substring(void);
|
||||
void register_node_type_fn_value_to_string(void);
|
||||
|
|
|
@ -272,9 +272,10 @@ DefNode(FunctionNode, FN_NODE_INPUT_SPECIAL_CHARACTERS, 0, "INPUT_SPECIAL_CHARAC
|
|||
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_RANDOM_VALUE, def_fn_random_value, "RANDOM_VALUE", RandomValue, "Random Value", "")
|
||||
DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
|
||||
DefNode(FunctionNode, FN_NODE_ROTATE_EULER, def_fn_rotate_euler, "ROTATE_EULER", RotateEuler, "Rotate Euler", "")
|
||||
DefNode(FunctionNode, FN_NODE_STRING_LENGTH, 0, "STRING_LENGTH", StringLength, "String Length", "")
|
||||
DefNode(FunctionNode, FN_NODE_STRING_SUBSTRING, 0, "STRING_SUBSTRING", StringSubstring, "String Substring", "")
|
||||
DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
|
||||
|
||||
DefNode(GeometryNode, GEO_NODE_LEGACY_ALIGN_ROTATION_TO_VECTOR, def_geo_align_rotation_to_vector, "LEGACY_ALIGN_ROTATION_TO_VECTOR", LegacyAlignRotationToVector, "Align Rotation to Vector", "")
|
||||
DefNode(GeometryNode, GEO_NODE_LEGACY_ATTRIBUTE_CLAMP, def_geo_attribute_clamp, "LEGACY_ATTRIBUTE_CLAMP", LegacyAttributeClamp, "Attribute Clamp", "")
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "node_function_util.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
static void fn_node_rotate_euler_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.is_function_node();
|
||||
b.add_input<decl::Vector>("Rotation").subtype(PROP_EULER).hide_value();
|
||||
b.add_input<decl::Vector>("Rotate By").subtype(PROP_EULER);
|
||||
b.add_input<decl::Vector>("Axis").default_value({0.0, 0.0, 1.0}).subtype(PROP_XYZ);
|
||||
b.add_input<decl::Float>("Angle").subtype(PROP_ANGLE);
|
||||
b.add_output<decl::Vector>("Rotation");
|
||||
};
|
||||
|
||||
static void fn_node_rotate_euler_update(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
bNodeSocket *rotate_by_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 1));
|
||||
bNodeSocket *axis_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 2));
|
||||
bNodeSocket *angle_socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, 3));
|
||||
|
||||
nodeSetSocketAvailability(rotate_by_socket,
|
||||
ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_EULER));
|
||||
nodeSetSocketAvailability(axis_socket,
|
||||
ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
|
||||
nodeSetSocketAvailability(angle_socket,
|
||||
ELEM(node->custom1, FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE));
|
||||
}
|
||||
|
||||
static void fn_node_rotate_euler_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
||||
uiItemR(layout, ptr, "space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static const fn::MultiFunction *get_multi_function(bNode &bnode)
|
||||
{
|
||||
static fn::CustomMF_SI_SI_SO<float3, float3, float3> obj_euler_rot{
|
||||
"Rotate Euler by Euler/Object", [](const float3 &input, const float3 &rotation) {
|
||||
float input_mat[3][3];
|
||||
eul_to_mat3(input_mat, input);
|
||||
float rot_mat[3][3];
|
||||
eul_to_mat3(rot_mat, rotation);
|
||||
float mat_res[3][3];
|
||||
mul_m3_m3m3(mat_res, rot_mat, input_mat);
|
||||
float3 result;
|
||||
mat3_to_eul(result, mat_res);
|
||||
return result;
|
||||
}};
|
||||
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> obj_AA_rot{
|
||||
"Rotate Euler by AxisAngle/Object",
|
||||
[](const float3 &input, const float3 &axis, float angle) {
|
||||
float input_mat[3][3];
|
||||
eul_to_mat3(input_mat, input);
|
||||
float rot_mat[3][3];
|
||||
axis_angle_to_mat3(rot_mat, axis, angle);
|
||||
float mat_res[3][3];
|
||||
mul_m3_m3m3(mat_res, rot_mat, input_mat);
|
||||
float3 result;
|
||||
mat3_to_eul(result, mat_res);
|
||||
return result;
|
||||
}};
|
||||
static fn::CustomMF_SI_SI_SO<float3, float3, float3> point_euler_rot{
|
||||
"Rotate Euler by Euler/Point", [](const float3 &input, const float3 &rotation) {
|
||||
float input_mat[3][3];
|
||||
eul_to_mat3(input_mat, input);
|
||||
float rot_mat[3][3];
|
||||
eul_to_mat3(rot_mat, rotation);
|
||||
float mat_res[3][3];
|
||||
mul_m3_m3m3(mat_res, input_mat, rot_mat);
|
||||
float3 result;
|
||||
mat3_to_eul(result, mat_res);
|
||||
return result;
|
||||
}};
|
||||
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> point_AA_rot{
|
||||
"Rotate Euler by AxisAngle/Point", [](const float3 &input, const float3 &axis, float angle) {
|
||||
float input_mat[3][3];
|
||||
eul_to_mat3(input_mat, input);
|
||||
float rot_mat[3][3];
|
||||
axis_angle_to_mat3(rot_mat, axis, angle);
|
||||
float mat_res[3][3];
|
||||
mul_m3_m3m3(mat_res, input_mat, rot_mat);
|
||||
float3 result;
|
||||
mat3_to_eul(result, mat_res);
|
||||
return result;
|
||||
}};
|
||||
short type = bnode.custom1;
|
||||
short space = bnode.custom2;
|
||||
if (type == FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE) {
|
||||
return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? &obj_AA_rot : &point_AA_rot;
|
||||
}
|
||||
if (type == FN_NODE_ROTATE_EULER_TYPE_EULER) {
|
||||
return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? &obj_euler_rot : &point_euler_rot;
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void fn_node_rotate_euler_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
void register_node_type_fn_rotate_euler()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
fn_node_type_base(&ntype, FN_NODE_ROTATE_EULER, "Rotate Euler", NODE_CLASS_CONVERTER, 0);
|
||||
ntype.declare = blender::nodes::fn_node_rotate_euler_declare;
|
||||
ntype.draw_buttons = blender::nodes::fn_node_rotate_euler_layout;
|
||||
node_type_update(&ntype, blender::nodes::fn_node_rotate_euler_update);
|
||||
ntype.build_multi_function = blender::nodes::fn_node_rotate_euler_build_multi_function;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Loading…
Reference in New Issue