Refactor: GEO: Mesh selection header file

Share code of geometry processing of mesh selection.
For now, `mesh_copy_selection` is only user of this code,
but in #115142 this will also be used.

Pull Request: https://projects.blender.org/blender/blender/pulls/115376
This commit is contained in:
Iliya Katueshenock 2023-11-25 13:41:17 +01:00 committed by Hans Goudey
parent 42ddc13033
commit 361174b588
4 changed files with 150 additions and 91 deletions

View File

@ -26,6 +26,7 @@ set(SRC
intern/mesh_primitive_grid.cc
intern/mesh_primitive_line.cc
intern/mesh_primitive_uv_sphere.cc
intern/mesh_selection.cc
intern/mesh_split_edges.cc
intern/mesh_to_curve_convert.cc
intern/mesh_to_volume.cc
@ -52,6 +53,7 @@ set(SRC
GEO_mesh_primitive_grid.hh
GEO_mesh_primitive_line.hh
GEO_mesh_primitive_uv_sphere.hh
GEO_mesh_selection.hh
GEO_mesh_split_edges.hh
GEO_mesh_to_curve.hh
GEO_mesh_to_volume.hh

View File

@ -0,0 +1,51 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_index_mask.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_offset_indices.hh"
#include "BLI_span.hh"
namespace blender::geometry {
/** A vertex is selected if it's used by a selected edge. */
IndexMask vert_selection_from_edge(Span<int2> edges,
const IndexMask &edge_mask,
int verts_num,
IndexMaskMemory &memory);
/** A vertex is selected if it is used by a selected face. */
IndexMask vert_selection_from_face(OffsetIndices<int> faces,
const IndexMask &face_mask,
Span<int> corner_verts,
int verts_num,
IndexMaskMemory &memory);
/** An edge is selected if it is used by a selected face. */
IndexMask edge_selection_from_face(OffsetIndices<int> faces,
const IndexMask &face_mask,
Span<int> corner_edges,
int edges_num,
IndexMaskMemory &memory);
/** An edge is selected if both of its vertices are selected. */
IndexMask edge_selection_from_vert(Span<int2> edges,
Span<bool> vert_selection,
IndexMaskMemory &memory);
/** A face is selected if all of its vertices are selected. */
IndexMask face_selection_from_vert(OffsetIndices<int> faces,
Span<int> corner_verts,
Span<bool> vert_selection,
IndexMaskMemory &memory);
/** A face is selected if all of its edges are selected. */
IndexMask face_selection_from_edge(OffsetIndices<int> faces,
Span<int> corner_edges,
Span<bool> edge_mask,
IndexMaskMemory &memory);
} // namespace blender::geometry

View File

@ -13,6 +13,7 @@
#include "BKE_mesh.hh"
#include "GEO_mesh_copy_selection.hh"
#include "GEO_mesh_selection.hh"
namespace blender::geometry {
@ -76,97 +77,6 @@ static void remap_edges(const OffsetIndices<int> src_faces,
});
}
/** A vertex is selected if it's used by a selected edge. */
static IndexMask vert_selection_from_edge(const Span<int2> edges,
const IndexMask &edge_mask,
const int verts_num,
IndexMaskMemory &memory)
{
Array<bool> array(verts_num, false);
edge_mask.foreach_index_optimized<int>(GrainSize(4096), [&](const int i) {
array[edges[i][0]] = true;
array[edges[i][1]] = true;
});
return IndexMask::from_bools(array, memory);
}
static IndexMask mapped_corner_selection_from_face(const OffsetIndices<int> faces,
const IndexMask &face_mask,
const Span<int> corner_verts_or_edges,
const int verts_or_edges_num,
IndexMaskMemory &memory)
{
Array<bool> array(verts_or_edges_num, false);
face_mask.foreach_index(GrainSize(512), [&](const int64_t i) {
array.as_mutable_span().fill_indices(corner_verts_or_edges.slice(faces[i]), true);
});
return IndexMask::from_bools(array, memory);
}
/** A vertex is selected if it is used by a selected face. */
static IndexMask vert_selection_from_face(const OffsetIndices<int> faces,
const IndexMask &face_mask,
const Span<int> corner_verts,
const int verts_num,
IndexMaskMemory &memory)
{
return mapped_corner_selection_from_face(faces, face_mask, corner_verts, verts_num, memory);
}
/** An edge is selected if it is used by a selected face. */
static IndexMask edge_selection_from_face(const OffsetIndices<int> faces,
const IndexMask &face_mask,
const Span<int> corner_edges,
const int edges_num,
IndexMaskMemory &memory)
{
return mapped_corner_selection_from_face(faces, face_mask, corner_edges, edges_num, memory);
}
/** An edge is selected if both of its vertices are selected. */
static IndexMask edge_selection_from_vert(const Span<int2> edges,
const Span<bool> vert_selection,
IndexMaskMemory &memory)
{
return IndexMask::from_predicate(
edges.index_range(), GrainSize(1024), memory, [&](const int64_t i) {
const int2 edge = edges[i];
return vert_selection[edge[0]] && vert_selection[edge[1]];
});
}
static IndexMask face_selection_from_mapped_corner(const OffsetIndices<int> faces,
const Span<int> corner_verts_or_edges,
const Span<bool> vert_or_edge_selection,
IndexMaskMemory &memory)
{
return IndexMask::from_predicate(
faces.index_range(), GrainSize(1024), memory, [&](const int64_t i) {
const Span<int> indices = corner_verts_or_edges.slice(faces[i]);
return std::all_of(indices.begin(), indices.end(), [&](const int i) {
return vert_or_edge_selection[i];
});
});
}
/** A face is selected if all of its vertices are selected. */
static IndexMask face_selection_from_vert(const OffsetIndices<int> faces,
const Span<int> corner_verts,
const Span<bool> vert_selection,
IndexMaskMemory &memory)
{
return face_selection_from_mapped_corner(faces, corner_verts, vert_selection, memory);
}
/** A face is selected if all of its edges are selected. */
static IndexMask face_selection_from_edge(const OffsetIndices<int> faces,
const Span<int> corner_edges,
const Span<bool> edge_mask,
IndexMaskMemory &memory)
{
return face_selection_from_mapped_corner(faces, corner_edges, edge_mask, memory);
}
/** Create a mesh with no built-in attributes. */
static Mesh *create_mesh_no_attributes(const Mesh &params_mesh,
const int verts_num,

View File

@ -0,0 +1,96 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_index_mask.hh"
#include "BKE_mesh.hh"
namespace blender::geometry {
IndexMask vert_selection_from_edge(const Span<int2> edges,
const IndexMask &edge_mask,
const int verts_num,
IndexMaskMemory &memory)
{
Array<bool> array(verts_num, false);
edge_mask.foreach_index_optimized<int>(GrainSize(4096), [&](const int i) {
array[edges[i][0]] = true;
array[edges[i][1]] = true;
});
return IndexMask::from_bools(array, memory);
}
static IndexMask mapped_corner_selection_from_face(const OffsetIndices<int> faces,
const IndexMask &face_mask,
const Span<int> corner_verts_or_edges,
const int verts_or_edges_num,
IndexMaskMemory &memory)
{
Array<bool> array(verts_or_edges_num, false);
face_mask.foreach_index(GrainSize(512), [&](const int64_t i) {
array.as_mutable_span().fill_indices(corner_verts_or_edges.slice(faces[i]), true);
});
return IndexMask::from_bools(array, memory);
}
IndexMask vert_selection_from_face(const OffsetIndices<int> faces,
const IndexMask &face_mask,
const Span<int> corner_verts,
const int verts_num,
IndexMaskMemory &memory)
{
return mapped_corner_selection_from_face(faces, face_mask, corner_verts, verts_num, memory);
}
IndexMask edge_selection_from_face(const OffsetIndices<int> faces,
const IndexMask &face_mask,
const Span<int> corner_edges,
const int edges_num,
IndexMaskMemory &memory)
{
return mapped_corner_selection_from_face(faces, face_mask, corner_edges, edges_num, memory);
}
IndexMask edge_selection_from_vert(const Span<int2> edges,
const Span<bool> vert_selection,
IndexMaskMemory &memory)
{
return IndexMask::from_predicate(
edges.index_range(), GrainSize(1024), memory, [&](const int64_t i) {
const int2 edge = edges[i];
return vert_selection[edge[0]] && vert_selection[edge[1]];
});
}
static IndexMask face_selection_from_mapped_corner(const OffsetIndices<int> faces,
const Span<int> corner_verts_or_edges,
const Span<bool> vert_or_edge_selection,
IndexMaskMemory &memory)
{
return IndexMask::from_predicate(
faces.index_range(), GrainSize(1024), memory, [&](const int64_t i) {
const Span<int> indices = corner_verts_or_edges.slice(faces[i]);
return std::all_of(indices.begin(), indices.end(), [&](const int i) {
return vert_or_edge_selection[i];
});
});
}
IndexMask face_selection_from_vert(const OffsetIndices<int> faces,
const Span<int> corner_verts,
const Span<bool> vert_selection,
IndexMaskMemory &memory)
{
return face_selection_from_mapped_corner(faces, corner_verts, vert_selection, memory);
}
IndexMask face_selection_from_edge(const OffsetIndices<int> faces,
const Span<int> corner_edges,
const Span<bool> edge_mask,
IndexMaskMemory &memory)
{
return face_selection_from_mapped_corner(faces, corner_edges, edge_mask, memory);
}
} // namespace blender::geometry