Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_merge_by_distance.cc
| Show All 13 Lines | |||||
| namespace blender::nodes::node_geo_merge_by_distance_cc { | namespace blender::nodes::node_geo_merge_by_distance_cc { | ||||
| NODE_STORAGE_FUNCS(NodeGeometryMergeByDistance) | NODE_STORAGE_FUNCS(NodeGeometryMergeByDistance) | ||||
| static void node_declare(NodeDeclarationBuilder &b) | static void node_declare(NodeDeclarationBuilder &b) | ||||
| { | { | ||||
| b.add_input<decl::Geometry>(N_("Geometry")) | b.add_input<decl::Geometry>(N_("Geometry")) | ||||
| .supported_type({GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_MESH}); | .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::Bool>(N_("Selection")).default_value(true).hide_value().field_on_all(); | ||||
| b.add_input<decl::Float>(N_("Distance")).default_value(0.001f).min(0.0f).subtype(PROP_DISTANCE); | b.add_input<decl::Float>(N_("Distance")).default_value(0.001f).min(0.0f).subtype(PROP_DISTANCE); | ||||
| b.add_output<decl::Geometry>(N_("Geometry")); | b.add_output<decl::Geometry>(N_("Geometry")).propagate_all(); | ||||
| } | } | ||||
| static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) | static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) | ||||
| { | { | ||||
| uiLayoutSetPropSep(layout, true); | uiLayoutSetPropSep(layout, true); | ||||
| uiLayoutSetPropDecorate(layout, false); | uiLayoutSetPropDecorate(layout, false); | ||||
| uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); | uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); | ||||
| } | } | ||||
| static void node_init(bNodeTree * /*tree*/, bNode *node) | static void node_init(bNodeTree * /*tree*/, bNode *node) | ||||
| { | { | ||||
| NodeGeometryMergeByDistance *data = MEM_cnew<NodeGeometryMergeByDistance>(__func__); | NodeGeometryMergeByDistance *data = MEM_cnew<NodeGeometryMergeByDistance>(__func__); | ||||
| data->mode = GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL; | data->mode = GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL; | ||||
| node->storage = data; | node->storage = data; | ||||
| } | } | ||||
| static PointCloud *pointcloud_merge_by_distance(const PointCloud &src_points, | static PointCloud *pointcloud_merge_by_distance( | ||||
| const PointCloud &src_points, | |||||
| const float merge_distance, | const float merge_distance, | ||||
| const Field<bool> &selection_field) | const Field<bool> &selection_field, | ||||
| const AnonymousAttributePropagationInfo &propagation_info) | |||||
| { | { | ||||
| bke::PointCloudFieldContext context{src_points}; | bke::PointCloudFieldContext context{src_points}; | ||||
| FieldEvaluator evaluator{context, src_points.totpoint}; | FieldEvaluator evaluator{context, src_points.totpoint}; | ||||
| evaluator.add(selection_field); | evaluator.add(selection_field); | ||||
| evaluator.evaluate(); | evaluator.evaluate(); | ||||
| const IndexMask selection = evaluator.get_evaluated_as_mask(0); | const IndexMask selection = evaluator.get_evaluated_as_mask(0); | ||||
| if (selection.is_empty()) { | if (selection.is_empty()) { | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| return geometry::point_merge_by_distance(src_points, merge_distance, selection); | return geometry::point_merge_by_distance( | ||||
| src_points, merge_distance, selection, propagation_info); | |||||
| } | } | ||||
| static std::optional<Mesh *> mesh_merge_by_distance_connected(const Mesh &mesh, | static std::optional<Mesh *> mesh_merge_by_distance_connected(const Mesh &mesh, | ||||
| const float merge_distance, | const float merge_distance, | ||||
| const Field<bool> &selection_field) | const Field<bool> &selection_field) | ||||
| { | { | ||||
| Array<bool> selection(mesh.totvert); | Array<bool> selection(mesh.totvert); | ||||
| bke::MeshFieldContext context{mesh, ATTR_DOMAIN_POINT}; | bke::MeshFieldContext context{mesh, ATTR_DOMAIN_POINT}; | ||||
| Show All 28 Lines | static void node_geo_exec(GeoNodeExecParams params) | ||||
| GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); | GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); | ||||
| const Field<bool> selection = params.extract_input<Field<bool>>("Selection"); | const Field<bool> selection = params.extract_input<Field<bool>>("Selection"); | ||||
| const float merge_distance = params.extract_input<float>("Distance"); | const float merge_distance = params.extract_input<float>("Distance"); | ||||
| geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { | ||||
| if (const PointCloud *pointcloud = geometry_set.get_pointcloud_for_read()) { | if (const PointCloud *pointcloud = geometry_set.get_pointcloud_for_read()) { | ||||
| PointCloud *result = pointcloud_merge_by_distance(*pointcloud, merge_distance, selection); | PointCloud *result = pointcloud_merge_by_distance( | ||||
| *pointcloud, merge_distance, selection, params.get_output_propagation_info("Geometry")); | |||||
| if (result) { | if (result) { | ||||
| geometry_set.replace_pointcloud(result); | geometry_set.replace_pointcloud(result); | ||||
| } | } | ||||
| } | } | ||||
| if (const Mesh *mesh = geometry_set.get_mesh_for_read()) { | if (const Mesh *mesh = geometry_set.get_mesh_for_read()) { | ||||
| std::optional<Mesh *> result; | std::optional<Mesh *> result; | ||||
| switch (mode) { | switch (mode) { | ||||
| case GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL: | case GEO_NODE_MERGE_BY_DISTANCE_MODE_ALL: | ||||
| Show All 36 Lines | |||||