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.
11 changed files with 261 additions and 9 deletions
Showing only changes of commit 9a55a9bdd5 - Show all commits

View File

@ -1883,6 +1883,10 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
return "NodeSocketInterfaceTexture";
case SOCK_MATERIAL:
return "NodeSocketInterfaceMaterial";
case SOCK_MATRIX3x3:
return "NodeSocketInterfaceMatrix3x3";
case SOCK_MATRIX4x4:
return "NodeSocketInterfaceMatrix4x4";
}
return nullptr;
}
@ -1916,6 +1920,10 @@ const char *nodeStaticSocketLabel(int type, int /*subtype*/)
return "Texture";
case SOCK_MATERIAL:
return "Material";
case SOCK_MATRIX3x3:
return "Matrix3x3";
case SOCK_MATRIX4x4:
return "Matrix4x4";
}
return nullptr;
}

View File

@ -72,7 +72,7 @@ namespace node_field_inferencing {
static bool is_field_socket_type(eNodeSocketDatatype type)
{
return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA);
return ELEM(type, SOCK_FLOAT, SOCK_INT, SOCK_BOOLEAN, SOCK_VECTOR, SOCK_RGBA, SOCK_MATRIX3x3, SOCK_MATRIX4x4);
}
static bool is_field_socket_type(const bNodeSocket &socket)

View File

@ -1200,6 +1200,8 @@ static const float std_node_socket_colors[][4] = {
{0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
{0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
{0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
{0.01, 0.61, 0.66, 1.0}, /* SOCK_MATRIX3x3 */
{0.01, 0.36, 0.62, 1.0}, /* SOCK_MATRIX4x4 */
};
/* common color callbacks for standard types */
@ -1320,6 +1322,24 @@ static void std_node_socket_draw(
}
}
break;
case SOCK_MATRIX3x3:
if (sock->flag & SOCK_COMPACT) {
uiTemplateComponentMenu(layout, ptr, "default_value", text);
}
else {
uiLayout *column = uiLayoutColumn(layout, true);
uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE);
}
break;
case SOCK_MATRIX4x4:
if (sock->flag & SOCK_COMPACT) {
uiTemplateComponentMenu(layout, ptr, "default_value", text);
}
else {
uiLayout *column = uiLayoutColumn(layout, true);
uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE);
}
break;
case SOCK_RGBA: {
if (text[0] == '\0') {
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, "", 0);
@ -1450,6 +1470,20 @@ static void std_node_socket_interface_draw(bContext * /*C*/, uiLayout *layout, P
uiItemR(sub, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
break;
}
case SOCK_MATRIX3x3: {
uiItemR(col, ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
uiLayout *sub = uiLayoutColumn(col, true);
uiItemR(sub, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
uiItemR(sub, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
break;
}
case SOCK_MATRIX4x4: {
uiItemR(col, ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
uiLayout *sub = uiLayoutColumn(col, true);
uiItemR(sub, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
uiItemR(sub, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
break;
}
case SOCK_BOOLEAN:
case SOCK_RGBA:
case SOCK_STRING:

View File

@ -451,6 +451,10 @@ static eCustomDataType socket_type_to_custom_data_type(const eNodeSocketDatatype
return CD_PROP_INT32;
case SOCK_VECTOR:
return CD_PROP_FLOAT3;
case SOCK_MATRIX3x3:
return CD_PROP_FLOAT3x3;
case SOCK_MATRIX4x4:
return CD_PROP_FLOAT4x4;
case SOCK_BOOLEAN:
return CD_PROP_BOOL;
case SOCK_RGBA:
@ -2070,8 +2074,12 @@ static int get_main_socket_priority(const bNodeSocket *socket)
return 3;
case SOCK_VECTOR:
return 4;
case SOCK_RGBA:
case SOCK_MATRIX3x3:
return 5;
case SOCK_MATRIX4x4:
return 6;
case SOCK_RGBA:
return 7;
case SOCK_STRING:
case SOCK_SHADER:
case SOCK_OBJECT:
@ -2080,7 +2088,7 @@ static int get_main_socket_priority(const bNodeSocket *socket)
case SOCK_COLLECTION:
case SOCK_TEXTURE:
case SOCK_MATERIAL:
return 6;
return 8;
}
return -1;
}

View File

@ -868,6 +868,8 @@ static void ui_node_draw_input(
else {
switch (input.type) {
case SOCK_VECTOR:
case SOCK_MATRIX3x3:
case SOCK_MATRIX4x4:
uiItemS(sub);
sub = uiLayoutColumn(sub, true);
ATTR_FALLTHROUGH;

View File

@ -62,6 +62,8 @@ static const EnumPropertyItem node_socket_data_type_items[] = {
{SOCK_INT, "INT", 0, "Integer", ""},
{SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_MATRIX3x3, "MATRIX3x3", 0, "3x3 Matrix", ""},
{SOCK_MATRIX4x4, "MATRIX4x4", 0, "4x4 Matrix", ""},
{SOCK_STRING, "STRING", 0, "String", ""},
{SOCK_RGBA, "RGBA", 0, "Color", ""},
{SOCK_OBJECT, "OBJECT", 0, "Object", ""},
@ -89,6 +91,8 @@ static const EnumPropertyItem node_socket_type_items[] = {
{SOCK_INT, "INT", 0, "Integer", ""},
{SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_MATRIX3x3, "MATRIX3x3", 0, "3x3 Matrix", ""},
{SOCK_MATRIX4x4, "MATRIX4x4", 0, "4x4 Matrix", ""},
{SOCK_STRING, "STRING", 0, "String", ""},
{SOCK_RGBA, "RGBA", 0, "RGBA", ""},
{SOCK_SHADER, "SHADER", 0, "Shader", ""},

View File

@ -12,6 +12,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_array.hh"
#include "BLI_float3x3.hh"
#include "BLI_float4x4.hh"
#include "BLI_listbase.h"
#include "BLI_math_vec_types.hh"
#include "BLI_multi_value_map.hh"
@ -100,6 +102,8 @@ using blender::ColorGeometry4f;
using blender::CPPType;
using blender::destruct_ptr;
using blender::float3;
using blender::float3x3;
using blender::float4x4;
using blender::FunctionRef;
using blender::GMutablePointer;
using blender::GMutableSpan;
@ -417,7 +421,7 @@ static const std::string attribute_name_suffix = "_attribute_name";
*/
static bool socket_type_has_attribute_toggle(const bNodeSocket &socket)
{
return ELEM(socket.type, SOCK_FLOAT, SOCK_VECTOR, SOCK_BOOLEAN, SOCK_RGBA, SOCK_INT);
return ELEM(socket.type, SOCK_FLOAT, SOCK_VECTOR, SOCK_BOOLEAN, SOCK_RGBA, SOCK_INT, SOCK_MATRIX3x3, SOCK_MATRIX4x4);
}
/**
@ -475,6 +479,36 @@ id_property_create_from_socket(const bNodeSocket &socket)
}
return property;
}
case SOCK_MATRIX3x3: {
const bNodeSocketValueMatrix3x3 *value = static_cast<const bNodeSocketValueMatrix3x3 *>(
socket.default_value);
auto property = bke::idprop::create(socket.identifier, Span<float>(value->value, 9));
IDPropertyUIDataFloat *ui_data = (IDPropertyUIDataFloat *)IDP_ui_data_ensure(property.get());
ui_data->base.rna_subtype = PROP_MATRIX;
ui_data->min = ui_data->soft_min = double(value->min);
ui_data->max = ui_data->soft_max = double(value->max);
ui_data->default_array = (double *)MEM_mallocN(sizeof(double[9]), "mod_prop_default");
ui_data->default_array_len = 9;
for (const int i : IndexRange(9)) {
ui_data->default_array[i] = double(value->value[i]);
}
return property;
}
case SOCK_MATRIX4x4: {
const bNodeSocketValueMatrix4x4 *value = static_cast<const bNodeSocketValueMatrix4x4 *>(
socket.default_value);
auto property = bke::idprop::create(socket.identifier, Span<float>(value->value, 16));
IDPropertyUIDataFloat *ui_data = (IDPropertyUIDataFloat *)IDP_ui_data_ensure(property.get());
ui_data->base.rna_subtype = PROP_MATRIX;
ui_data->min = ui_data->soft_min = double(value->min);
ui_data->max = ui_data->soft_max = double(value->max);
ui_data->default_array = (double *)MEM_mallocN(sizeof(double[16]), "mod_prop_default");
ui_data->default_array_len = 16;
for (const int i : IndexRange(16)) {
ui_data->default_array[i] = double(value->value[i]);
}
return property;
}
case SOCK_RGBA: {
const bNodeSocketValueRGBA *value = static_cast<const bNodeSocketValueRGBA *>(
socket.default_value);
@ -551,6 +585,10 @@ static bool id_property_type_matches_socket(const bNodeSocket &socket, const IDP
return property.type == IDP_INT;
case SOCK_VECTOR:
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 3;
case SOCK_MATRIX3x3:
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 9;
case SOCK_MATRIX4x4:
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 16;
case SOCK_RGBA:
return property.type == IDP_ARRAY && property.subtype == IDP_FLOAT && property.len == 4;
case SOCK_BOOLEAN:
@ -595,6 +633,18 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
new (r_value) ValueOrField<float3>(value);
break;
}
case SOCK_MATRIX3x3: {
float3x3 value;
copy_m3_m3(value.ptr(), (const float (*)[3])IDP_Array(&property));
new (r_value) ValueOrField<float3x3>(value);
break;
}
case SOCK_MATRIX4x4: {
float4x4 value;
copy_m4_m4(value.ptr(), (const float(*)[4])IDP_Array(&property));
new (r_value) ValueOrField<float4x4>(value);
break;
}
case SOCK_RGBA: {
blender::ColorGeometry4f value;
copy_v4_v4((float *)value, (const float *)IDP_Array(&property));

View File

@ -100,7 +100,9 @@ static bool geometry_node_tree_socket_type_valid(bNodeTreeType * /*treetype*/,
SOCK_COLLECTION,
SOCK_TEXTURE,
SOCK_IMAGE,
SOCK_MATERIAL);
SOCK_MATERIAL,
SOCK_MATRIX3x3,
SOCK_MATRIX4x4);
}
void register_node_tree_type_geo()

View File

@ -21,6 +21,10 @@ std::optional<eCustomDataType> node_data_type_to_custom_data_type(const eNodeSoc
return CD_PROP_FLOAT;
case SOCK_VECTOR:
return CD_PROP_FLOAT3;
case SOCK_MATRIX3x3:
return CD_PROP_MATRIX3;
case SOCK_MATRIX4x4:
return CD_PROP_MATRIX4;
case SOCK_RGBA:
return CD_PROP_COLOR;
case SOCK_BOOLEAN:

View File

@ -10,6 +10,8 @@
#include "DNA_node_types.h"
#include "BLI_color.hh"
#include "BLI_float3x3.hh"
#include "BLI_float4x4.hh"
#include "BLI_listbase.h"
#include "BLI_math_vec_types.hh"
#include "BLI_string.h"
@ -77,6 +79,24 @@ struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
dval->max = stemp->max;
break;
}
case SOCK_MATRIX3x3: {
bNodeSocketValueMatrix3x3 *dval = (bNodeSocketValueMatrix3x3 *)sock->default_value;
dval->value[0] = stemp->val1;
dval->value[1] = stemp->val2;
dval->value[2] = stemp->val3;
dval->min = stemp->min;
dval->max = stemp->max;
break;
}
case SOCK_MATRIX4x4: {
bNodeSocketValueMatrix4x4 *dval = (bNodeSocketValueMatrix4x4 *)sock->default_value;
dval->value[0] = stemp->val1;
dval->value[1] = stemp->val2;
dval->value[2] = stemp->val3;
dval->min = stemp->min;
dval->max = stemp->max;
break;
}
case SOCK_RGBA: {
bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)sock->default_value;
dval->value[0] = stemp->val1;
@ -330,6 +350,34 @@ void node_socket_init_default_value(bNodeSocket *sock)
sock->default_value = dval;
break;
}
case SOCK_MATRIX3x3: {
static float default_value[][3] = {
{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}};
bNodeSocketValueMatrix3x3 *dval = MEM_cnew<bNodeSocketValueMatrix3x3>(
"node socket value matrix 3x3");
dval->subtype = subtype;
copy_m3_m3(dval->value, default_value);
dval->min = -FLT_MAX;
dval->max = FLT_MAX;
sock->default_value = dval;
break;
}
case SOCK_MATRIX4x4: {
static float default_value[][4] = {{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}};
bNodeSocketValueMatrix4x4 *dval = MEM_cnew<bNodeSocketValueMatrix4x4>(
"node socket value vector");
dval->subtype = subtype;
copy_m4_m4(dval->value, default_value);
dval->min = -FLT_MAX;
dval->max = FLT_MAX;
sock->default_value = dval;
break;
}
case SOCK_RGBA: {
static float default_value[] = {0.0f, 0.0f, 0.0f, 1.0f};
bNodeSocketValueRGBA *dval = MEM_cnew<bNodeSocketValueRGBA>("node socket value color");
@ -430,6 +478,18 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
*toval = *fromval;
break;
}
case SOCK_MATRIX3x3: {
bNodeSocketValueMatrix3x3 *toval = (bNodeSocketValueMatrix3x3 *)to->default_value;
bNodeSocketValueMatrix3x3 *fromval = (bNodeSocketValueMatrix3x3 *)from->default_value;
*toval = *fromval;
break;
}
case SOCK_MATRIX4x4: {
bNodeSocketValueMatrix4x4 *toval = (bNodeSocketValueMatrix4x4 *)to->default_value;
bNodeSocketValueMatrix4x4 *fromval = (bNodeSocketValueMatrix4x4 *)from->default_value;
*toval = *fromval;
break;
}
case SOCK_RGBA: {
bNodeSocketValueRGBA *toval = (bNodeSocketValueRGBA *)to->default_value;
bNodeSocketValueRGBA *fromval = (bNodeSocketValueRGBA *)from->default_value;
@ -590,6 +650,22 @@ static void standard_node_socket_interface_verify_socket(bNodeTree * /*ntree*/,
toval->max = fromval->max;
break;
}
case SOCK_MATRIX3x3: {
bNodeSocketValueMatrix3x3 *toval = (bNodeSocketValueMatrix3x3 *)sock->default_value;
const bNodeSocketValueMatrix3x3 *fromval = (const bNodeSocketValueMatrix3x3 *)
interface_socket->default_value;
toval->min = fromval->min;
toval->max = fromval->max;
break;
}
case SOCK_MATRIX4x4: {
bNodeSocketValueMatrix4x4 *toval = (bNodeSocketValueMatrix4x4 *)sock->default_value;
const bNodeSocketValueMatrix4x4 *fromval = (const bNodeSocketValueMatrix4x4 *)
interface_socket->default_value;
toval->min = fromval->min;
toval->max = fromval->max;
break;
}
}
}
@ -744,6 +820,38 @@ static bNodeSocketType *make_socket_type_vector(PropertySubType subtype)
return socktype;
}
static bNodeSocketType *make_socket_type_matrix3()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_MATRIX3x3, PROP_MATRIX);
socktype->base_cpp_type = &blender::CPPType::get<blender::float3x3>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(blender::float3x3 *)r_value = ((bNodeSocketValueMatrix3x3 *)socket.default_value)->value;
};
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<blender::float3x3>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
blender::float3x3 value;
socket.typeinfo->get_base_cpp_value(socket, &value);
new (r_value) ValueOrField<blender::float3x3>(value);
};
return socktype;
}
static bNodeSocketType *make_socket_type_matrix4()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_MATRIX4x4, PROP_MATRIX);
socktype->base_cpp_type = &blender::CPPType::get<blender::float4x4>();
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(blender::float4x4 *)r_value = ((bNodeSocketValueMatrix4x4 *)socket.default_value)->value;
};
socktype->geometry_nodes_cpp_type = &blender::CPPType::get<ValueOrField<blender::float4x4>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
blender::float4x4 value;
socket.typeinfo->get_base_cpp_value(socket, &value);
new (r_value) ValueOrField<blender::float4x4>(value);
};
return socktype;
}
static bNodeSocketType *make_socket_type_rgba()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_RGBA, PROP_NONE);

View File

@ -254,9 +254,13 @@ bNodeSocket &Vector::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket
bNodeSocket &Matrix3x3::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *nodeAddSocket(
&ntree, &node, in_out_, "NodeSocketMatrix3x3", identifier_.c_str(), name_.c_str());
bNodeSocket &socket = *nodeAddStaticSocket(
&ntree, &node, in_out_, SOCK_MATRIX3x3, PROP_MATRIX, identifier_.c_str(), name_.c_str());
this->set_common_flags(socket);
bNodeSocketValueMatrix3x3 &value = *(bNodeSocketValueMatrix3x3 *)socket.default_value;
copy_m3_m3(value.value, default_value_.ptr());
value.min = soft_min_value_;
value.max = soft_max_value_;
return socket;
}
@ -276,6 +280,18 @@ bool Matrix3x3::can_connect(const bNodeSocket &socket) const
return sockets_can_connect(*this, socket) && socket.type == SOCK_MATRIX3x3;
}
bNodeSocket &Matrix3x3::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_MATRIX3x3) {
BLI_assert(socket.in_out == in_out_);
return this->build(ntree, node);
}
this->set_common_flags(socket);
bNodeSocketValueMatrix3x3 &value = *(bNodeSocketValueMatrix3x3 *)socket.default_value;
STRNCPY(socket.name, name_.c_str());
return socket;
}
/** \} */
/* -------------------------------------------------------------------- */
@ -284,9 +300,13 @@ bool Matrix3x3::can_connect(const bNodeSocket &socket) const
bNodeSocket &Matrix4x4::build(bNodeTree &ntree, bNode &node) const
{
bNodeSocket &socket = *nodeAddSocket(
&ntree, &node, in_out_, "NodeSocketMatrix4x4", identifier_.c_str(), name_.c_str());
bNodeSocket &socket = *nodeAddStaticSocket(
&ntree, &node, in_out_, SOCK_MATRIX4x4, PROP_MATRIX, identifier_.c_str(), name_.c_str());
this->set_common_flags(socket);
bNodeSocketValueMatrix4x4 &value = *(bNodeSocketValueMatrix4x4 *)socket.default_value;
copy_m4_m4(value.value, default_value_.ptr());
value.min = soft_min_value_;
value.max = soft_max_value_;
return socket;
}
@ -306,6 +326,18 @@ bool Matrix4x4::can_connect(const bNodeSocket &socket) const
return sockets_can_connect(*this, socket) && socket.type == SOCK_MATRIX4x4;
}
bNodeSocket &Matrix4x4::update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const
{
if (socket.type != SOCK_MATRIX4x4) {
BLI_assert(socket.in_out == in_out_);
return this->build(ntree, node);
}
this->set_common_flags(socket);
bNodeSocketValueMatrix4x4 &value = *(bNodeSocketValueMatrix4x4 *)socket.default_value;
STRNCPY(socket.name, name_.c_str());
return socket;
}
/** \} */
/* -------------------------------------------------------------------- */