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')
-rw-r--r--source/blender/blenloader/intern/versioning_300.c17
-rw-r--r--source/blender/makesdna/DNA_node_types.h10
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c26
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc64
5 files changed, 112 insertions, 7 deletions
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 5ba7dc74e3d..dd3412d6c83 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -2648,5 +2648,22 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
+
+ /* Add node storage for the merge by distance node. */
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_GEOMETRY) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (node->type == GEO_NODE_MERGE_BY_DISTANCE) {
+ if (node->storage == NULL) {
+ NodeGeometryMergeByDistance *data = MEM_callocN(sizeof(NodeGeometryMergeByDistance),
+ __func__);
+ data->mode = GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL;
+ node->storage = data;
+ }
+ }
+ }
+ }
+ }
+ FOREACH_NODETREE_END;
}
}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 73539bea8ee..ff7686d87af 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1296,6 +1296,11 @@ typedef struct NodeGeometryMeshCone {
uint8_t fill_type;
} NodeGeometryMeshCone;
+typedef struct NodeGeometryMergeByDistance {
+ /* GeometryNodeMergeByDistanceMode. */
+ uint8_t mode;
+} NodeGeometryMergeByDistance;
+
typedef struct NodeGeometryMeshLine {
/* GeometryNodeMeshLineMode. */
uint8_t mode;
@@ -2007,6 +2012,11 @@ typedef enum GeometryNodeMeshCircleFillType {
GEO_NODE_MESH_CIRCLE_FILL_TRIANGLE_FAN = 2,
} GeometryNodeMeshCircleFillType;
+typedef enum GeometryNodeMergeByDistanceMode {
+ GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL = 0,
+ GEO_NODE_MERGE_BY_DISTANCE_MODE_CONNECTED = 1,
+} GeometryNodeMergeByDistanceMode;
+
typedef enum GeometryNodeMeshLineMode {
GEO_NODE_MESH_LINE_MODE_END_POINTS = 0,
GEO_NODE_MESH_LINE_MODE_OFFSET = 1,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index cbac6aefc10..31b2d36dcfd 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -9846,6 +9846,32 @@ static void def_geo_mesh_cone(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
+static void def_geo_merge_by_distance(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem mode_items[] = {
+ {GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL,
+ "ALL",
+ 0,
+ "All",
+ "Merge all close selected points, whether or not they are connected"},
+ {GEO_NODE_MERGE_BY_DISTANCE_MODE_CONNECTED,
+ "CONNECTED",
+ 0,
+ "Connected",
+ "Only merge mesh vertices along existing edges. This method can be much faster"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_struct_sdna_from(srna, "NodeGeometryMergeByDistance", "storage");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
+}
+
static void def_geo_mesh_line(StructRNA *srna)
{
PropertyRNA *prop;
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 0cc5b2d541d..b45097a4ed1 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -334,7 +334,7 @@ DefNode(GeometryNode, GEO_NODE_INSTANCES_TO_POINTS, 0, "INSTANCES_TO_POINTS", In
DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "")
DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "")
DefNode(GeometryNode, GEO_NODE_MATERIAL_SELECTION, 0, "MATERIAL_SELECTION", MaterialSelection, "Material Selection", "")
-DefNode(GeometryNode, GEO_NODE_MERGE_BY_DISTANCE, 0, "MERGE_BY_DISTANCE", MergeByDistance, "Merge by Distance", "")
+DefNode(GeometryNode, GEO_NODE_MERGE_BY_DISTANCE, def_geo_merge_by_distance, "MERGE_BY_DISTANCE", MergeByDistance, "Merge by Distance", "")
DefNode(GeometryNode, GEO_NODE_MESH_BOOLEAN, def_geo_boolean, "MESH_BOOLEAN", MeshBoolean, "Mesh Boolean", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CIRCLE, def_geo_mesh_circle, "MESH_PRIMITIVE_CIRCLE", MeshCircle, "Mesh Circle", "")
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_CONE, def_geo_mesh_cone, "MESH_PRIMITIVE_CONE", MeshCone, "Cone", "")
diff --git a/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc b/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc
index 4b9b2064915..1ec97858d4d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc
@@ -3,10 +3,15 @@
#include "GEO_mesh_merge_by_distance.hh"
#include "GEO_point_merge_by_distance.hh"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_merge_by_distance_cc {
+NODE_STORAGE_FUNCS(NodeGeometryMergeByDistance)
+
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"))
@@ -16,6 +21,20 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Geometry>(N_("Geometry"));
}
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+}
+
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeGeometryMergeByDistance *data = MEM_cnew<NodeGeometryMergeByDistance>(__func__);
+ data->mode = GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL;
+ node->storage = data;
+}
+
static PointCloud *pointcloud_merge_by_distance(const PointCloudComponent &src_points,
const float merge_distance,
const Field<bool> &selection_field)
@@ -34,9 +53,24 @@ static PointCloud *pointcloud_merge_by_distance(const PointCloudComponent &src_p
return geometry::point_merge_by_distance(src_points, merge_distance, selection);
}
-static std::optional<Mesh *> mesh_merge_by_distance(const MeshComponent &mesh_component,
- const float merge_distance,
- const Field<bool> &selection_field)
+static std::optional<Mesh *> mesh_merge_by_distance_connected(const MeshComponent &mesh_component,
+ const float merge_distance,
+ const Field<bool> &selection_field)
+{
+ const int src_size = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ Array<bool> selection(src_size);
+ GeometryComponentFieldContext context{mesh_component, ATTR_DOMAIN_POINT};
+ FieldEvaluator evaluator{context, src_size};
+ evaluator.add_with_destination(selection_field, selection.as_mutable_span());
+ evaluator.evaluate();
+
+ const Mesh &mesh = *mesh_component.get_for_read();
+ return geometry::mesh_merge_by_distance_connected(mesh, selection, merge_distance, false);
+}
+
+static std::optional<Mesh *> mesh_merge_by_distance_all(const MeshComponent &mesh_component,
+ const float merge_distance,
+ const Field<bool> &selection_field)
{
const int src_size = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT);
GeometryComponentFieldContext context{mesh_component, ATTR_DOMAIN_POINT};
@@ -55,6 +89,9 @@ static std::optional<Mesh *> mesh_merge_by_distance(const MeshComponent &mesh_co
static void node_geo_exec(GeoNodeExecParams params)
{
+ const NodeGeometryMergeByDistance &storage = node_storage(params.node());
+ const GeometryNodeMergeByDistanceMode mode = (GeometryNodeMergeByDistanceMode)storage.mode;
+
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
const Field<bool> selection = params.extract_input<Field<bool>>("Selection");
@@ -69,8 +106,18 @@ static void node_geo_exec(GeoNodeExecParams params)
}
}
if (geometry_set.has_mesh()) {
- std::optional<Mesh *> result = mesh_merge_by_distance(
- *geometry_set.get_component_for_read<MeshComponent>(), merge_distance, selection);
+ const MeshComponent &component = *geometry_set.get_component_for_read<MeshComponent>();
+ std::optional<Mesh *> result;
+ switch (mode) {
+ case GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL:
+ result = mesh_merge_by_distance_all(component, merge_distance, selection);
+ break;
+ case GEO_NODE_MERGE_BY_DISTANCE_MODE_CONNECTED:
+ result = mesh_merge_by_distance_connected(component, merge_distance, selection);
+ break;
+ default:
+ BLI_assert_unreachable();
+ }
if (result) {
geometry_set.replace_mesh(*result);
}
@@ -89,8 +136,13 @@ void register_node_type_geo_merge_by_distance()
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_MERGE_BY_DISTANCE, "Merge by Distance", NODE_CLASS_GEOMETRY);
-
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_storage(&ntype,
+ "NodeGeometryMergeByDistance",
+ node_free_standard_storage,
+ node_copy_standard_storage);
ntype.declare = file_ns::node_declare;
ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}