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 <string.h>
#include "BLI_function_ref.hh"
#include "BLI_math.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},
};
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
static const EnumPropertyItem node_sampler_type_items[] = {
{0, "NEAREST", 0, "Nearest", ""},
@ -2062,7 +2071,7 @@ static StructRNA *rna_Node_register(Main *bmain,
static const EnumPropertyItem *itemf_function_check(
const EnumPropertyItem *original_item_array,
bool (*value_supported)(const EnumPropertyItem *item))
blender::FunctionRef<bool(const EnumPropertyItem *item)> value_supported)
{
EnumPropertyItem *item_array = nullptr;
int items_len = 0;
@ -3793,6 +3802,27 @@ static const EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl)
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*/,
PointerRNA *ptr,
PropertyRNA * /*prop*/,
@ -5206,13 +5236,6 @@ static void def_compare(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[] = {
{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"},
@ -5224,6 +5247,7 @@ static void def_sh_mix(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeShaderMix", "storage");
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_default(prop, SOCK_FLOAT);
RNA_def_property_ui_text(prop, "Data Type", "");

View File

@ -8,6 +8,8 @@
#include <algorithm>
#include "BLI_math_quaternion.hh"
#include "UI_interface.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})
.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::Vector>("Result", "Result_Vector");
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)
{
const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data));
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
if (data.data_type == SOCK_VECTOR) {
uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE);
}
if (data.data_type == SOCK_RGBA) {
uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "clamp_result", 0, nullptr, ICON_NONE);
uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE);
}
else {
uiItemR(layout, ptr, "clamp_factor", 0, nullptr, ICON_NONE);
switch (data.data_type) {
case SOCK_FLOAT:
break;
case SOCK_VECTOR:
uiItemR(layout, ptr, "factor_mode", 0, "", ICON_NONE);
break;
case SOCK_RGBA:
uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE);
uiItemR(layout, ptr, "clamp_result", 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*/,
@ -167,6 +180,9 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
case SOCK_RGBA:
type = SOCK_RGBA;
break;
case SOCK_ROTATION:
type = SOCK_ROTATION;
break;
default:
return;
}
@ -210,15 +226,21 @@ static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
weight);
weight--;
}
params.add_item(
IFACE_("Factor"),
[type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "Factor");
},
weight);
weight--;
if (type != SOCK_ROTATION) {
params.add_item(
IFACE_("Factor"),
[type](LinkSearchOpParams &params) {
bNode &node = params.add_node("ShaderNodeMix");
node_storage(node).data_type = type;
params.update_and_connect_available_socket(node, "Factor");
},
weight);
weight--;
}
}
if (type == SOCK_ROTATION) {
return;
}
if (type != SOCK_RGBA) {
@ -309,6 +331,8 @@ static const char *gpu_shader_get_name(eNodeSocketDatatype data_type,
BLI_assert_unreachable();
return nullptr;
}
case SOCK_ROTATION:
return nullptr;
default:
BLI_assert_unreachable();
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();
return nullptr;