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:
authorAleksi Juvani <aleksijuvani>2022-04-07 01:30:56 +0300
committerHans Goudey <h.goudey@me.com>2022-04-07 01:30:56 +0300
commit81ec3dce6542f996e5d61017fab83bd721b61822 (patch)
treed6434658da8830faee00e4614aaa832704975d48
parent181d577d7d97990bf1094710a09c377bad24a8eb (diff)
Geometry Nodes: Add "Connected" mode to Merge by Distance node
Expose the "Connected" mode from the weld modifier in the "Merge by Distance" geometry node. This method only merges vertices along existing edges, but it can be much faster because it doesn't have to build a KD Tree of all selected points. Differential Revision: https://developer.blender.org/D14321
-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);
}