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:
-rw-r--r--release/scripts/startup/nodeitems_builtins.py2
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/intern/node.cc2
-rw-r--r--source/blender/makesdna/DNA_node_types.h14
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c33
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/NOD_geometry.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc135
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc148
10 files changed, 342 insertions, 0 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 40b57fd10de..9d7485a0837 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -491,6 +491,8 @@ geometry_node_categories = [
NodeItem("GeometryNodeAttributeColorRamp"),
NodeItem("GeometryNodeAttributeVectorMath"),
NodeItem("GeometryNodeAttributeSampleTexture"),
+ NodeItem("GeometryNodeAttributeCombineXYZ"),
+ NodeItem("GeometryNodeAttributeSeparateXYZ"),
]),
GeometryNodeCategory("GEO_COLOR", "Color", items=[
NodeItem("ShaderNodeValToRGB"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index f4f753c4084..7984bbc980a 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1370,6 +1370,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_IS_VIEWPORT 1024
#define GEO_NODE_ATTRIBUTE_PROXIMITY 1025
#define GEO_NODE_VOLUME_TO_MESH 1026
+#define GEO_NODE_ATTRIBUTE_COMBINE_XYZ 1027
+#define GEO_NODE_ATTRIBUTE_SEPARATE_XYZ 1028
/** \} */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index a4440d3d9f3..ed8dd84a9bb 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4753,12 +4753,14 @@ static void registerGeometryNodes()
register_node_type_geo_align_rotation_to_vector();
register_node_type_geo_attribute_color_ramp();
+ register_node_type_geo_attribute_combine_xyz();
register_node_type_geo_attribute_compare();
register_node_type_geo_attribute_fill();
register_node_type_geo_attribute_math();
register_node_type_geo_attribute_mix();
register_node_type_geo_attribute_proximity();
register_node_type_geo_attribute_randomize();
+ register_node_type_geo_attribute_separate_xyz();
register_node_type_geo_attribute_vector_math();
register_node_type_geo_boolean();
register_node_type_geo_collection_info();
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index e8748e28776..61b0b469426 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1216,6 +1216,20 @@ typedef struct NodeGeometryVolumeToMesh {
char _pad[7];
} NodeGeometryVolumeToMesh;
+typedef struct NodeAttributeCombineXYZ {
+ /* GeometryNodeAttributeInputMode. */
+ uint8_t input_type_x;
+ uint8_t input_type_y;
+ uint8_t input_type_z;
+
+ char _pad[1];
+} NodeAttributeCombineXYZ;
+
+typedef struct NodeAttributeSeparateXYZ {
+ /* GeometryNodeAttributeInputMode. */
+ uint8_t input_type;
+} NodeAttributeSeparateXYZ;
+
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index c67a3e4448b..c00f843c76e 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -9029,6 +9029,39 @@ static void def_geo_volume_to_mesh(StructRNA *srna)
prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, resolution_mode_items);
RNA_def_property_ui_text(prop, "Resolution Mode", "How the voxel size is specified");
+}
+
+static void def_geo_attribute_combine_xyz(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeAttributeCombineXYZ", "storage");
+
+ prop = RNA_def_property(srna, "input_type_x", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float);
+ RNA_def_property_ui_text(prop, "Input Type X", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "input_type_y", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float);
+ RNA_def_property_ui_text(prop, "Input Type Y", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+
+ prop = RNA_def_property(srna, "input_type_z", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float);
+ RNA_def_property_ui_text(prop, "Input Type Z", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
+static void def_geo_attribute_separate_xyz(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeAttributeSeparateXYZ", "storage");
+
+ prop = RNA_def_property(srna, "input_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector);
+ RNA_def_property_ui_text(prop, "Input Type", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 4656e2e5e4f..64c240eb5fd 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -143,6 +143,7 @@ set(SRC
geometry/nodes/node_geo_align_rotation_to_vector.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_fill.cc
geometry/nodes/node_geo_attribute_math.cc
@@ -150,6 +151,7 @@ set(SRC
geometry/nodes/node_geo_attribute_sample_texture.cc
geometry/nodes/node_geo_attribute_proximity.cc
geometry/nodes/node_geo_attribute_randomize.cc
+ geometry/nodes/node_geo_attribute_separate_xyz.cc
geometry/nodes/node_geo_attribute_vector_math.cc
geometry/nodes/node_geo_boolean.cc
geometry/nodes/node_geo_collection_info.cc
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 39338ab14dc..8980855fd51 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -28,12 +28,14 @@ void register_node_type_geo_group(void);
void register_node_type_geo_align_rotation_to_vector(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_fill(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);
void register_node_type_geo_attribute_randomize(void);
+void register_node_type_geo_attribute_separate_xyz(void);
void register_node_type_geo_attribute_vector_math(void);
void register_node_type_geo_boolean(void);
void register_node_type_geo_collection_info(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 980790af766..15f078cebf2 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -295,6 +295,8 @@ DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLEC
DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "")
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_PROXIMITY, def_geo_attribute_proximity, "ATTRIBUTE_PROXIMITY", AttributeProximity, "Attribute Proximity", "")
DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "")
+DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_COMBINE_XYZ, def_geo_attribute_combine_xyz, "ATTRIBUTE_COMBINE_XYZ", AttributeCombineXYZ, "Attribute Combine XYZ", "")
+DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_SEPARATE_XYZ, def_geo_attribute_separate_xyz, "ATTRIBUTE_SEPARATE_XYZ", AttributeSeparateXYZ, "Attribute Separate XYZ", "")
/* undefine macros */
#undef DefNode
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc
new file mode 100644
index 00000000000..a231b4f9e92
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc
@@ -0,0 +1,135 @@
+/*
+ * 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_combine_xyz_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {SOCK_STRING, N_("X")},
+ {SOCK_FLOAT, N_("X"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
+ {SOCK_STRING, N_("Y")},
+ {SOCK_FLOAT, N_("Y"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
+ {SOCK_STRING, N_("Z")},
+ {SOCK_FLOAT, N_("Z"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
+ {SOCK_STRING, N_("Result")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_attribute_combine_xyz_out[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static void geo_node_attribute_combine_xyz_layout(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "input_type_x", 0, IFACE_("Type X"), ICON_NONE);
+ uiItemR(layout, ptr, "input_type_y", 0, IFACE_("Type Y"), ICON_NONE);
+ uiItemR(layout, ptr, "input_type_z", 0, IFACE_("Type Z"), ICON_NONE);
+}
+
+namespace blender::nodes {
+
+static void geo_node_attribute_combine_xyz_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeAttributeCombineXYZ *data = (NodeAttributeCombineXYZ *)MEM_callocN(
+ sizeof(NodeAttributeCombineXYZ), __func__);
+
+ data->input_type_x = GEO_NODE_ATTRIBUTE_INPUT_FLOAT;
+ data->input_type_y = GEO_NODE_ATTRIBUTE_INPUT_FLOAT;
+ data->input_type_z = GEO_NODE_ATTRIBUTE_INPUT_FLOAT;
+ node->storage = data;
+}
+
+static void geo_node_attribute_combine_xyz_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAttributeCombineXYZ *node_storage = (NodeAttributeCombineXYZ *)node->storage;
+ update_attribute_input_socket_availabilities(
+ *node, "X", (GeometryNodeAttributeInputMode)node_storage->input_type_x);
+ update_attribute_input_socket_availabilities(
+ *node, "Y", (GeometryNodeAttributeInputMode)node_storage->input_type_y);
+ update_attribute_input_socket_availabilities(
+ *node, "Z", (GeometryNodeAttributeInputMode)node_storage->input_type_z);
+}
+
+static void combine_attributes(GeometryComponent &component, const GeoNodeExecParams &params)
+{
+ const std::string result_name = params.get_input<std::string>("Result");
+ /* The result domain is always point for now. */
+ const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
+ if (result_name.empty()) {
+ return;
+ }
+
+ OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
+ result_name, result_domain, CD_PROP_FLOAT3);
+ if (!attribute_result) {
+ return;
+ }
+ FloatReadAttribute attribute_x = params.get_input_attribute<float>(
+ "X", component, result_domain, 0.0f);
+ FloatReadAttribute attribute_y = params.get_input_attribute<float>(
+ "Y", component, result_domain, 0.0f);
+ FloatReadAttribute attribute_z = params.get_input_attribute<float>(
+ "Z", component, result_domain, 0.0f);
+
+ MutableSpan<float3> results = attribute_result->get_span_for_write_only<float3>();
+ for (const int i : results.index_range()) {
+ const float x = attribute_x[i];
+ const float y = attribute_y[i];
+ const float z = attribute_z[i];
+ const float3 result = float3(x, y, z);
+ results[i] = result;
+ }
+ attribute_result.apply_span_and_save();
+}
+
+static void geo_node_attribute_combine_xyz_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+ if (geometry_set.has<MeshComponent>()) {
+ combine_attributes(geometry_set.get_component_for_write<MeshComponent>(), params);
+ }
+ if (geometry_set.has<PointCloudComponent>()) {
+ combine_attributes(geometry_set.get_component_for_write<PointCloudComponent>(), params);
+ }
+
+ params.set_output("Geometry", geometry_set);
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_attribute_combine_xyz()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_ATTRIBUTE_COMBINE_XYZ, "Attribute Combine XYZ", NODE_CLASS_ATTRIBUTE, 0);
+ node_type_socket_templates(
+ &ntype, geo_node_attribute_combine_xyz_in, geo_node_attribute_combine_xyz_out);
+ node_type_init(&ntype, blender::nodes::geo_node_attribute_combine_xyz_init);
+ node_type_update(&ntype, blender::nodes::geo_node_attribute_combine_xyz_update);
+ node_type_storage(
+ &ntype, "NodeAttributeCombineXYZ", node_free_standard_storage, node_copy_standard_storage);
+ ntype.geometry_node_execute = blender::nodes::geo_node_attribute_combine_xyz_exec;
+ ntype.draw_buttons = geo_node_attribute_combine_xyz_layout;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc
new file mode 100644
index 00000000000..07941f7db79
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc
@@ -0,0 +1,148 @@
+/*
+ * 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 "DNA_material_types.h"
+
+#include "node_geometry_util.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static bNodeSocketTemplate geo_node_attribute_separate_xyz_in[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {SOCK_STRING, N_("Vector")},
+ {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ {SOCK_STRING, N_("Result X")},
+ {SOCK_STRING, N_("Result Y")},
+ {SOCK_STRING, N_("Result Z")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_attribute_separate_xyz_out[] = {
+ {SOCK_GEOMETRY, N_("Geometry")},
+ {-1, ""},
+};
+
+static void geo_node_attribute_separate_xyz_layout(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE);
+}
+
+namespace blender::nodes {
+
+static void geo_node_attribute_separate_xyz_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeAttributeSeparateXYZ *data = (NodeAttributeSeparateXYZ *)MEM_callocN(
+ sizeof(NodeAttributeSeparateXYZ), __func__);
+ data->input_type = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE;
+ node->storage = data;
+}
+
+static void geo_node_attribute_separate_xyz_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeAttributeSeparateXYZ *node_storage = (NodeAttributeSeparateXYZ *)node->storage;
+ update_attribute_input_socket_availabilities(
+ *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type);
+}
+
+static void extract_input(const int index, const Span<float3> &input, MutableSpan<float> result)
+{
+ for (const int i : result.index_range()) {
+ /* Get the component of the float3. (0: X, 1: Y, 2: Z). */
+ const float component = input[i][index];
+ result[i] = component;
+ }
+}
+
+static void separate_attribute(GeometryComponent &component, const GeoNodeExecParams &params)
+{
+ const std::string result_name_x = params.get_input<std::string>("Result X");
+ const std::string result_name_y = params.get_input<std::string>("Result Y");
+ const std::string result_name_z = params.get_input<std::string>("Result Z");
+ /* The node is only for float3 to float conversions. */
+ const CustomDataType input_type = CD_PROP_FLOAT3;
+ const CustomDataType result_type = CD_PROP_FLOAT;
+ /* The result domain is always point for now. */
+ const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
+
+ /* No output to write to. */
+ if (result_name_x.empty() && result_name_y.empty() && result_name_z.empty()) {
+ return;
+ }
+
+ ReadAttributePtr attribute_input = params.get_input_attribute(
+ "Vector", component, result_domain, input_type, nullptr);
+ if (!attribute_input) {
+ return;
+ }
+ const Span<float3> input_span = attribute_input->get_span<float3>();
+
+ OutputAttributePtr attribute_result_x = component.attribute_try_get_for_output(
+ result_name_x, result_domain, result_type);
+ OutputAttributePtr attribute_result_y = component.attribute_try_get_for_output(
+ result_name_y, result_domain, result_type);
+ OutputAttributePtr attribute_result_z = component.attribute_try_get_for_output(
+ result_name_z, result_domain, result_type);
+
+ /* Only extract the components for the outputs with a given attribute. */
+ if (attribute_result_x) {
+ extract_input(0, input_span, attribute_result_x->get_span_for_write_only<float>());
+ attribute_result_x.apply_span_and_save();
+ }
+ if (attribute_result_y) {
+ extract_input(1, input_span, attribute_result_y->get_span_for_write_only<float>());
+ attribute_result_y.apply_span_and_save();
+ }
+ if (attribute_result_z) {
+ extract_input(2, input_span, attribute_result_z->get_span_for_write_only<float>());
+ attribute_result_z.apply_span_and_save();
+ }
+}
+
+static void geo_node_attribute_separate_xyz_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+
+ if (geometry_set.has<MeshComponent>()) {
+ separate_attribute(geometry_set.get_component_for_write<MeshComponent>(), params);
+ }
+ if (geometry_set.has<PointCloudComponent>()) {
+ separate_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params);
+ }
+
+ params.set_output("Geometry", geometry_set);
+}
+
+} // namespace blender::nodes
+
+void register_node_type_geo_attribute_separate_xyz()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(
+ &ntype, GEO_NODE_ATTRIBUTE_SEPARATE_XYZ, "Attribute Separate XYZ", NODE_CLASS_ATTRIBUTE, 0);
+ node_type_socket_templates(
+ &ntype, geo_node_attribute_separate_xyz_in, geo_node_attribute_separate_xyz_out);
+ node_type_init(&ntype, blender::nodes::geo_node_attribute_separate_xyz_init);
+ node_type_update(&ntype, blender::nodes::geo_node_attribute_separate_xyz_update);
+ node_type_storage(
+ &ntype, "NodeAttributeSeparateXYZ", node_free_standard_storage, node_copy_standard_storage);
+ ntype.geometry_node_execute = blender::nodes::geo_node_attribute_separate_xyz_exec;
+ ntype.draw_buttons = geo_node_attribute_separate_xyz_layout;
+ nodeRegisterType(&ntype);
+}