Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/CMakeLists.txt7
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/NOD_derived_node_tree.hh5
-rw-r--r--source/blender/nodes/NOD_geometry.h4
-rw-r--r--source/blender/nodes/NOD_math_functions.hh3
-rw-r--r--source/blender/nodes/NOD_socket.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h5
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_antialiasing.c65
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc278
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc417
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc (renamed from source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_plane.cc)30
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc15
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_instance.cc5
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc28
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc6
-rw-r--r--source/blender/nodes/intern/node_socket.cc11
-rw-r--r--source/blender/nodes/intern/node_tree_multi_function.cc11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.cc186
23 files changed, 920 insertions, 179 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 271f4e5c5e4..07380addaff 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -46,6 +46,7 @@ set(INC
set(SRC
composite/nodes/node_composite_alphaOver.c
+ composite/nodes/node_composite_antialiasing.c
composite/nodes/node_composite_bilateralblur.c
composite/nodes/node_composite_blur.c
composite/nodes/node_composite_bokehblur.c
@@ -139,19 +140,21 @@ set(SRC
function/node_function_util.cc
geometry/nodes/node_geo_align_rotation_to_vector.cc
+ geometry/nodes/node_geo_attribute_clamp.cc
geometry/nodes/node_geo_attribute_color_ramp.cc
geometry/nodes/node_geo_attribute_combine_xyz.cc
geometry/nodes/node_geo_attribute_compare.cc
geometry/nodes/node_geo_attribute_convert.cc
geometry/nodes/node_geo_attribute_fill.cc
+ geometry/nodes/node_geo_attribute_map_range.cc
geometry/nodes/node_geo_attribute_math.cc
geometry/nodes/node_geo_attribute_mix.cc
geometry/nodes/node_geo_attribute_proximity.cc
geometry/nodes/node_geo_attribute_randomize.cc
+ geometry/nodes/node_geo_attribute_remove.cc
geometry/nodes/node_geo_attribute_sample_texture.cc
geometry/nodes/node_geo_attribute_separate_xyz.cc
geometry/nodes/node_geo_attribute_vector_math.cc
- geometry/nodes/node_geo_attribute_remove.cc
geometry/nodes/node_geo_boolean.cc
geometry/nodes/node_geo_collection_info.cc
geometry/nodes/node_geo_common.cc
@@ -162,9 +165,9 @@ set(SRC
geometry/nodes/node_geo_mesh_primitive_cone.cc
geometry/nodes/node_geo_mesh_primitive_cube.cc
geometry/nodes/node_geo_mesh_primitive_cylinder.cc
+ geometry/nodes/node_geo_mesh_primitive_grid.cc
geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
geometry/nodes/node_geo_mesh_primitive_line.cc
- geometry/nodes/node_geo_mesh_primitive_plane.cc
geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
geometry/nodes/node_geo_object_info.cc
geometry/nodes/node_geo_point_distribute.cc
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index b0dd0edeec5..258e4c961c9 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -79,6 +79,7 @@ void register_node_type_cmp_inpaint(void);
void register_node_type_cmp_despeckle(void);
void register_node_type_cmp_defocus(void);
void register_node_type_cmp_denoise(void);
+void register_node_type_cmp_antialiasing(void);
void register_node_type_cmp_valtorgb(void);
void register_node_type_cmp_rgbtobw(void);
diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh
index e47774bb25a..c29de611e18 100644
--- a/source/blender/nodes/NOD_derived_node_tree.hh
+++ b/source/blender/nodes/NOD_derived_node_tree.hh
@@ -261,7 +261,7 @@ inline const NodeRef *DNode::operator->() const
inline uint64_t DNode::hash() const
{
- return DefaultHash<const DTreeContext *>{}(context_) ^ DefaultHash<const NodeRef *>{}(node_ref_);
+ return get_default_hash_2(context_, node_ref_);
}
/* --------------------------------------------------------------------
@@ -316,8 +316,7 @@ inline const SocketRef *DSocket::operator->() const
inline uint64_t DSocket::hash() const
{
- return DefaultHash<const DTreeContext *>{}(context_) ^
- DefaultHash<const SocketRef *>{}(socket_ref_);
+ return get_default_hash_2(context_, socket_ref_);
}
/* --------------------------------------------------------------------
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 03115852d80..3a26f38d6ba 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -27,11 +27,13 @@ void register_node_tree_type_geo(void);
void register_node_type_geo_group(void);
void register_node_type_geo_align_rotation_to_vector(void);
+void register_node_type_geo_attribute_clamp(void);
void register_node_type_geo_attribute_color_ramp(void);
void register_node_type_geo_attribute_combine_xyz(void);
void register_node_type_geo_attribute_compare(void);
void register_node_type_geo_attribute_convert(void);
void register_node_type_geo_attribute_fill(void);
+void register_node_type_geo_attribute_map_range(void);
void register_node_type_geo_attribute_math(void);
void register_node_type_geo_attribute_mix(void);
void register_node_type_geo_attribute_proximity(void);
@@ -47,8 +49,8 @@ void register_node_type_geo_join_geometry(void);
void register_node_type_geo_mesh_primitive_circle(void);
void register_node_type_geo_mesh_primitive_cone(void);
void register_node_type_geo_mesh_primitive_cube(void);
-void register_node_type_geo_mesh_primitive_plane(void);
void register_node_type_geo_mesh_primitive_cylinder(void);
+void register_node_type_geo_mesh_primitive_grid(void);
void register_node_type_geo_mesh_primitive_ico_sphere(void);
void register_node_type_geo_mesh_primitive_line(void);
void register_node_type_geo_mesh_primitive_uv_sphere(void);
diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh
index 08496e044c5..45de1816549 100644
--- a/source/blender/nodes/NOD_math_functions.hh
+++ b/source/blender/nodes/NOD_math_functions.hh
@@ -379,7 +379,8 @@ inline bool try_dispatch_float_math_fl3_fl3_fl_to_fl3(const NodeVectorMathOperat
switch (operation) {
case NODE_VECTOR_MATH_REFRACT:
- return dispatch([](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); });
+ return dispatch(
+ [](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); });
default:
return false;
}
diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h
index 3344a25bdea..6bcfda70d04 100644
--- a/source/blender/nodes/NOD_socket.h
+++ b/source/blender/nodes/NOD_socket.h
@@ -41,7 +41,7 @@ extern "C" {
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocketTemplate *stemp,
- int in_out);
+ eNodeSocketInOut in_out);
void node_verify_socket_templates(struct bNodeTree *ntree, struct bNode *node);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index ec687ae6b70..0b1efaca502 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -224,6 +224,7 @@ DefNode(CompositorNode, CMP_NODE_CRYPTOMATTE, def_cmp_cryptomatte, "CRYPTO
DefNode(CompositorNode, CMP_NODE_CRYPTOMATTE_LEGACY, def_cmp_cryptomatte_legacy, "CRYPTOMATTE", Cryptomatte, "Cryptomatte (Legacy)", "" )
DefNode(CompositorNode, CMP_NODE_DENOISE, def_cmp_denoise, "DENOISE", Denoise, "Denoise", "" )
DefNode(CompositorNode, CMP_NODE_EXPOSURE, 0, "EXPOSURE", Exposure, "Exposure", "" )
+DefNode(CompositorNode, CMP_NODE_ANTIALIASING, def_cmp_antialiasing, "ANTIALIASING", AntiAliasing, "Anti-Aliasing", "" )
DefNode(TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode(TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
@@ -305,7 +306,9 @@ DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CYLINDER, def_geo_mesh_cylinder, "
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, 0, "MESH_PRIMITIVE_ICO_SPHERE", MeshIcoSphere, "Ico Sphere", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, def_geo_mesh_line, "MESH_PRIMITIVE_LINE", MeshLine, "Line", "")
-DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_PLANE, 0, "MESH_PRIMITIVE_PLANE", MeshPlane, "Plane", "")
+DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_GRID, 0, "MESH_PRIMITIVE_GRID", MeshGrid, "Grid", "")
+DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MAP_RANGE, def_geo_attribute_map_range, "ATTRIBUTE_MAP_RANGE", AttributeMapRange, "Attribute Map Range", "")
+DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_CLAMP, def_geo_attribute_clamp, "ATTRIBUTE_CLAMP", AttributeClamp, "Attribute Clamp", "")
/* undefine macros */
#undef DefNode
diff --git a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c
new file mode 100644
index 00000000000..7437496d878
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): IRIE Shinsuke
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_antialiasing.c
+ * \ingroup cmpnodes
+ */
+
+#include "node_composite_util.h"
+
+/* **************** Anti-Aliasing (SMAA 1x) ******************** */
+
+static bNodeSocketTemplate cmp_node_antialiasing_in[] = {
+ {SOCK_RGBA, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, ""}};
+
+static bNodeSocketTemplate cmp_node_antialiasing_out[] = {{SOCK_RGBA, N_("Image")}, {-1, ""}};
+
+static void node_composit_init_antialiasing(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAntiAliasingData *data = MEM_callocN(sizeof(NodeAntiAliasingData), "node antialiasing data");
+
+ data->threshold = 1.0f;
+ data->contrast_limit = 0.2f;
+ data->corner_rounding = 0.25f;
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_antialiasing(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(
+ &ntype, CMP_NODE_ANTIALIASING, "Anti-Aliasing", NODE_CLASS_OP_FILTER, NODE_PREVIEW);
+ node_type_socket_templates(&ntype, cmp_node_antialiasing_in, cmp_node_antialiasing_out);
+ node_type_size(&ntype, 170, 140, 200);
+ node_type_init(&ntype, node_composit_init_antialiasing);
+ node_type_storage(
+ &ntype, "NodeAntiAliasingData", node_free_standard_storage, node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
new file mode 100644
index 00000000000..93e4124bd70
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_clamp.cc
@@ -0,0 +1,278 @@
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_geometry_util.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static bNodeSocketTemplate geo_node_attribute_clamp_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {SOCK_STRING, N_("Attribute")},
+ {SOCK_STRING, N_("Result")},
+ {SOCK_VECTOR, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_INT, N_("Min"), 0.0f, 0.0f, 0.0f, 0.0f, -100000, 100000},
+ {SOCK_INT, N_("Max"), 100.0f, 0.0f, 0.0f, 0.0f, -100000, 100000},
+ {SOCK_RGBA, N_("Min"), 0.5, 0.5, 0.5, 1.0},
+ {SOCK_RGBA, N_("Max"), 0.5, 0.5, 0.5, 1.0},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_attribute_clamp_out[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static void geo_node_attribute_clamp_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
+}
+
+static void geo_node_attribute_clamp_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeAttributeClamp *data = (NodeAttributeClamp *)MEM_callocN(sizeof(NodeAttributeClamp),
+ __func__);
+ data->data_type = CD_PROP_FLOAT;
+ data->operation = NODE_CLAMP_MINMAX;
+ node->storage = data;
+}
+
+static void geo_node_attribute_clamp_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock_min_vector = (bNodeSocket *)BLI_findlink(&node->inputs, 3);
+ bNodeSocket *sock_max_vector = sock_min_vector->next;
+ bNodeSocket *sock_min_float = sock_max_vector->next;
+ bNodeSocket *sock_max_float = sock_min_float->next;
+ bNodeSocket *sock_min_int = sock_max_float->next;
+ bNodeSocket *sock_max_int = sock_min_int->next;
+ bNodeSocket *sock_min_color = sock_max_int->next;
+ bNodeSocket *sock_max_color = sock_min_color->next;
+
+ const NodeAttributeClamp &storage = *(const NodeAttributeClamp *)node->storage;
+ const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
+ nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_min_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(sock_max_int, data_type == CD_PROP_INT32);
+ nodeSetSocketAvailability(sock_min_color, data_type == CD_PROP_COLOR);
+ nodeSetSocketAvailability(sock_max_color, data_type == CD_PROP_COLOR);
+}
+
+namespace blender::nodes {
+
+template<typename T> T clamp_value(const T val, const T min, const T max);
+
+template<> inline float clamp_value(const float val, const float min, const float max)
+{
+ return std::min(std::max(val, min), max);
+}
+
+template<> inline int clamp_value(const int val, const int min, const int max)
+{
+ return std::min(std::max(val, min), max);
+}
+
+template<> inline float3 clamp_value(const float3 val, const float3 min, const float3 max)
+{
+ float3 tmp;
+ tmp.x = std::min(std::max(val.x, min.x), max.x);
+ tmp.y = std::min(std::max(val.y, min.y), max.y);
+ tmp.z = std::min(std::max(val.z, min.z), max.z);
+ return tmp;
+}
+
+template<> inline Color4f clamp_value(const Color4f val, const Color4f min, const Color4f max)
+{
+ Color4f tmp;
+ tmp.r = std::min(std::max(val.r, min.r), max.r);
+ tmp.g = std::min(std::max(val.g, min.g), max.g);
+ tmp.b = std::min(std::max(val.b, min.b), max.b);
+ tmp.a = std::min(std::max(val.a, min.a), max.a);
+ return tmp;
+}
+
+template<typename T>
+static void clamp_attribute(Span<T> read_span, MutableSpan<T> span, const T min, const T max)
+{
+ for (const int i : span.index_range()) {
+ span[i] = clamp_value<T>(read_span[i], min, max);
+ }
+}
+
+static AttributeDomain get_result_domain(const GeometryComponent &component,
+ StringRef source_name,
+ StringRef result_name)
+{
+ ReadAttributePtr result_attribute = component.attribute_try_get_for_read(result_name);
+ if (result_attribute) {
+ return result_attribute->domain();
+ }
+ ReadAttributePtr source_attribute = component.attribute_try_get_for_read(source_name);
+ if (source_attribute) {
+ return source_attribute->domain();
+ }
+ return ATTR_DOMAIN_POINT;
+}
+
+static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParams &params)
+{
+ const std::string attribute_name = params.get_input<std::string>("Attribute");
+ const std::string result_name = params.get_input<std::string>("Result");
+
+ if (attribute_name.empty() || result_name.empty()) {
+ return;
+ }
+
+ if (!component.attribute_exists(attribute_name)) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("No attribute with name \"") + attribute_name + "\"");
+ return;
+ }
+
+ const NodeAttributeClamp &storage = *(const NodeAttributeClamp *)params.node().storage;
+ const CustomDataType data_type = static_cast<CustomDataType>(storage.data_type);
+ const AttributeDomain domain = get_result_domain(component, attribute_name, result_name);
+ const int operation = static_cast<int>(storage.operation);
+
+ ReadAttributePtr attribute_input = component.attribute_try_get_for_read(
+ attribute_name, domain, data_type);
+
+ OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
+ result_name, domain, data_type);
+
+ if (!attribute_result) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Could not find or create attribute with name \"") +
+ result_name + "\"");
+ return;
+ }
+
+ switch (data_type) {
+ case CD_PROP_FLOAT3: {
+ Span<float3> read_span = attribute_input->get_span<float3>();
+ MutableSpan<float3> span = attribute_result->get_span_for_write_only<float3>();
+ float3 min = params.get_input<float3>("Min");
+ float3 max = params.get_input<float3>("Max");
+ if (operation == NODE_CLAMP_RANGE) {
+ if (min.x > max.x) {
+ std::swap(min.x, max.x);
+ }
+ if (min.y > max.y) {
+ std::swap(min.y, max.y);
+ }
+ if (min.z > max.z) {
+ std::swap(min.z, max.z);
+ }
+ }
+ clamp_attribute<float3>(read_span, span, min, max);
+ break;
+ }
+ case CD_PROP_FLOAT: {
+ Span<float> read_span = attribute_input->get_span<float>();
+ MutableSpan<float> span = attribute_result->get_span_for_write_only<float>();
+ const float min = params.get_input<float>("Min_001");
+ const float max = params.get_input<float>("Max_001");
+ if (operation == NODE_CLAMP_RANGE && min > max) {
+ clamp_attribute<float>(read_span, span, max, min);
+ }
+ else {
+ clamp_attribute<float>(read_span, span, min, max);
+ }
+ break;
+ }
+ case CD_PROP_INT32: {
+ Span<int> read_span = attribute_input->get_span<int>();
+ MutableSpan<int> span = attribute_result->get_span_for_write_only<int>();
+ const int min = params.get_input<int>("Min_002");
+ const int max = params.get_input<int>("Max_002");
+ if (operation == NODE_CLAMP_RANGE && min > max) {
+ clamp_attribute<int>(read_span, span, max, min);
+ }
+ else {
+ clamp_attribute<int>(read_span, span, min, max);
+ }
+ break;
+ }
+ case CD_PROP_COLOR: {
+ Span<Color4f> read_span = attribute_input->get_span<Color4f>();
+ MutableSpan<Color4f> span = attribute_result->get_span_for_write_only<Color4f>();
+ Color4f min = params.get_input<Color4f>("Min_003");
+ Color4f max = params.get_input<Color4f>("Max_003");
+ if (operation == NODE_CLAMP_RANGE) {
+ if (min.r > max.r) {
+ std::swap(min.r, max.r);
+ }
+ if (min.g > max.g) {
+ std::swap(min.g, max.g);
+ }
+ if (min.b > max.b) {
+ std::swap(min.b, max.b);
+ }
+ if (min.a > max.a) {
+ std::swap(min.a, max.a);
+ }
+ }
+ clamp_attribute<Color4f>(read_span, span, min, max);
+ break;
+ }
+ default: {
+ BLI_assert(false);
+ break;
+ }
+ }
+
+ attribute_result.apply_span_and_save();
+}
+
+static void geo_node_attribute_clamp_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+ geometry_set = geometry_set_realize_instances(geometry_set);
+
+ if (geometry_set.has<MeshComponent>()) {
+ clamp_attribute(geometry_set.get_component_for_write<MeshComponent>(), params);
+ }
+ if (geometry_set.has<PointCloudComponent>()) {
+ clamp_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params);
+ }
+
+ params.set_output("Geometry", geometry_set);
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_attribute_clamp()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_CLAMP, "Attribute Clamp", NODE_CLASS_ATTRIBUTE, 0);
+ node_type_socket_templates(&ntype, geo_node_attribute_clamp_in, geo_node_attribute_clamp_out);
+ node_type_init(&ntype, geo_node_attribute_clamp_init);
+ node_type_update(&ntype, geo_node_attribute_clamp_update);
+ ntype.geometry_node_execute = blender::nodes::geo_node_attribute_clamp_exec;
+ ntype.draw_buttons = geo_node_attribute_clamp_layout;
+ node_type_storage(
+ &ntype, "NodeAttributeClamp", node_free_standard_storage, node_copy_standard_storage);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc
new file mode 100644
index 00000000000..4e0dfd3a636
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_map_range.cc
@@ -0,0 +1,417 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "node_geometry_util.hh"
+
+#include "BLI_math_base_safe.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static bNodeSocketTemplate geo_node_attribute_map_range_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {SOCK_STRING, N_("Attribute")},
+ {SOCK_STRING, N_("Result")},
+ {SOCK_FLOAT, N_("From Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("From Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("To Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("To Max"), 1.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_FLOAT, N_("Steps"), 4.0f, 4.0f, 4.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("From Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("From Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("To Min"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("To Max"), 1.0f, 1.0f, 1.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_VECTOR, N_("Steps"), 4.0f, 4.0f, 4.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_BOOLEAN, N_("Clamp")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_attribute_map_range_out[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static void fn_attribute_map_range_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE);
+}
+
+static void geo_node_attribute_map_range_init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAttributeMapRange *data = (NodeAttributeMapRange *)MEM_callocN(sizeof(NodeAttributeMapRange),
+ __func__);
+ data->data_type = CD_PROP_FLOAT;
+ data->interpolation_type = NODE_MAP_RANGE_LINEAR;
+
+ node->storage = data;
+}
+static void geo_node_attribute_map_range_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node->storage;
+
+ bNodeSocket *sock_from_min_float = (bNodeSocket *)BLI_findlink(&node->inputs, 3);
+ bNodeSocket *sock_from_max_float = sock_from_min_float->next;
+ bNodeSocket *sock_to_min_float = sock_from_max_float->next;
+ bNodeSocket *sock_to_max_float = sock_to_min_float->next;
+ bNodeSocket *sock_steps_float = sock_to_max_float->next;
+
+ bNodeSocket *sock_from_min_vector = sock_steps_float->next;
+ bNodeSocket *sock_from_max_vector = sock_from_min_vector->next;
+ bNodeSocket *sock_to_min_vector = sock_from_max_vector->next;
+ bNodeSocket *sock_to_max_vector = sock_to_min_vector->next;
+ bNodeSocket *sock_steps_vector = sock_to_max_vector->next;
+
+ bNodeSocket *sock_clamp = sock_steps_vector->next;
+
+ const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type);
+
+ nodeSetSocketAvailability(sock_clamp,
+ node_storage.interpolation_type == NODE_MAP_RANGE_LINEAR ||
+ node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
+
+ nodeSetSocketAvailability(sock_from_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_from_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_to_min_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_to_max_float, data_type == CD_PROP_FLOAT);
+ nodeSetSocketAvailability(sock_steps_float,
+ data_type == CD_PROP_FLOAT &&
+ node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
+
+ nodeSetSocketAvailability(sock_from_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_from_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_to_min_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_to_max_vector, data_type == CD_PROP_FLOAT3);
+ nodeSetSocketAvailability(sock_steps_vector,
+ data_type == CD_PROP_FLOAT3 &&
+ node_storage.interpolation_type == NODE_MAP_RANGE_STEPPED);
+}
+
+namespace blender::nodes {
+
+static float map_linear(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to)
+{
+ /* First we calculate a fraction that measures how far along
+ * the [min_from, max_from] interval the value lies.
+ *
+ * value
+ * min_from [------>|------------------------] max_from
+ * factor (e.g. 0.25)
+ *
+ * Then to find where the value is mapped, we add the same fraction
+ * of the [min_to, max_to] interval to min_to.
+ *
+ * min_to [--->|-----------] max_to
+ * v
+ * min_to + (max_to - min_to) * factor
+ */
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ return min_to + factor * (max_to - min_to);
+}
+
+static float map_stepped(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to,
+ const float steps)
+{
+ /* First the factor is calculated here in the same way as for the linear mapping.
+ *
+ * Then the factor is mapped to multiples of 1.0 / steps.
+ * This is best understood with a few examples. Assume steps == 3.
+ * ____________________________________
+ * | factor | * 4.0 | floor() | / 3.0 |
+ * |--------|-------|---------|-------|
+ * | 0.0 | 0.0 | 0.0 | 0.0 |
+ * | 0.1 | 0.4 | 0.0 | 0.0 |
+ * | 0.25 | 1.0 | 1.0 | 0.333 |
+ * | 0.45 | 1.8 | 1.0 | 0.333 |
+ * | 0.5 | 2.0 | 2.0 | 0.666 |
+ * | 0.55 | 2.2 | 2.0 | 0.666 |
+ * | 0.999 | 3.999 | 3.0 | 1.0 |
+ * | 1.0 | 4.0 | 4.0 | 1.333 |
+ * ------------------------------------
+ * Note that the factor is not always mapped the closest multiple of 1.0 /steps.
+ */
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ const float factor_mapped = safe_divide(floorf(factor * (steps + 1.0f)), steps);
+ return min_to + factor_mapped * (max_to - min_to);
+}
+
+static float smoothstep_polynomial(float x)
+{
+ /* This polynomial is only meant to be used for the [0, 1] range. */
+ return (3.0f - 2.0f * x) * (x * x);
+}
+
+static float map_smoothstep(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to)
+{
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ const float factor_clamped = std::clamp(factor, 0.0f, 1.0f);
+ const float factor_mapped = smoothstep_polynomial(factor_clamped);
+ return min_to + factor_mapped * (max_to - min_to);
+}
+
+static float smootherstep_polynomial(float x)
+{
+ /* This polynomial is only meant to be used for the [0, 1] range. */
+ return x * x * x * (x * (x * 6.0f - 15.0f) + 10.0f);
+}
+
+static float map_smootherstep(const float value,
+ const float min_from,
+ const float max_from,
+ const float min_to,
+ const float max_to)
+{
+ const float factor = safe_divide(value - min_from, max_from - min_from);
+ const float factor_clamped = std::clamp(factor, 0.0f, 1.0f);
+ const float factor_mapped = smootherstep_polynomial(factor_clamped);
+ return min_to + factor_mapped * (max_to - min_to);
+}
+
+static void map_range_float(FloatReadAttribute attribute_input,
+ FloatWriteAttribute attribute_result,
+ const GeoNodeExecParams &params)
+{
+ const bNode &node = params.node();
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage;
+ const int interpolation_type = node_storage.interpolation_type;
+ const float min_from = params.get_input<float>("From Min");
+ const float max_from = params.get_input<float>("From Max");
+ const float min_to = params.get_input<float>("To Min");
+ const float max_to = params.get_input<float>("To Max");
+
+ Span<float> span = attribute_input.get_span();
+ MutableSpan<float> result_span = attribute_result.get_span();
+
+ switch (interpolation_type) {
+ case NODE_MAP_RANGE_LINEAR: {
+ for (int i : span.index_range()) {
+ result_span[i] = map_linear(span[i], min_from, max_from, min_to, max_to);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_STEPPED: {
+ const float steps = params.get_input<float>("Steps");
+ for (int i : span.index_range()) {
+ result_span[i] = map_stepped(span[i], min_from, max_from, min_to, max_to, steps);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i] = map_smoothstep(span[i], min_from, max_from, min_to, max_to);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHERSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i] = map_smootherstep(span[i], min_from, max_from, min_to, max_to);
+ }
+ break;
+ }
+ }
+
+ if (ELEM(interpolation_type, NODE_MAP_RANGE_LINEAR, NODE_MAP_RANGE_STEPPED) &&
+ params.get_input<bool>("Clamp")) {
+ /* Users can specify min_to > max_to, but clamping expects min < max. */
+ const float clamp_min = min_to < max_to ? min_to : max_to;
+ const float clamp_max = min_to < max_to ? max_to : min_to;
+
+ for (int i : result_span.index_range()) {
+ result_span[i] = std::clamp(result_span[i], clamp_min, clamp_max);
+ }
+ }
+}
+
+static void map_range_float3(Float3ReadAttribute attribute_input,
+ Float3WriteAttribute attribute_result,
+ const GeoNodeExecParams &params)
+{
+ const bNode &node = params.node();
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage;
+ const int interpolation_type = node_storage.interpolation_type;
+ const float3 min_from = params.get_input<float3>("From Min_001");
+ const float3 max_from = params.get_input<float3>("From Max_001");
+ const float3 min_to = params.get_input<float3>("To Min_001");
+ const float3 max_to = params.get_input<float3>("To Max_001");
+
+ Span<float3> span = attribute_input.get_span();
+ MutableSpan<float3> result_span = attribute_result.get_span();
+
+ switch (interpolation_type) {
+ case NODE_MAP_RANGE_LINEAR: {
+ for (int i : span.index_range()) {
+ result_span[i].x = map_linear(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x);
+ result_span[i].y = map_linear(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y);
+ result_span[i].z = map_linear(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_STEPPED: {
+ const float3 steps = params.get_input<float3>("Steps_001");
+ for (int i : span.index_range()) {
+ result_span[i].x = map_stepped(
+ span[i].x, min_from.x, max_from.x, min_to.x, max_to.x, steps.x);
+ result_span[i].y = map_stepped(
+ span[i].y, min_from.y, max_from.y, min_to.y, max_to.y, steps.y);
+ result_span[i].z = map_stepped(
+ span[i].z, min_from.z, max_from.z, min_to.z, max_to.z, steps.z);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i].x = map_smoothstep(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x);
+ result_span[i].y = map_smoothstep(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y);
+ result_span[i].z = map_smoothstep(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z);
+ }
+ break;
+ }
+ case NODE_MAP_RANGE_SMOOTHERSTEP: {
+ for (int i : span.index_range()) {
+ result_span[i].x = map_smootherstep(span[i].x, min_from.x, max_from.x, min_to.x, max_to.x);
+ result_span[i].y = map_smootherstep(span[i].y, min_from.y, max_from.y, min_to.y, max_to.y);
+ result_span[i].z = map_smootherstep(span[i].z, min_from.z, max_from.z, min_to.z, max_to.z);
+ }
+ break;
+ }
+ }
+
+ if (ELEM(interpolation_type, NODE_MAP_RANGE_LINEAR, NODE_MAP_RANGE_STEPPED) &&
+ params.get_input<bool>("Clamp")) {
+ /* Users can specify min_to > max_to, but clamping expects min < max. */
+ float3 clamp_min;
+ float3 clamp_max;
+ clamp_min.x = min_to.x < max_to.x ? min_to.x : max_to.x;
+ clamp_max.x = min_to.x < max_to.x ? max_to.x : min_to.x;
+ clamp_min.y = min_to.y < max_to.y ? min_to.y : max_to.y;
+ clamp_max.y = min_to.y < max_to.y ? max_to.y : min_to.y;
+ clamp_min.z = min_to.z < max_to.z ? min_to.z : max_to.z;
+ clamp_max.z = min_to.z < max_to.z ? max_to.z : min_to.z;
+
+ for (int i : result_span.index_range()) {
+ clamp_v3_v3v3(result_span[i], clamp_min, clamp_max);
+ }
+ }
+}
+
+static AttributeDomain get_result_domain(const GeometryComponent &component,
+ StringRef source_name,
+ StringRef result_name)
+{
+ ReadAttributePtr result_attribute = component.attribute_try_get_for_read(result_name);
+ if (result_attribute) {
+ return result_attribute->domain();
+ }
+ ReadAttributePtr source_attribute = component.attribute_try_get_for_read(source_name);
+ if (source_attribute) {
+ return source_attribute->domain();
+ }
+ return ATTR_DOMAIN_POINT;
+}
+
+static void map_range_attribute(GeometryComponent &component, const GeoNodeExecParams &params)
+{
+ const std::string input_name = params.get_input<std::string>("Attribute");
+ const std::string result_name = params.get_input<std::string>("Result");
+
+ if (input_name.empty() || result_name.empty()) {
+ return;
+ }
+
+ const bNode &node = params.node();
+ NodeAttributeMapRange &node_storage = *(NodeAttributeMapRange *)node.storage;
+ const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type);
+
+ const AttributeDomain domain = get_result_domain(component, input_name, result_name);
+
+ ReadAttributePtr attribute_input = component.attribute_try_get_for_read(
+ input_name, domain, data_type);
+
+ if (!attribute_input) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("No attribute with name \"") + input_name + "\"");
+ return;
+ }
+
+ OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
+ result_name, domain, data_type);
+ if (!attribute_result) {
+ params.error_message_add(NodeWarningType::Error,
+ TIP_("Could not find or create attribute with name \"") +
+ result_name + "\"");
+ return;
+ }
+
+ switch (data_type) {
+ case CD_PROP_FLOAT: {
+ map_range_float(*attribute_input, *attribute_result, params);
+ break;
+ }
+ case CD_PROP_FLOAT3: {
+ map_range_float3(*attribute_input, *attribute_result, params);
+ break;
+ }
+ default:
+ BLI_assert_unreachable();
+ }
+
+ attribute_result.apply_span_and_save();
+}
+
+static void geo_node_attribute_map_range_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+ if (geometry_set.has<MeshComponent>()) {
+ map_range_attribute(geometry_set.get_component_for_write<MeshComponent>(), params);
+ }
+ if (geometry_set.has<PointCloudComponent>()) {
+ map_range_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params);
+ }
+
+ params.set_output("Geometry", geometry_set);
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_attribute_map_range()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_ATTRIBUTE_MAP_RANGE, "Attribute Map Range", NODE_CLASS_ATTRIBUTE, 0);
+ node_type_socket_templates(
+ &ntype, geo_node_attribute_map_range_in, geo_node_attribute_map_range_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_attribute_map_range_exec;
+ node_type_init(&ntype, geo_node_attribute_map_range_init);
+ node_type_update(&ntype, geo_node_attribute_map_range_update);
+ node_type_storage(
+ &ntype, "NodeAttributeMapRange", node_free_standard_storage, node_copy_standard_storage);
+ ntype.draw_buttons = fn_attribute_map_range_layout;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
index 9c48e7c44ba..0c970f0d2e2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc
@@ -223,8 +223,10 @@ Mesh *create_cylinder_or_cone_mesh(const float radius_top,
transform.values,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
index 1803a13f651..f8a9bfd2ed1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
@@ -50,8 +50,10 @@ static Mesh *create_cube_mesh(const float size)
size,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_plane.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
index eff84d7d1ad..1b9ec91a2f6 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_plane.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc
@@ -27,14 +27,14 @@
#include "node_geometry_util.hh"
-static bNodeSocketTemplate geo_node_mesh_primitive_plane_in[] = {
+static bNodeSocketTemplate geo_node_mesh_primitive_grid_in[] = {
{SOCK_FLOAT, N_("Size"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
- {SOCK_INT, N_("Vertices X"), 10, 0.0f, 0.0f, 0.0f, 2, 1000},
- {SOCK_INT, N_("Vertices Y"), 10, 0.0f, 0.0f, 0.0f, 2, 1000},
+ {SOCK_INT, N_("Vertices X"), 3, 0.0f, 0.0f, 0.0f, 2, 1000},
+ {SOCK_INT, N_("Vertices Y"), 3, 0.0f, 0.0f, 0.0f, 2, 1000},
{-1, ""},
};
-static bNodeSocketTemplate geo_node_mesh_primitive_plane_out[] = {
+static bNodeSocketTemplate geo_node_mesh_primitive_grid_out[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{-1, ""},
};
@@ -51,14 +51,14 @@ static void calculate_uvs(Mesh *mesh, Span<MVert> verts, Span<MLoop> loops, cons
for (const int i : loops.index_range()) {
const float3 &co = verts[loops[i].v].co;
- uvs[i].x = (co.x + size) / (size * 2.0f);
- uvs[i].y = (co.y + size) / (size * 2.0f);
+ uvs[i].x = (co.x + (size * 0.5)) / size;
+ uvs[i].y = (co.y + (size * 0.5)) / size;
}
uv_attribute.apply_span_and_save();
}
-static Mesh *create_plane_mesh(const int verts_x, const int verts_y, const float size)
+static Mesh *create_grid_mesh(const int verts_x, const int verts_y, const float size)
{
const int edges_x = verts_x - 1;
const int edges_y = verts_y - 1;
@@ -75,9 +75,9 @@ static Mesh *create_plane_mesh(const int verts_x, const int verts_y, const float
{
const float dx = size / edges_x;
const float dy = size / edges_y;
- float x = -size;
+ float x = -size * 0.5;
for (const int x_index : IndexRange(verts_x)) {
- float y = -size;
+ float y = -size * 0.5;
for (const int y_index : IndexRange(verts_y)) {
const int vert_index = x_index * verts_y + y_index;
verts[vert_index].co[0] = x;
@@ -147,7 +147,7 @@ static Mesh *create_plane_mesh(const int verts_x, const int verts_y, const float
return mesh;
}
-static void geo_node_mesh_primitive_plane_exec(GeoNodeExecParams params)
+static void geo_node_mesh_primitive_grid_exec(GeoNodeExecParams params)
{
const float size = params.extract_input<float>("Size");
const int verts_x = params.extract_input<int>("Vertices X");
@@ -157,7 +157,7 @@ static void geo_node_mesh_primitive_plane_exec(GeoNodeExecParams params)
return;
}
- Mesh *mesh = create_plane_mesh(verts_x, verts_y, size);
+ Mesh *mesh = create_grid_mesh(verts_x, verts_y, size);
BLI_assert(BKE_mesh_is_valid(mesh));
params.set_output("Geometry", GeometrySet::create_with_mesh(mesh));
@@ -165,13 +165,13 @@ static void geo_node_mesh_primitive_plane_exec(GeoNodeExecParams params)
} // namespace blender::nodes
-void register_node_type_geo_mesh_primitive_plane()
+void register_node_type_geo_mesh_primitive_grid()
{
static bNodeType ntype;
- geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_PLANE, "Plane", NODE_CLASS_GEOMETRY, 0);
+ geo_node_type_base(&ntype, GEO_NODE_MESH_PRIMITIVE_GRID, "Grid", NODE_CLASS_GEOMETRY, 0);
node_type_socket_templates(
- &ntype, geo_node_mesh_primitive_plane_in, geo_node_mesh_primitive_plane_out);
- ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_plane_exec;
+ &ntype, geo_node_mesh_primitive_grid_in, geo_node_mesh_primitive_grid_out);
+ ntype.geometry_node_execute = blender::nodes::geo_node_mesh_primitive_grid_exec;
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
index f16b37fe977..242cc6ed7df 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc
@@ -52,8 +52,10 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions, const float radius)
transform.values,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
index b7d249c18bc..8efba91da1a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc
@@ -85,8 +85,10 @@ static Mesh *create_uv_sphere_mesh_bmesh(const float radius, const int segments,
transform.values,
true);
+ BMeshToMeshParams params{};
+ params.calc_object_remap = false;
Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
- BM_mesh_bm_to_me_for_eval(bm, mesh, nullptr);
+ BM_mesh_bm_to_me(nullptr, bm, mesh, &params);
BM_mesh_free(bm);
return mesh;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index 4795970377a..1e1f5e9d085 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -310,10 +310,10 @@ BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh,
}
template<typename T>
-BLI_NOINLINE static void interpolate_attribute_polygon(const Mesh &mesh,
- const Span<int> looptri_indices,
- const Span<T> data_in,
- MutableSpan<T> data_out)
+BLI_NOINLINE static void interpolate_attribute_face(const Mesh &mesh,
+ const Span<int> looptri_indices,
+ const Span<T> data_in,
+ MutableSpan<T> data_out)
{
BLI_assert(data_in.size() == mesh.totpoly);
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
@@ -344,8 +344,8 @@ BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh,
mesh, bary_coords, looptri_indices, source_span, output_span);
break;
}
- case ATTR_DOMAIN_POLYGON: {
- interpolate_attribute_polygon<T>(mesh, looptri_indices, source_span, output_span);
+ case ATTR_DOMAIN_FACE: {
+ interpolate_attribute_face<T>(mesh, looptri_indices, source_span, output_span);
break;
}
default: {
@@ -636,7 +636,8 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
return;
}
- Vector<GeometryInstanceGroup> set_groups = bke::geometry_set_gather_instances(geometry_set);
+ Vector<GeometryInstanceGroup> set_groups;
+ geometry_set_gather_instances(geometry_set, set_groups);
if (set_groups.is_empty()) {
params.set_output("Geometry", GeometrySet());
return;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
index dbbb73bd36d..5d8f0a76719 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc
@@ -188,9 +188,8 @@ static void add_instances_from_geometry_component(InstancesComponent &instances,
for (const int i : IndexRange(domain_size)) {
if (instances_data[i].has_value()) {
- float transform[4][4];
- loc_eul_size_to_mat4(transform, positions[i], rotations[i], scales[i]);
- instances.add_instance(*instances_data[i], transform, ids[i]);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]);
+ instances.add_instance(*instances_data[i], matrix, ids[i]);
}
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
index b79ca0a6197..eb441a0a568 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
@@ -38,7 +38,7 @@ static bNodeSocketTemplate geo_node_points_to_volume_in[] = {
{-1, ""},
};
-static bNodeSocketTemplate geo_node_point_translate_out[] = {
+static bNodeSocketTemplate geo_node_points_to_volume_out[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{-1, ""},
};
@@ -262,7 +262,7 @@ void register_node_type_geo_points_to_volume()
geo_node_type_base(
&ntype, GEO_NODE_POINTS_TO_VOLUME, "Points to Volume", NODE_CLASS_GEOMETRY, 0);
- node_type_socket_templates(&ntype, geo_node_points_to_volume_in, geo_node_point_translate_out);
+ node_type_socket_templates(&ntype, geo_node_points_to_volume_in, geo_node_points_to_volume_out);
node_type_storage(&ntype,
"NodeGeometryPointsToVolume",
node_free_standard_storage,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
index ef6f0be40f2..2c05c98c9ba 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
@@ -18,7 +18,7 @@
# include <openvdb/openvdb.h>
#endif
-#include "BLI_math_matrix.h"
+#include "BLI_float4x4.hh"
#include "DNA_pointcloud_types.h"
#include "DNA_volume_types.h"
@@ -65,13 +65,12 @@ void transform_mesh(Mesh *mesh,
/* Use only translation if rotation and scale are zero. */
if (use_translate(rotation, scale)) {
if (!translation.is_zero()) {
- BKE_mesh_translate(mesh, translation, true);
+ BKE_mesh_translate(mesh, translation, false);
}
}
else {
- float mat[4][4];
- loc_eul_size_to_mat4(mat, translation, rotation, scale);
- BKE_mesh_transform(mesh, mat, true);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
+ BKE_mesh_transform(mesh, matrix.values, false);
BKE_mesh_calc_normals(mesh);
}
}
@@ -83,15 +82,15 @@ static void transform_pointcloud(PointCloud *pointcloud,
{
/* Use only translation if rotation and scale don't apply. */
if (use_translate(rotation, scale)) {
- for (int i = 0; i < pointcloud->totpoint; i++) {
+ for (const int i : IndexRange(pointcloud->totpoint)) {
add_v3_v3(pointcloud->co[i], translation);
}
}
else {
- float mat[4][4];
- loc_eul_size_to_mat4(mat, translation, rotation, scale);
- for (int i = 0; i < pointcloud->totpoint; i++) {
- mul_m4_v3(mat, pointcloud->co[i]);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
+ for (const int i : IndexRange(pointcloud->totpoint)) {
+ float3 &co = *(float3 *)pointcloud->co[i];
+ co = matrix * co;
}
}
}
@@ -110,11 +109,9 @@ static void transform_instances(InstancesComponent &instances,
}
}
else {
- float mat[4][4];
-
- loc_eul_size_to_mat4(mat, translation, rotation, scale);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
for (float4x4 &transform : transforms) {
- mul_m4_m4_pre(transform.ptr(), mat);
+ transform = matrix * transform;
}
}
}
@@ -136,8 +133,7 @@ static void transform_volume(Volume *volume,
Main *bmain = DEG_get_bmain(params.depsgraph());
BKE_volume_load(volume, bmain);
- float matrix[4][4];
- loc_eul_size_to_mat4(matrix, translation, rotation, limited_scale);
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, limited_scale);
openvdb::Mat4s vdb_matrix;
memcpy(vdb_matrix.asPointer(), matrix, sizeof(float[4][4]));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
index 54dccb613a1..1c0e7106b19 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc
@@ -36,7 +36,7 @@
static bNodeSocketTemplate geo_node_volume_to_mesh_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
- {SOCK_STRING, N_("Grid")},
+ {SOCK_STRING, N_("Density")},
{SOCK_FLOAT, N_("Voxel Size"), 0.3f, 0.0f, 0.0f, 0.0f, 0.01f, FLT_MAX},
{SOCK_FLOAT, N_("Voxel Amount"), 64.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
{SOCK_FLOAT, N_("Threshold"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
@@ -64,7 +64,7 @@ static void geo_node_volume_to_mesh_init(bNodeTree *UNUSED(ntree), bNode *node)
sizeof(NodeGeometryVolumeToMesh), __func__);
data->resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_GRID;
- bNodeSocket *grid_socket = nodeFindSocket(node, SOCK_IN, "Grid");
+ bNodeSocket *grid_socket = nodeFindSocket(node, SOCK_IN, "Density");
bNodeSocketValueString *grid_socket_value = (bNodeSocketValueString *)grid_socket->default_value;
STRNCPY(grid_socket_value->value, "density");
@@ -120,7 +120,7 @@ static void create_mesh_from_volume(GeometrySet &geometry_set_in,
Main *bmain = DEG_get_bmain(params.depsgraph());
BKE_volume_load(const_cast<Volume *>(volume), bmain);
- const std::string grid_name = params.get_input<std::string>("Grid");
+ const std::string grid_name = params.get_input<std::string>("Density");
VolumeGrid *volume_grid = BKE_volume_grid_find(volume, grid_name.c_str());
if (volume_grid == nullptr) {
return;
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index 26df3f77738..b583523da98 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -52,7 +52,7 @@
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocketTemplate *stemp,
- int in_out)
+ eNodeSocketInOut in_out)
{
bNodeSocket *sock = nodeAddStaticSocket(
ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
@@ -102,8 +102,11 @@ struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
return sock;
}
-static bNodeSocket *verify_socket_template(
- bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp)
+static bNodeSocket *verify_socket_template(bNodeTree *ntree,
+ bNode *node,
+ eNodeSocketInOut in_out,
+ ListBase *socklist,
+ bNodeSocketTemplate *stemp)
{
bNodeSocket *sock;
@@ -132,7 +135,7 @@ static bNodeSocket *verify_socket_template(
static void verify_socket_template_list(bNodeTree *ntree,
bNode *node,
- int in_out,
+ eNodeSocketInOut in_out,
ListBase *socklist,
bNodeSocketTemplate *stemp_first)
{
diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc
index b973350becd..c77a6b42f97 100644
--- a/source/blender/nodes/intern/node_tree_multi_function.cc
+++ b/source/blender/nodes/intern/node_tree_multi_function.cc
@@ -164,7 +164,8 @@ static DataTypeConversions create_implicit_conversions()
add_implicit_conversion<float, float2>(conversions);
add_implicit_conversion<float, float3>(conversions);
add_implicit_conversion<float, int32_t>(conversions);
- add_implicit_conversion<float, bool>(conversions);
+ add_implicit_conversion<float, bool>(
+ conversions, "float to boolean", [](float a) { return a > 0.0f; });
add_implicit_conversion<float, Color4f>(
conversions, "float to Color4f", [](float a) { return Color4f(a, a, a, 1.0f); });
@@ -189,7 +190,8 @@ static DataTypeConversions create_implicit_conversions()
add_implicit_conversion<float3, Color4f>(
conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); });
- add_implicit_conversion<int32_t, bool>(conversions);
+ add_implicit_conversion<int32_t, bool>(
+ conversions, "int32 to boolean", [](int32_t a) { return a > 0; });
add_implicit_conversion<int32_t, float>(conversions);
add_implicit_conversion<int32_t, float2>(
conversions, "int32 to float2", [](int32_t a) { return float2((float)a); });
@@ -209,9 +211,8 @@ static DataTypeConversions create_implicit_conversions()
return (a) ? Color4f(1.0f, 1.0f, 1.0f, 1.0f) : Color4f(0.0f, 0.0f, 0.0f, 1.0f);
});
- add_implicit_conversion<Color4f, bool>(conversions, "Color4f to boolean", [](Color4f a) {
- return a.r != 0.0f && a.g != 0.0f && a.b != 0.0f;
- });
+ add_implicit_conversion<Color4f, bool>(
+ conversions, "Color4f to boolean", [](Color4f a) { return rgb_to_grayscale(a) > 0.0f; });
add_implicit_conversion<Color4f, float>(
conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); });
add_implicit_conversion<Color4f, float2>(
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
index 3a9822fbc8e..472f903e1a5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
@@ -23,6 +23,8 @@
#include "node_shader_util.h"
+#include "NOD_math_functions.hh"
+
/* **************** VECTOR MATH ******************** */
static bNodeSocketTemplate sh_node_vector_math_in[] = {
{SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
@@ -177,117 +179,79 @@ static const blender::fn::MultiFunction &get_multi_function(
{
using blender::float3;
- const int mode = builder.bnode().custom1;
- switch (mode) {
- case NODE_VECTOR_MATH_ADD: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Add", [](float3 a, float3 b) { return a + b; }};
- return fn;
- }
- case NODE_VECTOR_MATH_SUBTRACT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Subtract", [](float3 a, float3 b) { return a - b; }};
- return fn;
- }
- case NODE_VECTOR_MATH_MULTIPLY: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Multiply", [](float3 a, float3 b) { return a * b; }};
- return fn;
- }
- case NODE_VECTOR_MATH_DIVIDE: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Divide", [](float3 a, float3 b) { return float3::safe_divide(a, b); }};
- return fn;
- }
- case NODE_VECTOR_MATH_CROSS_PRODUCT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Cross Product", float3::cross_high_precision};
- return fn;
- }
- case NODE_VECTOR_MATH_PROJECT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{"Project", float3::project};
- return fn;
- }
- case NODE_VECTOR_MATH_REFLECT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- "Reflect", [](float3 a, float3 b) { return a.reflected(b); }};
- return fn;
- }
- case NODE_VECTOR_MATH_DOT_PRODUCT: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Dot Product", float3::dot};
- return fn;
- }
- case NODE_VECTOR_MATH_DISTANCE: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{"Distance",
- float3::distance};
- return fn;
- }
- case NODE_VECTOR_MATH_LENGTH: {
- static blender::fn::CustomMF_SI_SO<float3, float> fn{"Length",
- [](float3 a) { return a.length(); }};
- return fn;
- }
- case NODE_VECTOR_MATH_SCALE: {
- static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{
- "Scale", [](float3 a, float factor) { return a * factor; }};
- return fn;
- }
- case NODE_VECTOR_MATH_NORMALIZE: {
- static blender::fn::CustomMF_SI_SO<float3, float3> fn{
- "Normalize", [](float3 a) { return a.normalized(); }};
- return fn;
- }
- case NODE_VECTOR_MATH_REFRACT: {
- static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
- "Refract",
- [](float3 a, float3 b, float c) { return float3::refract(a, b.normalized(), c); }};
- return fn;
- }
- case NODE_VECTOR_MATH_FACEFORWARD: {
- static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
- "Faceforward", float3::faceforward};
- return fn;
- }
- case NODE_VECTOR_MATH_SNAP: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_FLOOR: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_CEIL: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_MODULO: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_FRACTION: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_ABSOLUTE: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_MINIMUM: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_MAXIMUM: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_WRAP: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_SINE: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_COSINE: {
- return builder.get_not_implemented_fn();
- }
- case NODE_VECTOR_MATH_TANGENT: {
- return builder.get_not_implemented_fn();
- }
- default:
- BLI_assert_unreachable();
- return builder.get_not_implemented_fn();
- };
+ NodeVectorMathOperation operation = NodeVectorMathOperation(builder.bnode().custom1);
+
+ const blender::fn::MultiFunction *multi_fn = nullptr;
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{info.title_case_name,
+ function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_fl3_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
+ info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_fl_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
+ info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl3_to_fl(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SO<float3, float3, float> fn{info.title_case_name,
+ function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_fl_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SI_SO<float3, float, float3> fn{info.title_case_name,
+ function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_to_fl3(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ blender::nodes::try_dispatch_float_math_fl3_to_fl(
+ operation, [&](auto function, const blender::nodes::FloatMathOperationInfo &info) {
+ static blender::fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name, function};
+ multi_fn = &fn;
+ });
+ if (multi_fn != nullptr) {
+ return *multi_fn;
+ }
+
+ return builder.get_not_implemented_fn();
}
static void sh_node_vector_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)