Geometry Nodes: Mix Rotations
Add support a new Rotation socket/data type to a Mix node. Rotation socket avala ible only in Geometry Nodes right now, list of supported types for node depend on own node tree type. Mixing kind is slerp (interpolation) of a quaternion. As initial phase this is enough. In a future, other modes of interpolation can be added (Euler for XY+Z, YZ+X, ZX+Y, ...). Clamping for factor work the same as for all other data types. Drag and drop should take care avoiding create links between Rotation sockets and all other socket types, this requires chages is mix node callback for drag & drop system. See: https://projects.blender.org/blender/blender/issues/92967 Pull Request: https://projects.blender.org/blender/blender/pulls/109084
This commit is contained in:
parent
bef20cd3f1
commit
3957a1ad03
@ -10,6 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
@ -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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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", "");
|
||||
|
@ -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 ¶ms)
|
||||
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 ¶ms)
|
||||
weight);
|
||||
weight--;
|
||||
}
|
||||
params.add_item(
|
||||
IFACE_("Factor"),
|
||||
[type](LinkSearchOpParams ¶ms) {
|
||||
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 ¶ms) {
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user