Geometry Nodes: Port weld modifier to the merge by distance node
This commit moves the weld modifier code to the geometry module
so that it can be used in the "Merge by Distance" geometry node
from ec1b0c2014
. The "All" mode is exposed in the node
for now, though we could expose the "Connected" mode in the future.
The modifier itself is responsible for creating the selections from
the vertex group. The "All" mode takes an `IndexMask` for the
selection, and the "Connected" mode takes a boolean array,
since it actually iterates over all edges.
Some disabled code for a BVH mode has not been copied over,
it's still accessible through the patches and git history anyway,
and it made the port slightly simpler.
Differential Revision: https://developer.blender.org/D13907
This commit is contained in:
parent
932d8dba52
commit
0ec94d5359
Notes:
blender-bot
2023-03-08 08:04:35 +01:00
Referenced by issue #105556, Weld-vertices modifier crashes when merging N-gons
|
@ -30,10 +30,12 @@ set(INC
|
|||
)
|
||||
|
||||
set(SRC
|
||||
intern/mesh_merge_by_distance.cc
|
||||
intern/mesh_to_curve_convert.cc
|
||||
intern/point_merge_by_distance.cc
|
||||
intern/realize_instances.cc
|
||||
|
||||
GEO_mesh_merge_by_distance.hh
|
||||
GEO_mesh_to_curve.hh
|
||||
GEO_point_merge_by_distance.hh
|
||||
GEO_realize_instances.hh
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
struct Mesh;
|
||||
|
||||
/** \file
|
||||
* \ingroup geo
|
||||
*/
|
||||
|
||||
namespace blender::geometry {
|
||||
|
||||
/**
|
||||
* Merge selected vertices into other selected vertices within the \a merge_distance. The merged
|
||||
* indices favor speed over accuracy, since the results will depend on the order of the vertices.
|
||||
*
|
||||
* \returns std::nullopt if the mesh should not be changed (no vertices are merged), in order to
|
||||
* avoid copying the input. Otherwise returns the new mesh with merged geoemetry.
|
||||
*/
|
||||
std::optional<Mesh *> mesh_merge_by_distance_all(const Mesh &mesh,
|
||||
IndexMask selection,
|
||||
float merge_distance);
|
||||
|
||||
/**
|
||||
* Merge selected vertices along edges to other selected vertices. Only vertices connected by edges
|
||||
* are considered for merging.
|
||||
*
|
||||
* \returns std::nullopt if the mesh should not be changed (no vertices are merged), in order to
|
||||
* avoid copying the input. Otherwise returns the new mesh with merged geoemetry.
|
||||
*/
|
||||
std::optional<Mesh *> mesh_merge_by_distance_connected(const Mesh &mesh,
|
||||
Span<bool> selection,
|
||||
float merge_distance,
|
||||
bool only_loose_edges);
|
||||
|
||||
} // namespace blender::geometry
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -14,6 +14,7 @@
|
|||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "GEO_mesh_merge_by_distance.hh"
|
||||
#include "GEO_point_merge_by_distance.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
@ -22,7 +23,8 @@ namespace blender::nodes::node_geo_merge_by_distance_cc {
|
|||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Geometry>(N_("Geometry")).supported_type({GEO_COMPONENT_TYPE_POINT_CLOUD});
|
||||
b.add_input<decl::Geometry>(N_("Geometry"))
|
||||
.supported_type({GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_MESH});
|
||||
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
|
||||
b.add_input<decl::Float>(N_("Distance")).default_value(0.1f).min(0.0f).subtype(PROP_DISTANCE);
|
||||
b.add_output<decl::Geometry>(N_("Geometry"));
|
||||
|
@ -46,6 +48,25 @@ 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)
|
||||
{
|
||||
const int src_size = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT);
|
||||
GeometryComponentFieldContext context{mesh_component, ATTR_DOMAIN_POINT};
|
||||
FieldEvaluator evaluator{context, src_size};
|
||||
evaluator.add(selection_field);
|
||||
evaluator.evaluate();
|
||||
|
||||
const IndexMask selection = evaluator.get_evaluated_as_mask(0);
|
||||
if (selection.is_empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Mesh &mesh = *mesh_component.get_for_read();
|
||||
return geometry::mesh_merge_by_distance_all(mesh, selection, merge_distance);
|
||||
}
|
||||
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
{
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
|
||||
|
@ -59,6 +80,13 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
*geometry_set.get_component_for_read<PointCloudComponent>(), merge_distance, selection);
|
||||
geometry_set.replace_pointcloud(result);
|
||||
}
|
||||
if (geometry_set.has_mesh()) {
|
||||
std::optional<Mesh *> result = mesh_merge_by_distance(
|
||||
*geometry_set.get_component_for_read<MeshComponent>(), merge_distance, selection);
|
||||
if (result) {
|
||||
geometry_set.replace_mesh(*result);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
params.set_output("Geometry", std::move(geometry_set));
|
||||
|
|
Loading…
Reference in New Issue