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/nodes/geometry/nodes/node_geo_delete_geometry.cc')
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc342
1 files changed, 240 insertions, 102 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index d07644f8403..1de809b30e4 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -29,63 +29,26 @@
#include "node_geometry_util.hh"
-using blender::bke::CustomDataAttributes;
-
-/* Code from the mask modifier in MOD_mask.cc. */
-extern void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh,
- Mesh &dst_mesh,
- blender::Span<int> vertex_map);
-extern void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
- Mesh &dst_mesh,
- blender::Span<int> vertex_map,
- blender::Span<int> edge_map);
-extern void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
- Mesh &dst_mesh,
- blender::Span<int> vertex_map,
- blender::Span<int> edge_map,
- blender::Span<int> masked_poly_indices,
- blender::Span<int> new_loop_starts);
-
namespace blender::nodes {
-static void geo_node_delete_geometry_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Geometry>(N_("Geometry"));
- b.add_input<decl::Bool>(N_("Selection"))
- .default_value(true)
- .hide_value()
- .supports_field()
- .description(N_("The parts of the geometry to be deleted"));
- b.add_output<decl::Geometry>(N_("Geometry"));
-}
+using blender::bke::CustomDataAttributes;
-static void geo_node_delete_geometry_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+template<typename T>
+static void copy_data_based_on_mask(Span<T> data, MutableSpan<T> r_data, IndexMask mask)
{
- const bNode *node = static_cast<bNode *>(ptr->data);
- const NodeGeometryDeleteGeometry &storage = *(const NodeGeometryDeleteGeometry *)node->storage;
- const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
-
- uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
- /* Only show the mode when it is relevant. */
- if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE)) {
- uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+ for (const int i_out : mask.index_range()) {
+ r_data[i_out] = data[mask[i_out]];
}
}
-static void geo_node_delete_geometry_init(bNodeTree *UNUSED(tree), bNode *node)
-{
- NodeGeometryDeleteGeometry *data = (NodeGeometryDeleteGeometry *)MEM_callocN(
- sizeof(NodeGeometryDeleteGeometry), __func__);
- data->domain = ATTR_DOMAIN_POINT;
- data->mode = GEO_NODE_DELETE_GEOMETRY_MODE_ALL;
-
- node->storage = data;
-}
-
-template<typename T> static void copy_data(Span<T> data, MutableSpan<T> r_data, IndexMask mask)
+template<typename T>
+static void copy_data_based_on_map(Span<T> src, MutableSpan<T> dst, Span<int> index_map)
{
- for (const int i_out : mask.index_range()) {
- r_data[i_out] = data[mask[i_out]];
+ for (const int i_src : index_map.index_range()) {
+ const int i_dst = index_map[i_src];
+ if (i_dst != -1) {
+ dst[i_dst] = src[i_src];
+ }
}
}
@@ -102,23 +65,6 @@ static IndexMask index_mask_indices(Span<bool> mask, const bool invert, Vector<i
return IndexMask(indices);
}
-/** Utility function for making an IndexMask from an array of integers, where the negative integers
- * are seen as false. The indices vector should live at least as long as the returned IndexMask.
- */
-static IndexMask index_mask_indices(Span<int> mask,
- const int num_indices,
- Vector<int64_t> &indices)
-{
- indices.clear();
- indices.reserve(num_indices);
- for (const int i : mask.index_range()) {
- if (mask[i] >= 0) {
- indices.append_unchecked(i);
- }
- }
- return IndexMask(indices);
-}
-
/**
* Copies the attributes with a domain in `domains` to `result_component`.
*/
@@ -191,12 +137,87 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
using T = decltype(dummy);
VArray_Span<T> span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.as_span<T>();
- copy_data(span, out_span, mask);
+ copy_data_based_on_mask(span, out_span, mask);
});
result_attribute.save();
}
}
+static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind> &attributes,
+ const GeometryComponent &in_component,
+ GeometryComponent &result_component,
+ const AttributeDomain domain,
+ const Span<int> index_map)
+{
+ for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
+ const AttributeIDRef attribute_id = entry.key;
+ ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id);
+ if (!attribute) {
+ continue;
+ }
+
+ /* Only copy if it is on a domain we want. */
+ if (domain != attribute.domain) {
+ continue;
+ }
+ const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
+
+ OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
+ attribute_id, attribute.domain, data_type);
+
+ if (!result_attribute) {
+ continue;
+ }
+
+ attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
+ using T = decltype(dummy);
+ VArray_Span<T> span{attribute.varray.typed<T>()};
+ MutableSpan<T> out_span = result_attribute.as_span<T>();
+ copy_data_based_on_map(span, out_span, index_map);
+ });
+ result_attribute.save();
+ }
+}
+
+static void copy_face_corner_attributes(const Map<AttributeIDRef, AttributeKind> &attributes,
+ const GeometryComponent &in_component,
+ GeometryComponent &out_component,
+ const int num_selected_loops,
+ const Span<int> selected_poly_indices,
+ const Mesh &mesh_in)
+{
+ Vector<int64_t> indices;
+ indices.reserve(num_selected_loops);
+ for (const int src_poly_index : selected_poly_indices) {
+ const MPoly &src_poly = mesh_in.mpoly[src_poly_index];
+ const int src_loop_start = src_poly.loopstart;
+ const int tot_loop = src_poly.totloop;
+ for (const int i : IndexRange(tot_loop)) {
+ indices.append_unchecked(src_loop_start + i);
+ }
+ }
+ copy_attributes_based_on_mask(
+ attributes, in_component, out_component, ATTR_DOMAIN_CORNER, IndexMask(indices));
+}
+
+static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map)
+{
+ BLI_assert(src_mesh.totvert == vertex_map.size());
+ for (const int i_src : vertex_map.index_range()) {
+ const int i_dst = vertex_map[i_src];
+ if (i_dst == -1) {
+ continue;
+ }
+
+ const MVert &v_src = src_mesh.mvert[i_src];
+ MVert &v_dst = dst_mesh.mvert[i_dst];
+
+ v_dst = v_src;
+ }
+}
+
static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh, Span<int> edge_map)
{
BLI_assert(src_mesh.totedge == edge_map.size());
@@ -215,6 +236,28 @@ static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh, Mesh &dst_mesh,
}
}
+static void copy_masked_edges_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map,
+ Span<int> edge_map)
+{
+ BLI_assert(src_mesh.totvert == vertex_map.size());
+ BLI_assert(src_mesh.totedge == edge_map.size());
+ for (const int i_src : IndexRange(src_mesh.totedge)) {
+ const int i_dst = edge_map[i_src];
+ if (i_dst == -1) {
+ continue;
+ }
+
+ const MEdge &e_src = src_mesh.medge[i_src];
+ MEdge &e_dst = dst_mesh.medge[i_dst];
+
+ e_dst = e_src;
+ e_dst.v1 = vertex_map[e_src.v1];
+ e_dst.v2 = vertex_map[e_src.v2];
+ }
+}
+
/* Faces and edges changed but vertices are the same. */
static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
Mesh &dst_mesh,
@@ -268,29 +311,56 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
}
}
+static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
+ Mesh &dst_mesh,
+ Span<int> vertex_map,
+ Span<int> edge_map,
+ Span<int> masked_poly_indices,
+ Span<int> new_loop_starts)
+{
+ for (const int i_dst : masked_poly_indices.index_range()) {
+ const int i_src = masked_poly_indices[i_dst];
+
+ const MPoly &mp_src = src_mesh.mpoly[i_src];
+ MPoly &mp_dst = dst_mesh.mpoly[i_dst];
+ const int i_ml_src = mp_src.loopstart;
+ const int i_ml_dst = new_loop_starts[i_dst];
+
+ const MLoop *ml_src = src_mesh.mloop + i_ml_src;
+ MLoop *ml_dst = dst_mesh.mloop + i_ml_dst;
+
+ mp_dst = mp_src;
+ mp_dst.loopstart = i_ml_dst;
+ for (int i : IndexRange(mp_src.totloop)) {
+ ml_dst[i].v = vertex_map[ml_src[i].v];
+ ml_dst[i].e = edge_map[ml_src[i].e];
+ }
+ }
+}
+
static void spline_copy_builtin_attributes(const Spline &spline,
Spline &r_spline,
const IndexMask mask)
{
- copy_data(spline.positions(), r_spline.positions(), mask);
- copy_data(spline.radii(), r_spline.radii(), mask);
- copy_data(spline.tilts(), r_spline.tilts(), mask);
+ copy_data_based_on_mask(spline.positions(), r_spline.positions(), mask);
+ copy_data_based_on_mask(spline.radii(), r_spline.radii(), mask);
+ copy_data_based_on_mask(spline.tilts(), r_spline.tilts(), mask);
switch (spline.type()) {
case Spline::Type::Poly:
break;
case Spline::Type::Bezier: {
const BezierSpline &src = static_cast<const BezierSpline &>(spline);
BezierSpline &dst = static_cast<BezierSpline &>(r_spline);
- copy_data(src.handle_positions_left(), dst.handle_positions_left(), mask);
- copy_data(src.handle_positions_right(), dst.handle_positions_right(), mask);
- copy_data(src.handle_types_left(), dst.handle_types_left(), mask);
- copy_data(src.handle_types_right(), dst.handle_types_right(), mask);
+ copy_data_based_on_mask(src.handle_positions_left(), dst.handle_positions_left(), mask);
+ copy_data_based_on_mask(src.handle_positions_right(), dst.handle_positions_right(), mask);
+ copy_data_based_on_mask(src.handle_types_left(), dst.handle_types_left(), mask);
+ copy_data_based_on_mask(src.handle_types_right(), dst.handle_types_right(), mask);
break;
}
case Spline::Type::NURBS: {
const NURBSpline &src = static_cast<const NURBSpline &>(spline);
NURBSpline &dst = static_cast<NURBSpline &>(r_spline);
- copy_data(src.weights(), dst.weights(), mask);
+ copy_data_based_on_mask(src.weights(), dst.weights(), mask);
break;
}
}
@@ -316,7 +386,7 @@ static void copy_dynamic_attributes(const CustomDataAttributes &src,
attribute_math::convert_to_static_type(new_attribute->type(), [&](auto dummy) {
using T = decltype(dummy);
- copy_data(src_attribute->typed<T>(), new_attribute->typed<T>(), mask);
+ copy_data_based_on_mask(src_attribute->typed<T>(), new_attribute->typed<T>(), mask);
});
return true;
},
@@ -986,6 +1056,23 @@ static void do_mesh_separation(GeometrySet &geometry_set,
copy_masked_edges_to_new_mesh(mesh_in, *mesh_out, vertex_map, edge_map);
copy_masked_polys_to_new_mesh(
mesh_in, *mesh_out, vertex_map, edge_map, selected_poly_indices, new_loop_starts);
+
+ /* Copy attributes. */
+ copy_attributes_based_on_map(
+ attributes, in_component, out_component, ATTR_DOMAIN_POINT, vertex_map);
+ copy_attributes_based_on_map(
+ attributes, in_component, out_component, ATTR_DOMAIN_EDGE, edge_map);
+ copy_attributes_based_on_mask(attributes,
+ in_component,
+ out_component,
+ ATTR_DOMAIN_FACE,
+ IndexMask(Vector<int64_t>(selected_poly_indices.as_span())));
+ copy_face_corner_attributes(attributes,
+ in_component,
+ out_component,
+ num_selected_loops,
+ selected_poly_indices,
+ mesh_in);
break;
}
case GEO_NODE_DELETE_GEOMETRY_MODE_EDGE_FACE: {
@@ -1041,22 +1128,25 @@ static void do_mesh_separation(GeometrySet &geometry_set,
/* Copy the selected parts of the mesh over to the new mesh. */
memcpy(mesh_out->mvert, mesh_in.mvert, mesh_in.totvert * sizeof(MVert));
- copy_attributes(attributes, in_component, out_component, {ATTR_DOMAIN_POINT});
copy_masked_edges_to_new_mesh(mesh_in, *mesh_out, edge_map);
copy_masked_polys_to_new_mesh(
mesh_in, *mesh_out, edge_map, selected_poly_indices, new_loop_starts);
- Vector<int64_t> indices;
+
+ /* Copy attributes. */
+ copy_attributes(attributes, in_component, out_component, {ATTR_DOMAIN_POINT});
+ copy_attributes_based_on_map(
+ attributes, in_component, out_component, ATTR_DOMAIN_EDGE, edge_map);
copy_attributes_based_on_mask(attributes,
in_component,
out_component,
- ATTR_DOMAIN_EDGE,
- index_mask_indices(edge_map, num_selected_edges, indices));
- copy_attributes_based_on_mask(
- attributes,
- in_component,
- out_component,
- ATTR_DOMAIN_FACE,
- index_mask_indices(selected_poly_indices, num_selected_polys, indices));
+ ATTR_DOMAIN_FACE,
+ IndexMask(Vector<int64_t>(selected_poly_indices.as_span())));
+ copy_face_corner_attributes(attributes,
+ in_component,
+ out_component,
+ num_selected_loops,
+ selected_poly_indices,
+ mesh_in);
break;
}
case GEO_NODE_DELETE_GEOMETRY_MODE_ONLY_FACE: {
@@ -1100,14 +1190,22 @@ static void do_mesh_separation(GeometrySet &geometry_set,
/* Copy the selected parts of the mesh over to the new mesh. */
memcpy(mesh_out->mvert, mesh_in.mvert, mesh_in.totvert * sizeof(MVert));
memcpy(mesh_out->medge, mesh_in.medge, mesh_in.totedge * sizeof(MEdge));
+ copy_masked_polys_to_new_mesh(mesh_in, *mesh_out, selected_poly_indices, new_loop_starts);
+
+ /* Copy attributes. */
copy_attributes(
attributes, in_component, out_component, {ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE});
- copy_masked_polys_to_new_mesh(mesh_in, *mesh_out, selected_poly_indices, new_loop_starts);
- Vector<int64_t> indices;
- const IndexMask mask = index_mask_indices(
- selected_poly_indices, num_selected_polys, indices);
- copy_attributes_based_on_mask(
- attributes, in_component, out_component, ATTR_DOMAIN_FACE, mask);
+ copy_attributes_based_on_mask(attributes,
+ in_component,
+ out_component,
+ ATTR_DOMAIN_FACE,
+ IndexMask(Vector<int64_t>(selected_poly_indices.as_span())));
+ copy_face_corner_attributes(attributes,
+ in_component,
+ out_component,
+ num_selected_loops,
+ selected_poly_indices,
+ mesh_in);
break;
}
}
@@ -1177,17 +1275,55 @@ void separate_geometry(GeometrySet &geometry_set,
r_is_error = !some_valid_domain && geometry_set.has_realized_data();
}
-static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
+} // namespace blender::nodes
+
+namespace blender::nodes::node_geo_delete_geometry_cc {
+
+NODE_STORAGE_FUNCS(NodeGeometryDeleteGeometry)
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>(N_("Geometry"));
+ b.add_input<decl::Bool>(N_("Selection"))
+ .default_value(true)
+ .hide_value()
+ .supports_field()
+ .description(N_("The parts of the geometry to be deleted"));
+ b.add_output<decl::Geometry>(N_("Geometry"));
+}
+
+static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ const bNode *node = static_cast<bNode *>(ptr->data);
+ const NodeGeometryDeleteGeometry &storage = node_storage(*node);
+ const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
+
+ uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
+ /* Only show the mode when it is relevant. */
+ if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE)) {
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+ }
+}
+
+static void node_init(bNodeTree *UNUSED(tree), bNode *node)
+{
+ NodeGeometryDeleteGeometry *data = (NodeGeometryDeleteGeometry *)MEM_callocN(
+ sizeof(NodeGeometryDeleteGeometry), __func__);
+ data->domain = ATTR_DOMAIN_POINT;
+ data->mode = GEO_NODE_DELETE_GEOMETRY_MODE_ALL;
+
+ node->storage = data;
+}
+
+static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
- const bNode &node = params.node();
- const NodeGeometryDeleteGeometry &storage = *(const NodeGeometryDeleteGeometry *)node.storage;
+ const NodeGeometryDeleteGeometry &storage = node_storage(params.node());
const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
- const GeometryNodeDeleteGeometryMode mode = static_cast<GeometryNodeDeleteGeometryMode>(
- storage.mode);
+ const GeometryNodeDeleteGeometryMode mode = (GeometryNodeDeleteGeometryMode)storage.mode;
bool all_is_error = false;
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
@@ -1204,10 +1340,12 @@ static void geo_node_delete_geometry_exec(GeoNodeExecParams params)
params.set_output("Geometry", std::move(geometry_set));
}
-} // namespace blender::nodes
+} // namespace blender::nodes::node_geo_delete_geometry_cc
void register_node_type_geo_delete_geometry()
{
+ namespace file_ns = blender::nodes::node_geo_delete_geometry_cc;
+
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_DELETE_GEOMETRY, "Delete Geometry", NODE_CLASS_GEOMETRY, 0);
@@ -1217,10 +1355,10 @@ void register_node_type_geo_delete_geometry()
node_free_standard_storage,
node_copy_standard_storage);
- node_type_init(&ntype, blender::nodes::geo_node_delete_geometry_init);
+ node_type_init(&ntype, file_ns::node_init);
- ntype.declare = blender::nodes::geo_node_delete_geometry_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_delete_geometry_exec;
- ntype.draw_buttons = blender::nodes::geo_node_delete_geometry_layout;
+ ntype.declare = file_ns::node_declare;
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}