Matrix operations and sockets for geometry nodes #105408

Closed
Lukas Tönne wants to merge 37 commits from LukasTonne/blender:nodes-matrix-types into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
10 changed files with 603 additions and 206 deletions
Showing only changes of commit 726ad272aa - Show all commits

View File

@ -1567,10 +1567,10 @@ struct TexResult;
#define FN_NODE_INPUT_INT 1220
#define FN_NODE_SEPARATE_COLOR 1221
#define FN_NODE_COMBINE_COLOR 1222
#define FN_NODE_INPUT_MATRIX 1223
#define FN_NODE_SEPARATE_MATRIX 1224
#define FN_NODE_COMBINE_MATRIX 1225
#define FN_NODE_MATRIX_MATH 1226
#define FN_NODE_INPUT_MATRIX_4X4 1223
#define FN_NODE_SEPARATE_MATRIX_4X4 1224
#define FN_NODE_COMBINE_MATRIX_4X4 1225
#define FN_NODE_MATRIX_4X4_MATH 1226
/** \} */

View File

@ -1599,6 +1599,14 @@ typedef struct NodeShaderMix {
char _pad[3];
} NodeShaderMix;
typedef struct NodeInputMatrix {
float vec0[3];
float vec1[3];
float vec2[3];
float vec3[3];
float elements[4][4];
} NodeInputMatrix;
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
@ -1873,6 +1881,20 @@ typedef enum NodeVectorMathOperation {
NODE_VECTOR_MATH_MULTIPLY_ADD = 26,
} NodeVectorMathOperation;
typedef enum NodeMatrixMathOperation {
NODE_MATRIX_MATH_ADD = 0,
NODE_MATRIX_MATH_SUBTRACT = 1,
NODE_MATRIX_MATH_SCALAR_MULTIPLY = 2,
NODE_MATRIX_MATH_MULTIPLY = 3,
NODE_MATRIX_MATH_TRANSPOSE = 4,
NODE_MATRIX_MATH_INVERSE = 5,
NODE_MATRIX_MATH_DETERMINANT = 6,
NODE_MATRIX_MATH_TRACE = 7,
NODE_MATRIX_MATH_IS_SYMMETRIC = 8,
NODE_MATRIX_MATH_IS_ANTI_SYMMETRIC = 9,
NODE_MATRIX_MATH_IS_ORTHOGONAL = 10,
} NodeMatrixMathOperation;
typedef enum NodeBooleanMathOperation {
NODE_BOOLEAN_MATH_AND = 0,
NODE_BOOLEAN_MATH_OR = 1,
@ -2367,3 +2389,9 @@ typedef enum NodeCombSepColorMode {
NODE_COMBSEP_COLOR_HSV = 1,
NODE_COMBSEP_COLOR_HSL = 2,
} NodeCombSepColorMode;
typedef enum NodeCombSepMatrixMode {
NODE_COMBSEP_MATRIX_COLUMNS = 0,
NODE_COMBSEP_MATRIX_ROWS = 1,
NODE_COMBSEP_MATRIX_ELEMENTS = 2,
} NodeCombSepMatrixMode;

View File

@ -294,6 +294,24 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = {
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_node_matrix_math_items[] = {
{NODE_MATRIX_MATH_ADD, "ADD", 0, "Add", ""},
{NODE_MATRIX_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", ""},
{NODE_MATRIX_MATH_SCALAR_MULTIPLY, "SCALAR_MULTIPLY", 0, "Scalar Multiply", ""},
{NODE_MATRIX_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", ""},
RNA_ENUM_ITEM_SEPR,
{NODE_MATRIX_MATH_TRANSPOSE, "TRANSPOSE", 0, "Transpose", ""},
{NODE_MATRIX_MATH_INVERSE, "INVERSE", 0, "Inverse", ""},
RNA_ENUM_ITEM_SEPR,
{NODE_MATRIX_MATH_DETERMINANT, "DETERMINANT", 0, "Determinant", ""},
{NODE_MATRIX_MATH_TRACE, "TRACE", 0, "Trace", ""},
RNA_ENUM_ITEM_SEPR,
{NODE_MATRIX_MATH_IS_SYMMETRIC, "IS_SYMMETRIC", 0, "Is Symmetric", ""},
{NODE_MATRIX_MATH_IS_ANTI_SYMMETRIC, "IS_ANTI_SYMMETRIC", 0, "Is Anti-Symmetric", ""},
{NODE_MATRIX_MATH_IS_ORTHOGONAL, "IS_ORTHOGONAL", 0, "Is Orthogonal", ""},
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_node_boolean_math_items[] = {
{NODE_BOOLEAN_MATH_AND, "AND", 0, "And", "True when both inputs are true"},
{NODE_BOOLEAN_MATH_OR, "OR", 0, "Or", "True when at least one input is true"},
@ -505,6 +523,13 @@ static const EnumPropertyItem rna_node_combsep_color_items[] = {
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem rna_node_combsep_matrix_items[] = {
{NODE_COMBSEP_MATRIX_COLUMNS, "COLUMNS", ICON_NONE, "Columns", "Use vectors as matrix columns"},
{NODE_COMBSEP_MATRIX_ROWS, "ROWS", ICON_NONE, "Rows", "Use vectors as matrix rows"},
{NODE_COMBSEP_MATRIX_ELEMENTS, "ELEMENTS", ICON_NONE, "Elements", "Use individual matrix elements"},
{0, NULL, 0, NULL, NULL},
};
#ifndef RNA_RUNTIME
static const EnumPropertyItem node_sampler_type_items[] = {
{0, "NEAREST", 0, "Nearest", ""},
@ -5179,6 +5204,91 @@ static void def_fn_combsep_color(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
static void def_fn_input_matrix_4x4(StructRNA *srna)
{
static const float default_vec0[] = {1.0f, 0.0f, 0.0f};
static const float default_vec1[] = {0.0f, 1.0f, 0.0f};
static const float default_vec2[] = {0.0f, 0.0f, 1.0f};
static const float default_elements[] = {
1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
};
PropertyRNA *prop;
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_node_combsep_matrix_items);
RNA_def_property_ui_text(prop, "Mode", "Mode of matrix composition");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
RNA_def_struct_sdna_from(srna, "NodeInputInt", "storage");
RNA_def_struct_sdna_from(srna, "NodeInputMatrix", "storage");
prop = RNA_def_property(srna, "vec0", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vec0");
RNA_def_property_array(prop, 3);
RNA_def_property_float_array_default(prop, default_vec0);
RNA_def_property_ui_text(prop, "Vector 0", "Row or column vector");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "vec1", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vec1");
RNA_def_property_array(prop, 3);
RNA_def_property_float_array_default(prop, default_vec0);
RNA_def_property_ui_text(prop, "Vector 1", "Row or column vector");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "vec2", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vec2");
RNA_def_property_array(prop, 3);
RNA_def_property_float_array_default(prop, default_vec0);
RNA_def_property_ui_text(prop, "Vector 2", "Row or column vector");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "elements", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "elements");
RNA_def_property_array(prop, 16);
RNA_def_property_float_array_default(prop, default_elements);
RNA_def_property_ui_text(prop, "Integer", "Input value used for unconnected socket");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_fn_combsep_matrix(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_node_combsep_matrix_items);
RNA_def_property_ui_text(prop, "Mode", "Mode of matrix composition");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
static void def_fn_matrix_4x4_math(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_node_matrix_math_items);
RNA_def_property_ui_text(prop, "Operation", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
}
/* -- Shader Nodes ---------------------------------------------------------- */
static void def_sh_output(StructRNA *srna)

View File

@ -279,10 +279,10 @@ DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, def_fn_combsep_color, "SEPARATE_CO
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", "")
DefNode(FunctionNode, FN_NODE_INPUT_MATRIX, 0, "INPUT_MATRIX", InputMatrix, "Matrix", "")
DefNode(FunctionNode, FN_NODE_SEPARATE_MATRIX, 0, "SEPARATE_MATRIX", SeparateMatrix, "Separate Matrix", "")
DefNode(FunctionNode, FN_NODE_COMBINE_MATRIX, 0, "COMBINE_MATRIX", CombineMatrix, "Combine Matrix", "")
DefNode(FunctionNode, FN_NODE_MATRIX_MATH, 0, "MATRIX_MATH", MatrixMath, "Matrix Math", "")
DefNode(FunctionNode, FN_NODE_INPUT_MATRIX_4X4, def_fn_input_matrix_4x4, "INPUT_MATRIX_4X4", InputMatrix, "4x4 Matrix", "")
DefNode(FunctionNode, FN_NODE_SEPARATE_MATRIX_4X4, def_fn_combsep_matrix, "SEPARATE_MATRIX_4X4", SeparateMatrix, "Separate 4x4 Matrix", "")
DefNode(FunctionNode, FN_NODE_COMBINE_MATRIX_4X4, def_fn_combsep_matrix, "COMBINE_MATRIX_4X4", CombineMatrix, "Combine 4x4 Matrix", "")
DefNode(FunctionNode, FN_NODE_MATRIX_4X4_MATH, def_fn_matrix_4x4_math, "MATRIX_4X4_MATH", MatrixMath, "4x4 Matrix Math", "")
DefNode(GeometryNode, GEO_NODE_ACCUMULATE_FIELD, def_geo_accumulate_field, "ACCUMULATE_FIELD", AccumulateField, "Accumulate Field", "Add the values of an evaluated field together and output the running total for each element")
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_DOMAIN_SIZE, def_geo_attribute_domain_size, "ATTRIBUTE_DOMAIN_SIZE", AttributeDomainSize, "Domain Size", "Retrieve the number of elements in a geometry for each attribute domain")

View File

@ -9,18 +9,22 @@ 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_matrix_4x4();
register_node_type_fn_compare();
register_node_type_fn_float_to_int();
register_node_type_fn_input_bool();
register_node_type_fn_input_color();
register_node_type_fn_input_int();
register_node_type_fn_input_matrix_4x4();
register_node_type_fn_input_special_characters();
register_node_type_fn_input_string();
register_node_type_fn_input_vector();
register_node_type_fn_matrix_4x4_math();
register_node_type_fn_random_value();
register_node_type_fn_replace_string();
register_node_type_fn_rotate_euler();
register_node_type_fn_separate_color();
register_node_type_fn_separate_matrix_4x4();
register_node_type_fn_slice_string();
register_node_type_fn_string_length();
register_node_type_fn_value_to_string();

View File

@ -5,18 +5,22 @@
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_matrix_4x4();
void register_node_type_fn_compare();
void register_node_type_fn_float_to_int();
void register_node_type_fn_input_bool();
void register_node_type_fn_input_color();
void register_node_type_fn_input_int();
void register_node_type_fn_input_matrix_4x4();
void register_node_type_fn_input_special_characters();
void register_node_type_fn_input_string();
void register_node_type_fn_input_vector();
void register_node_type_fn_matrix_4x4_math();
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_matrix_4x4();
void register_node_type_fn_slice_string();
void register_node_type_fn_string_length();
void register_node_type_fn_value_to_string();

View File

@ -5,30 +5,32 @@
#include "UI_interface.h"
#include "UI_resources.h"
namespace blender::nodes::node_fn_combine_color_cc {
NODE_STORAGE_FUNCS(NodeCombSepColor)
namespace blender::nodes::node_fn_combine_matrix4x4_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.is_function_node();
b.add_input<decl::Float>(N_("Red")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Green"))
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Blue"))
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Alpha"))
.default_value(1.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_output<decl::Color>(N_("Color"));
b.add_input<decl::Vector>(N_("Vec0")).default_value({1.0f, 0.0f, 0.0f});
b.add_input<decl::Vector>(N_("Vec1")).default_value({0.0f, 1.0f, 0.0f});
b.add_input<decl::Vector>(N_("Vec2")).default_value({0.0f, 0.0f, 1.0f});
b.add_input<decl::Vector>(N_("Vec3")).default_value({0.0f, 0.0f, 0.0f});
b.add_input<decl::Float>(N_("Row 0 Col 0")).default_value(1.0f);
b.add_input<decl::Float>(N_("Row 1 Col 0")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 2 Col 0")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 3 Col 0")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 0 Col 1")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 1 Col 1")).default_value(1.0f);
b.add_input<decl::Float>(N_("Row 2 Col 1")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 3 Col 1")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 0 Col 2")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 1 Col 2")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 2 Col 2")).default_value(1.0f);
b.add_input<decl::Float>(N_("Row 3 Col 2")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 0 Col 3")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 1 Col 3")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 2 Col 3")).default_value(0.0f);
b.add_input<decl::Float>(N_("Row 3 Col 3")).default_value(1.0f);
b.add_output<decl::Matrix4x4>(N_("Matrix"));
};
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -36,47 +38,137 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
static void node_update(bNodeTree * /*tree*/, bNode *node)
static void node_update(bNodeTree *tree, bNode *node)
{
const NodeCombSepColor &storage = node_storage(*node);
node_combsep_color_label(&node->inputs, (NodeCombSepColorMode)storage.mode);
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)node->custom1;
const IndexRange vector_sockets(0, 4);
const IndexRange scalar_sockets(4, 16);
const bool show_vector_sockets = ELEM(
mode, NODE_COMBSEP_MATRIX_COLUMNS, NODE_COMBSEP_MATRIX_ROWS);
const bool show_scalar_sockets = ELEM(mode, NODE_COMBSEP_MATRIX_ELEMENTS);
for (const int i : vector_sockets) {
nodeSetSocketAvailability(tree, &node->input_socket(i), show_vector_sockets);
}
for (const int i : scalar_sockets) {
nodeSetSocketAvailability(tree, &node->input_socket(i), show_scalar_sockets);
}
switch (mode) {
case NODE_COMBSEP_MATRIX_COLUMNS:
node_sock_label(&node->input_socket(vector_sockets[0]), "Column 0");
node_sock_label(&node->input_socket(vector_sockets[1]), "Column 1");
node_sock_label(&node->input_socket(vector_sockets[2]), "Column 2");
node_sock_label(&node->input_socket(vector_sockets[3]), "Column 3");
break;
case NODE_COMBSEP_MATRIX_ROWS:
node_sock_label(&node->input_socket(vector_sockets[0]), "Row 0");
node_sock_label(&node->input_socket(vector_sockets[1]), "Row 1");
node_sock_label(&node->input_socket(vector_sockets[2]), "Row 2");
node_sock_label(&node->input_socket(vector_sockets[3]), "Row 3");
break;
case NODE_COMBSEP_MATRIX_ELEMENTS:
break;
}
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeCombSepColor *data = MEM_cnew<NodeCombSepColor>(__func__);
data->mode = NODE_COMBSEP_COLOR_RGB;
node->storage = data;
node->custom1 = NODE_COMBSEP_MATRIX_COLUMNS;
}
static const fn::MultiFunction *get_multi_function(const bNode &bnode)
{
const NodeCombSepColor &storage = node_storage(bnode);
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)bnode.custom1;
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> rgba_fn{
"RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); }};
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsva_fn{
"HSV", [](float h, float s, float v, float a) {
ColorGeometry4f r_color;
hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b);
r_color.a = a;
return r_color;
}};
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsla_fn{
"HSL", [](float h, float s, float l, float a) {
ColorGeometry4f color;
hsl_to_rgb(h, s, l, &color.r, &color.g, &color.b);
color.a = a;
return color;
static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float3, float3, float4x4>
columns_to_matrix_fn{
"columns_to_matrix",
[](const float3 &c0, const float3 &c1, const float3 &c2, const float3 &c3) {
float4x4 m;
copy_v3_v3(m[0], c0);
m[0][3] = 0.0f;
copy_v3_v3(m[1], c1);
m[1][3] = 0.0f;
copy_v3_v3(m[2], c2);
m[2][3] = 0.0f;
copy_v3_v3(m[3], c3);
m[3][3] = 1.0f;
return m;
}};
static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float3, float3, float4x4> rows_to_matrix_fn{
"rows_to_matrix",
[](const float3 &r0, const float3 &r1, const float3 &r2, const float3 &r3) {
float4x4 m;
m[0][0] = r0[0];
m[0][1] = r1[0];
m[0][2] = r2[0];
m[0][3] = 0.0f;
m[1][0] = r0[1];
m[1][1] = r1[1];
m[1][2] = r2[1];
m[1][3] = 0.0f;
m[2][0] = r0[2];
m[2][1] = r1[2];
m[2][2] = r2[2];
m[2][3] = 0.0f;
m[3][0] = r0[3];
m[3][1] = r1[3];
m[3][2] = r2[3];
m[3][3] = 1.0f;
return m;
}};
using Element = fn::MFParamTag<fn::MFParamCategory::SingleInput, float>;
using Matrix = fn::MFParamTag<fn::MFParamCategory::SingleOutput, float4x4>;
static fn::CustomMF<Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Element,
Matrix>
elements_to_matrix_fn{
"elements_to_matrix",
[](float m00,
float m01,
float m02,
float m03,
float m10,
float m11,
float m12,
float m13,
float m20,
float m21,
float m22,
float m23,
float m30,
float m31,
float m32,
float m33,
float4x4 &result) {
const float elements[] = {
m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33};
result = float4x4(elements);
}};
switch (storage.mode) {
case NODE_COMBSEP_COLOR_RGB:
return &rgba_fn;
case NODE_COMBSEP_COLOR_HSV:
return &hsva_fn;
case NODE_COMBSEP_COLOR_HSL:
return &hsla_fn;
switch (mode) {
case NODE_COMBSEP_MATRIX_COLUMNS:
return &columns_to_matrix_fn;
case NODE_COMBSEP_MATRIX_ROWS:
return &rows_to_matrix_fn;
case NODE_COMBSEP_MATRIX_ELEMENTS:
return &elements_to_matrix_fn;
}
BLI_assert_unreachable();
@ -89,20 +181,18 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
builder.set_matching_fn(fn);
}
} // namespace blender::nodes::node_fn_combine_color_cc
} // namespace blender::nodes::node_fn_combine_matrix4x4_cc
void register_node_type_fn_combine_color(void)
void register_node_type_fn_combine_matrix_4x4(void)
{
namespace file_ns = blender::nodes::node_fn_combine_color_cc;
namespace file_ns = blender::nodes::node_fn_combine_matrix4x4_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_CONVERTER);
fn_node_type_base(&ntype, FN_NODE_COMBINE_MATRIX_4X4, "Combine 4x4 Matrix", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::node_declare;
ntype.updatefunc = file_ns::node_update;
ntype.initfunc = file_ns::node_init;
node_type_storage(
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
ntype.build_multi_function = file_ns::node_build_multi_function;
ntype.draw_buttons = file_ns::node_layout;

View File

@ -5,104 +5,106 @@
#include "UI_interface.h"
#include "UI_resources.h"
namespace blender::nodes::node_fn_combine_color_cc {
namespace blender::nodes::node_fn_input_matrix4x4_cc {
NODE_STORAGE_FUNCS(NodeCombSepColor)
NODE_STORAGE_FUNCS(NodeInputMatrix);
static void node_declare(NodeDeclarationBuilder &b)
{
b.is_function_node();
b.add_input<decl::Float>(N_("Red")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Green"))
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Blue"))
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Alpha"))
.default_value(1.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_output<decl::Color>(N_("Color"));
b.add_output<decl::Matrix4x4>(N_("Matrix"));
};
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
const bNode *node = (const bNode *)ptr->data;
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)node->custom1;
static void node_update(bNodeTree * /*tree*/, bNode *node)
{
const NodeCombSepColor &storage = node_storage(*node);
node_combsep_color_label(&node->inputs, (NodeCombSepColorMode)storage.mode);
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
switch (mode) {
case NODE_COMBSEP_MATRIX_COLUMNS:
uiItemR(layout, ptr, "vec0", 0, "Column 0", ICON_NONE);
uiItemR(layout, ptr, "vec1", 0, "Column 1", ICON_NONE);
uiItemR(layout, ptr, "vec2", 0, "Column 2", ICON_NONE);
uiItemR(layout, ptr, "vec3", 0, "Column 3", ICON_NONE);
break;
case NODE_COMBSEP_MATRIX_ROWS:
uiItemR(layout, ptr, "vec0", 0, "Row 0", ICON_NONE);
uiItemR(layout, ptr, "vec1", 0, "Row 1", ICON_NONE);
uiItemR(layout, ptr, "vec2", 0, "Row 2", ICON_NONE);
uiItemR(layout, ptr, "vec3", 0, "Row 3", ICON_NONE);
break;
case NODE_COMBSEP_MATRIX_ELEMENTS:
uiItemR(layout, ptr, "elements", 0, "", ICON_NONE);
break;
}
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeCombSepColor *data = MEM_cnew<NodeCombSepColor>(__func__);
data->mode = NODE_COMBSEP_COLOR_RGB;
node->custom1 = NODE_COMBSEP_MATRIX_COLUMNS;
NodeInputMatrix *data = MEM_new<NodeInputMatrix>(__func__);
copy_v3_v3(data->vec0, float3(1.0f, 0.0f, 0.0f));
copy_v3_v3(data->vec1, float3(0.0f, 1.0f, 0.0f));
copy_v3_v3(data->vec2, float3(0.0f, 0.0f, 1.0f));
copy_v3_v3(data->vec3, float3(0.0f, 0.0f, 0.0f));
unit_m4(data->elements);
node->storage = data;
}
static const fn::MultiFunction *get_multi_function(const bNode &bnode)
{
const NodeCombSepColor &storage = node_storage(bnode);
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> rgba_fn{
"RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); }};
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsva_fn{
"HSV", [](float h, float s, float v, float a) {
ColorGeometry4f r_color;
hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b);
r_color.a = a;
return r_color;
}};
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsla_fn{
"HSL", [](float h, float s, float l, float a) {
ColorGeometry4f color;
hsl_to_rgb(h, s, l, &color.r, &color.g, &color.b);
color.a = a;
return color;
}};
switch (storage.mode) {
case NODE_COMBSEP_COLOR_RGB:
return &rgba_fn;
case NODE_COMBSEP_COLOR_HSV:
return &hsva_fn;
case NODE_COMBSEP_COLOR_HSL:
return &hsla_fn;
}
BLI_assert_unreachable();
return nullptr;
}
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{
const fn::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn);
const NodeInputMatrix &storage = node_storage(builder.node());
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)builder.node().custom1;
float4x4 matrix;
switch (mode) {
case NODE_COMBSEP_MATRIX_COLUMNS:
copy_v3_v3(matrix[0], storage.vec0);
matrix[0][3] = 0.0f;
copy_v3_v3(matrix[1], storage.vec1);
matrix[1][3] = 0.0f;
copy_v3_v3(matrix[2], storage.vec2);
matrix[2][3] = 0.0f;
copy_v3_v3(matrix[3], storage.vec3);
matrix[3][3] = 1.0f;
break;
case NODE_COMBSEP_MATRIX_ROWS:
matrix[0][0] = storage.vec0[0];
matrix[0][1] = storage.vec1[0];
matrix[0][2] = storage.vec2[0];
matrix[0][3] = 0.0f;
matrix[1][0] = storage.vec0[1];
matrix[1][1] = storage.vec1[1];
matrix[1][2] = storage.vec2[1];
matrix[1][3] = 0.0f;
matrix[2][0] = storage.vec0[2];
matrix[2][1] = storage.vec1[2];
matrix[2][2] = storage.vec2[2];
matrix[2][3] = 0.0f;
matrix[3][0] = storage.vec0[3];
matrix[3][1] = storage.vec1[3];
matrix[3][2] = storage.vec2[3];
matrix[3][3] = 1.0f;
break;
case NODE_COMBSEP_MATRIX_ELEMENTS:
matrix = float4x4(storage.elements);
break;
}
builder.construct_and_set_matching_fn<fn::CustomMF_Constant<float4x4>>(matrix);
}
} // namespace blender::nodes::node_fn_combine_color_cc
} // namespace blender::nodes::node_fn_input_matrix4x4_cc
void register_node_type_fn_combine_color(void)
void register_node_type_fn_input_matrix_4x4(void)
{
namespace file_ns = blender::nodes::node_fn_combine_color_cc;
namespace file_ns = blender::nodes::node_fn_input_matrix4x4_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_CONVERTER);
fn_node_type_base(&ntype, FN_NODE_INPUT_MATRIX_4X4, "4x4 Matrix", NODE_CLASS_INPUT);
ntype.declare = file_ns::node_declare;
ntype.updatefunc = file_ns::node_update;
ntype.initfunc = file_ns::node_init;
node_type_storage(
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
ntype.build_multi_function = file_ns::node_build_multi_function;
ntype.draw_buttons = file_ns::node_layout;

View File

@ -5,7 +5,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
namespace blender::nodes::node_fn_combine_color_cc {
namespace blender::nodes::node_fn_matrix4x4_math_cc {
NODE_STORAGE_FUNCS(NodeCombSepColor)
@ -89,20 +89,18 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
builder.set_matching_fn(fn);
}
} // namespace blender::nodes::node_fn_combine_color_cc
} // namespace blender::nodes::node_fn_matrix4x4_math_cc
void register_node_type_fn_combine_color(void)
void register_node_type_fn_matrix_4x4_math(void)
{
namespace file_ns = blender::nodes::node_fn_combine_color_cc;
namespace file_ns = blender::nodes::node_fn_matrix4x4_math_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_CONVERTER);
fn_node_type_base(&ntype, FN_NODE_MATRIX_4X4_MATH, "4x4 Matrix Math", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::node_declare;
ntype.updatefunc = file_ns::node_update;
ntype.initfunc = file_ns::node_init;
node_type_storage(
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
ntype.build_multi_function = file_ns::node_build_multi_function;
ntype.draw_buttons = file_ns::node_layout;

View File

@ -5,30 +5,32 @@
#include "UI_interface.h"
#include "UI_resources.h"
namespace blender::nodes::node_fn_combine_color_cc {
NODE_STORAGE_FUNCS(NodeCombSepColor)
namespace blender::nodes::node_fn_separate_matrix4x4_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.is_function_node();
b.add_input<decl::Float>(N_("Red")).default_value(0.0f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Green"))
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Blue"))
.default_value(0.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>(N_("Alpha"))
.default_value(1.0f)
.min(0.0f)
.max(1.0f)
.subtype(PROP_FACTOR);
b.add_output<decl::Color>(N_("Color"));
b.add_input<decl::Matrix4x4>(N_("Matrix")).default_value(float4x4::identity());
b.add_output<decl::Vector>(N_("Vec0"));
b.add_output<decl::Vector>(N_("Vec1"));
b.add_output<decl::Vector>(N_("Vec2"));
b.add_output<decl::Vector>(N_("Vec3"));
b.add_output<decl::Float>(N_("Row 0 Col 0"));
b.add_output<decl::Float>(N_("Row 1 Col 0"));
b.add_output<decl::Float>(N_("Row 2 Col 0"));
b.add_output<decl::Float>(N_("Row 3 Col 0"));
b.add_output<decl::Float>(N_("Row 0 Col 1"));
b.add_output<decl::Float>(N_("Row 1 Col 1"));
b.add_output<decl::Float>(N_("Row 2 Col 1"));
b.add_output<decl::Float>(N_("Row 3 Col 1"));
b.add_output<decl::Float>(N_("Row 0 Col 2"));
b.add_output<decl::Float>(N_("Row 1 Col 2"));
b.add_output<decl::Float>(N_("Row 2 Col 2"));
b.add_output<decl::Float>(N_("Row 3 Col 2"));
b.add_output<decl::Float>(N_("Row 0 Col 3"));
b.add_output<decl::Float>(N_("Row 1 Col 3"));
b.add_output<decl::Float>(N_("Row 2 Col 3"));
b.add_output<decl::Float>(N_("Row 3 Col 3"));
};
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
@ -36,73 +38,232 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
}
static void node_update(bNodeTree * /*tree*/, bNode *node)
static void node_update(bNodeTree *tree, bNode *node)
{
const NodeCombSepColor &storage = node_storage(*node);
node_combsep_color_label(&node->inputs, (NodeCombSepColorMode)storage.mode);
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)node->custom1;
const IndexRange vector_sockets(0, 4);
const IndexRange scalar_sockets(4, 16);
const bool show_vector_sockets = ELEM(
mode, NODE_COMBSEP_MATRIX_COLUMNS, NODE_COMBSEP_MATRIX_ROWS);
const bool show_scalar_sockets = ELEM(mode, NODE_COMBSEP_MATRIX_ELEMENTS);
for (const int i : vector_sockets) {
nodeSetSocketAvailability(tree, &node->output_socket(i), show_vector_sockets);
}
for (const int i : scalar_sockets) {
nodeSetSocketAvailability(tree, &node->output_socket(i), show_scalar_sockets);
}
switch (mode) {
case NODE_COMBSEP_MATRIX_COLUMNS:
node_sock_label(&node->output_socket(vector_sockets[0]), "Column 0");
node_sock_label(&node->output_socket(vector_sockets[1]), "Column 1");
node_sock_label(&node->output_socket(vector_sockets[2]), "Column 2");
node_sock_label(&node->output_socket(vector_sockets[3]), "Column 3");
break;
case NODE_COMBSEP_MATRIX_ROWS:
node_sock_label(&node->output_socket(vector_sockets[0]), "Row 0");
node_sock_label(&node->output_socket(vector_sockets[1]), "Row 1");
node_sock_label(&node->output_socket(vector_sockets[2]), "Row 2");
node_sock_label(&node->output_socket(vector_sockets[3]), "Row 3");
break;
case NODE_COMBSEP_MATRIX_ELEMENTS:
break;
}
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeCombSepColor *data = MEM_cnew<NodeCombSepColor>(__func__);
data->mode = NODE_COMBSEP_COLOR_RGB;
node->storage = data;
node->custom1 = NODE_COMBSEP_MATRIX_COLUMNS;
}
static const fn::MultiFunction *get_multi_function(const bNode &bnode)
{
const NodeCombSepColor &storage = node_storage(bnode);
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> rgba_fn{
"RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); }};
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsva_fn{
"HSV", [](float h, float s, float v, float a) {
ColorGeometry4f r_color;
hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b);
r_color.a = a;
return r_color;
}};
static fn::CustomMF_SI_SI_SI_SI_SO<float, float, float, float, ColorGeometry4f> hsla_fn{
"HSL", [](float h, float s, float l, float a) {
ColorGeometry4f color;
hsl_to_rgb(h, s, l, &color.r, &color.g, &color.b);
color.a = a;
return color;
}};
switch (storage.mode) {
case NODE_COMBSEP_COLOR_RGB:
return &rgba_fn;
case NODE_COMBSEP_COLOR_HSV:
return &hsva_fn;
case NODE_COMBSEP_COLOR_HSL:
return &hsla_fn;
class SeparateColumnsFunction : public fn::MultiFunction {
public:
SeparateColumnsFunction()
{
static fn::MFSignature signature = create_signature();
this->set_signature(&signature);
}
BLI_assert_unreachable();
return nullptr;
}
static fn::MFSignature create_signature()
{
fn::MFSignatureBuilder signature{"Separate Matrix 4x4"};
signature.single_input<float4x4>("Matrix");
signature.single_output<float3>("Column0");
signature.single_output<float3>("Column1");
signature.single_output<float3>("Column2");
signature.single_output<float3>("Column3");
return signature.build();
}
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override
{
const VArray<float4x4> &matrices = params.readonly_single_input<float4x4>(0, "Matrix");
MutableSpan<float3> col0 = params.uninitialized_single_output<float3>(1, "Column0");
MutableSpan<float3> col1 = params.uninitialized_single_output<float3>(2, "Column1");
MutableSpan<float3> col2 = params.uninitialized_single_output<float3>(3, "Column2");
MutableSpan<float3> col3 = params.uninitialized_single_output<float3>(4, "Column3");
for (int64_t i : mask) {
const float4x4 &mat = matrices[i];
col0[i] = float3(mat[0]);
col1[i] = float3(mat[1]);
col2[i] = float3(mat[2]);
col3[i] = float3(mat[3]);
}
}
};
class SeparateRowsFunction : public fn::MultiFunction {
public:
SeparateRowsFunction()
{
static fn::MFSignature signature = create_signature();
this->set_signature(&signature);
}
static fn::MFSignature create_signature()
{
fn::MFSignatureBuilder signature{"Separate Matrix 4x4"};
signature.single_input<float4x4>("Matrix");
signature.single_output<float3>("Row0");
signature.single_output<float3>("Row1");
signature.single_output<float3>("Row2");
signature.single_output<float3>("Row3");
return signature.build();
}
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override
{
const VArray<float4x4> &matrices = params.readonly_single_input<float4x4>(0, "Matrix");
MutableSpan<float3> row0 = params.uninitialized_single_output<float3>(1, "Row0");
MutableSpan<float3> row1 = params.uninitialized_single_output<float3>(2, "Row1");
MutableSpan<float3> row2 = params.uninitialized_single_output<float3>(3, "Row2");
MutableSpan<float3> row3 = params.uninitialized_single_output<float3>(4, "Row3");
for (int64_t i : mask) {
const float4x4 &mat = matrices[i];
row0[i] = float3(mat[0][0], mat[1][0], mat[2][0]);
row1[i] = float3(mat[0][1], mat[1][1], mat[2][1]);
row2[i] = float3(mat[0][2], mat[1][2], mat[2][2]);
row3[i] = float3(mat[0][3], mat[1][3], mat[2][3]);
}
}
};
class SeparateElementsFunction : public fn::MultiFunction {
public:
SeparateElementsFunction()
{
static fn::MFSignature signature = create_signature();
this->set_signature(&signature);
}
static fn::MFSignature create_signature()
{
fn::MFSignatureBuilder signature{"Separate Matrix 4x4"};
signature.single_input<float4x4>("Matrix");
signature.single_output<float>("Row0Column0");
signature.single_output<float>("Row0Column1");
signature.single_output<float>("Row0Column2");
signature.single_output<float>("Row0Column3");
signature.single_output<float>("Row1Column0");
signature.single_output<float>("Row1Column1");
signature.single_output<float>("Row1Column2");
signature.single_output<float>("Row1Column3");
signature.single_output<float>("Row2Column0");
signature.single_output<float>("Row2Column1");
signature.single_output<float>("Row2Column2");
signature.single_output<float>("Row2Column3");
signature.single_output<float>("Row3Column0");
signature.single_output<float>("Row3Column1");
signature.single_output<float>("Row3Column2");
signature.single_output<float>("Row3Column3");
return signature.build();
}
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override
{
const VArray<float4x4> &matrices = params.readonly_single_input<float4x4>(0, "Matrix");
MutableSpan<float> m00 = params.uninitialized_single_output<float>(1, "Row0Column0");
MutableSpan<float> m10 = params.uninitialized_single_output<float>(2, "Row0Column1");
MutableSpan<float> m20 = params.uninitialized_single_output<float>(3, "Row0Column2");
MutableSpan<float> m30 = params.uninitialized_single_output<float>(4, "Row0Column3");
MutableSpan<float> m01 = params.uninitialized_single_output<float>(5, "Row1Column0");
MutableSpan<float> m11 = params.uninitialized_single_output<float>(6, "Row1Column1");
MutableSpan<float> m21 = params.uninitialized_single_output<float>(7, "Row1Column2");
MutableSpan<float> m31 = params.uninitialized_single_output<float>(8, "Row1Column3");
MutableSpan<float> m02 = params.uninitialized_single_output<float>(9, "Row2Column0");
MutableSpan<float> m12 = params.uninitialized_single_output<float>(10, "Row2Column1");
MutableSpan<float> m22 = params.uninitialized_single_output<float>(11, "Row2Column2");
MutableSpan<float> m32 = params.uninitialized_single_output<float>(12, "Row2Column3");
MutableSpan<float> m03 = params.uninitialized_single_output<float>(13, "Row3Column0");
MutableSpan<float> m13 = params.uninitialized_single_output<float>(14, "Row3Column1");
MutableSpan<float> m23 = params.uninitialized_single_output<float>(15, "Row3Column2");
MutableSpan<float> m33 = params.uninitialized_single_output<float>(16, "Row3Column3");
for (int64_t i : mask) {
const float4x4 &mat = matrices[i];
m00[i] = mat[0][0];
m01[i] = mat[0][1];
m02[i] = mat[0][2];
m03[i] = mat[0][3];
m10[i] = mat[1][0];
m11[i] = mat[1][1];
m12[i] = mat[1][2];
m13[i] = mat[1][3];
m20[i] = mat[2][0];
m21[i] = mat[2][1];
m22[i] = mat[2][2];
m23[i] = mat[2][3];
m30[i] = mat[3][0];
m31[i] = mat[3][1];
m32[i] = mat[3][2];
m33[i] = mat[3][3];
}
}
};
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{
const fn::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn);
const NodeCombSepMatrixMode mode = (NodeCombSepMatrixMode)builder.node().custom1;
switch (mode) {
case NODE_COMBSEP_MATRIX_COLUMNS: {
static SeparateColumnsFunction fn;
builder.set_matching_fn(fn);
break;
}
case NODE_COMBSEP_MATRIX_ROWS: {
static SeparateRowsFunction fn;
builder.set_matching_fn(fn);
break;
}
case NODE_COMBSEP_MATRIX_ELEMENTS: {
static SeparateElementsFunction fn;
builder.set_matching_fn(fn);
break;
}
default: {
BLI_assert_unreachable();
break;
}
}
}
} // namespace blender::nodes::node_fn_combine_color_cc
} // namespace blender::nodes::node_fn_separate_matrix4x4_cc
void register_node_type_fn_combine_color(void)
void register_node_type_fn_separate_matrix_4x4(void)
{
namespace file_ns = blender::nodes::node_fn_combine_color_cc;
namespace file_ns = blender::nodes::node_fn_separate_matrix4x4_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_COMBINE_COLOR, "Combine Color", NODE_CLASS_CONVERTER);
fn_node_type_base(&ntype, FN_NODE_SEPARATE_MATRIX_4X4, "Separate 4x4 Matrix", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::node_declare;
ntype.updatefunc = file_ns::node_update;
ntype.initfunc = file_ns::node_init;
node_type_storage(
&ntype, "NodeCombSepColor", node_free_standard_storage, node_copy_standard_storage);
ntype.build_multi_function = file_ns::node_build_multi_function;
ntype.draw_buttons = file_ns::node_layout;