Geometry Nodes: Mix Rotations #109084

Merged
Hans Goudey merged 11 commits from mod_moder/blender:slerp into main 2023-06-27 00:51:00 +02:00
2 changed files with 95 additions and 27 deletions

View File

@ -10,6 +10,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "BLI_function_ref.hh"
#include "BLI_math.h" #include "BLI_math.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
mod_moder marked this conversation as resolved Outdated

Group this with the other BLI includes

Group this with the other BLI includes
@ -513,6 +514,14 @@ static const EnumPropertyItem rna_node_combsep_color_items[] = {
{0, nullptr, 0, nullptr, nullptr}, {0, nullptr, 0, nullptr, nullptr},
}; };
static const EnumPropertyItem rna_enum_mix_data_type_items[] = {
{SOCK_FLOAT, "FLOAT", 0, "Float", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_RGBA, "RGBA", 0, "Color", ""},
{SOCK_ROTATION, "ROTATION", 0, "Rotation", ""},
{0, nullptr, 0, nullptr, nullptr},
};
#ifndef RNA_RUNTIME #ifndef RNA_RUNTIME
static const EnumPropertyItem node_sampler_type_items[] = { static const EnumPropertyItem node_sampler_type_items[] = {
{0, "NEAREST", 0, "Nearest", ""}, {0, "NEAREST", 0, "Nearest", ""},
@ -2062,7 +2071,7 @@ static StructRNA *rna_Node_register(Main *bmain,
static const EnumPropertyItem *itemf_function_check( static const EnumPropertyItem *itemf_function_check(
const EnumPropertyItem *original_item_array, const EnumPropertyItem *original_item_array,
bool (*value_supported)(const EnumPropertyItem *item)) blender::FunctionRef<bool(const EnumPropertyItem *item)> value_supported)
{ {
EnumPropertyItem *item_array = nullptr; EnumPropertyItem *item_array = nullptr;
int items_len = 0; int items_len = 0;
@ -3793,6 +3802,27 @@ static const EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl)
return item; return item;
} }
static const EnumPropertyItem *rna_ShaderNodeMix_data_type_itemf(bContext * /*C*/,
PointerRNA *ptr,
PropertyRNA * /*prop*/,
bool *r_free)
{
*r_free = true;
const auto rotation_supported_mix = [&](const EnumPropertyItem *item) -> bool {
const eNodeSocketDatatype data_type = eNodeSocketDatatype(item->value);
mod_moder marked this conversation as resolved Outdated

[ptr] -> [&]

`[ptr]` -> `[&]`
if (U.experimental.use_rotation_socket && data_type == SOCK_ROTATION) {
const bNodeTree *tree = reinterpret_cast<const bNodeTree *>(ptr->owner_id);
if (tree->type == NTREE_GEOMETRY) {
return true;
mod_moder marked this conversation as resolved
Review

This assert is unnecessary IMO, the pointer is de-referenced in the next line which shows it's not expected to be null.

This assert is unnecessary IMO, the pointer is de-referenced in the next line which shows it's not expected to be null.
}
}
return ELEM(data_type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
};
return itemf_function_check(rna_enum_mix_data_type_items, rotation_supported_mix);
}
static const EnumPropertyItem *rna_Node_image_layer_itemf(bContext * /*C*/, static const EnumPropertyItem *rna_Node_image_layer_itemf(bContext * /*C*/,
PointerRNA *ptr, PointerRNA *ptr,
PropertyRNA * /*prop*/, PropertyRNA * /*prop*/,
@ -5206,13 +5236,6 @@ static void def_compare(StructRNA *srna)
static void def_sh_mix(StructRNA *srna) static void def_sh_mix(StructRNA *srna)
{ {
static const EnumPropertyItem rna_enum_mix_data_type_items[] = {
{SOCK_FLOAT, "FLOAT", 0, "Float", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_RGBA, "RGBA", 0, "Color", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem rna_enum_mix_mode_items[] = { static const EnumPropertyItem rna_enum_mix_mode_items[] = {
{NODE_MIX_MODE_UNIFORM, "UNIFORM", 0, "Uniform", "Use a single factor for all components"}, {NODE_MIX_MODE_UNIFORM, "UNIFORM", 0, "Uniform", "Use a single factor for all components"},
{NODE_MIX_MODE_NON_UNIFORM, "NON_UNIFORM", 0, "Non-Uniform", "Per component factor"}, {NODE_MIX_MODE_NON_UNIFORM, "NON_UNIFORM", 0, "Non-Uniform", "Per component factor"},
@ -5224,6 +5247,7 @@ static void def_sh_mix(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeShaderMix", "storage"); RNA_def_struct_sdna_from(srna, "NodeShaderMix", "storage");
prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_funcs(prop, nullptr, nullptr, "rna_ShaderNodeMix_data_type_itemf");
RNA_def_property_enum_items(prop, rna_enum_mix_data_type_items); RNA_def_property_enum_items(prop, rna_enum_mix_data_type_items);
RNA_def_property_enum_default(prop, SOCK_FLOAT); RNA_def_property_enum_default(prop, SOCK_FLOAT);
RNA_def_property_ui_text(prop, "Data Type", ""); RNA_def_property_ui_text(prop, "Data Type", "");

View File

@ -8,6 +8,8 @@
#include <algorithm> #include <algorithm>
#include "BLI_math_quaternion.hh"
#include "UI_interface.h" #include "UI_interface.h"
#include "UI_resources.h" #include "UI_resources.h"
@ -62,26 +64,37 @@ static void sh_node_mix_declare(NodeDeclarationBuilder &b)
.default_value({0.5f, 0.5f, 0.5f, 1.0f}) .default_value({0.5f, 0.5f, 0.5f, 1.0f})
.translation_context(BLT_I18NCONTEXT_ID_NODETREE); .translation_context(BLT_I18NCONTEXT_ID_NODETREE);
b.add_input<decl::Rotation>("A", "A_Rotation")
.is_default_link_socket()
.translation_context(BLT_I18NCONTEXT_ID_NODETREE);
b.add_input<decl::Rotation>("B", "B_Rotation").translation_context(BLT_I18NCONTEXT_ID_NODETREE);
b.add_output<decl::Float>("Result", "Result_Float"); b.add_output<decl::Float>("Result", "Result_Float");
b.add_output<decl::Vector>("Result", "Result_Vector"); b.add_output<decl::Vector>("Result", "Result_Vector");
b.add_output<decl::Color>("Result", "Result_Color"); b.add_output<decl::Color>("Result", "Result_Color");
b.add_output<decl::Rotation>("Result", "Result_Rotation");
}; };
static void sh_node_mix_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) static void sh_node_mix_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{ {
const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data)); const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data));
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
if (data.data_type == SOCK_VECTOR) { switch (data.data_type) {
uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE); case SOCK_FLOAT:
} break;
if (data.data_type == SOCK_RGBA) { case SOCK_VECTOR:
uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE); uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE);
uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE); break;
uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE); case SOCK_RGBA:
} uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE);
else { uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE);
uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE); break;
case SOCK_ROTATION:
break;
default:
BLI_assert_unreachable();
} }
uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE);
} }
static void sh_node_mix_label(const bNodeTree * /*ntree*/, static void sh_node_mix_label(const bNodeTree * /*ntree*/,
@ -167,6 +180,9 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
case SOCK_RGBA: case SOCK_RGBA:
type = SOCK_RGBA; type = SOCK_RGBA;
break; break;
case SOCK_ROTATION:
type = SOCK_ROTATION;
break;
default: default:
return; return;
} }
@ -210,15 +226,21 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
weight); weight);
weight--; weight--;
} }
params.add_item( if (type != SOCK_ROTATION) {
IFACE_("Factor"), params.add_item(
[type](LinkSearchOpParams &params) { IFACE_("Factor"),
bNode &node = params.add_node("ShaderNodeMix"); [type](LinkSearchOpParams &params) {
node_storage(node).data_type = type; bNode &node = params.add_node("ShaderNodeMix");
params.update_and_connect_available_socket(node, "Factor"); node_storage(node).data_type = type;
}, params.update_and_connect_available_socket(node, "Factor");
weight); },
weight--; weight);
weight--;
}
}
if (type == SOCK_ROTATION) {
return;
} }
if (type != SOCK_RGBA) { if (type != SOCK_RGBA) {
@ -309,6 +331,8 @@ static const char *gpu_shader_get_name(eNodeSocketDatatype data_type,
BLI_assert_unreachable(); BLI_assert_unreachable();
return nullptr; return nullptr;
} }
case SOCK_ROTATION:
return nullptr;
default: default:
BLI_assert_unreachable(); BLI_assert_unreachable();
return nullptr; return nullptr;
@ -480,6 +504,26 @@ static const mf::MultiFunction *get_multi_function(const bNode &node)
} }
} }
} }
case SOCK_ROTATION: {
if (clamp_factor) {
static auto fn =
mf::build::SI3_SO<float, math::Quaternion, math::Quaternion, math::Quaternion>(
"Clamp Mix Rotation",
[](const float t, const math::Quaternion &a, const math::Quaternion &b) {
return math::interpolate(a, b, math::clamp(t, 0.0f, 1.0f));
});
return &fn;
}
else {
static auto fn =
mf::build::SI3_SO<float, math::Quaternion, math::Quaternion, math::Quaternion>(
"Mix Rotation",
[](const float t, const math::Quaternion &a, const math::Quaternion &b) {
return math::interpolate(a, b, t);
});
return &fn;
}
}
} }
BLI_assert_unreachable(); BLI_assert_unreachable();
return nullptr; return nullptr;