Cleanup: Move functions in BMesh Mesh conversion

These functions will be useful to speed up the edit mode to object
mode conversion too, move them above that so they can easily be
used for that case later.
This commit is contained in:
Hans Goudey
2023-03-09 08:35:16 -05:00
parent d21b9a4bb6
commit 85fb63f99c

View File

@@ -1095,6 +1095,80 @@ static Vector<BMeshToMeshLayerInfo> bm_to_mesh_copy_info_calc(const CustomData &
return infos;
}
namespace blender {
static void bm_vert_table_build(BMesh &bm,
MutableSpan<const BMVert *> table,
bool &need_select_vert,
bool &need_hide_vert)
{
char hflag = 0;
BMIter iter;
int i;
BMVert *vert;
BM_ITER_MESH_INDEX (vert, &iter, &bm, BM_VERTS_OF_MESH, i) {
BM_elem_index_set(vert, i); /* set_inline */
table[i] = vert;
hflag |= vert->head.hflag;
}
need_select_vert = (hflag & BM_ELEM_SELECT) != 0;
need_hide_vert = (hflag & BM_ELEM_HIDDEN) != 0;
}
static void bm_edge_table_build(BMesh &bm,
MutableSpan<const BMEdge *> table,
bool &need_select_edge,
bool &need_hide_edge,
bool &need_sharp_edge,
bool &need_uv_seams)
{
char hflag = 0;
BMIter iter;
int i;
BMEdge *edge;
BM_ITER_MESH_INDEX (edge, &iter, &bm, BM_EDGES_OF_MESH, i) {
BM_elem_index_set(edge, i); /* set_inline */
table[i] = edge;
hflag |= edge->head.hflag;
}
need_select_edge = (hflag & BM_ELEM_SELECT) != 0;
need_hide_edge = (hflag & BM_ELEM_HIDDEN) != 0;
need_sharp_edge = (hflag & BM_ELEM_SMOOTH) != 0;
need_uv_seams = (hflag & BM_ELEM_SEAM) != 0;
}
static void bm_face_loop_table_build(BMesh &bm,
MutableSpan<const BMFace *> face_table,
MutableSpan<const BMLoop *> loop_table,
bool &need_select_poly,
bool &need_hide_poly,
bool &need_sharp_face,
bool &need_material_index)
{
char hflag = 0;
BMIter iter;
int face_i = 0;
int loop_i = 0;
BMFace *face;
BM_ITER_MESH_INDEX (face, &iter, &bm, BM_FACES_OF_MESH, face_i) {
BM_elem_index_set(face, face_i); /* set_inline */
face_table[face_i] = face;
hflag |= face->head.hflag;
need_sharp_face |= (face->head.hflag & BM_ELEM_SMOOTH) == 0;
need_material_index |= face->mat_nr != 0;
BMLoop *loop = BM_FACE_FIRST_LOOP(face);
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
BM_elem_index_set(loop, loop_i); /* set_inline */
loop_table[loop_i] = loop;
loop = loop->next;
loop_i++;
}
}
need_select_poly = (hflag & BM_ELEM_SELECT) != 0;
need_hide_poly = (hflag & BM_ELEM_HIDDEN) != 0;
}
static void bmesh_block_copy_to_mesh_attributes(const Span<BMeshToMeshLayerInfo> copy_info,
const int mesh_index,
const void *block)
@@ -1106,6 +1180,132 @@ static void bmesh_block_copy_to_mesh_attributes(const Span<BMeshToMeshLayerInfo>
}
}
static void bm_to_mesh_verts(const BMesh &bm,
const Span<const BMVert *> bm_verts,
Mesh &mesh,
MutableSpan<bool> select_vert,
MutableSpan<bool> hide_vert)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.vdata, mesh.vdata);
MutableSpan<float3> dst_vert_positions = mesh.vert_positions_for_write();
threading::parallel_for(dst_vert_positions.index_range(), 1024, [&](const IndexRange range) {
for (const int vert_i : range) {
const BMVert &src_vert = *bm_verts[vert_i];
copy_v3_v3(dst_vert_positions[vert_i], src_vert.co);
bmesh_block_copy_to_mesh_attributes(info, vert_i, src_vert.head.data);
}
if (!select_vert.is_empty()) {
for (const int vert_i : range) {
select_vert[vert_i] = BM_elem_flag_test(bm_verts[vert_i], BM_ELEM_SELECT);
}
}
if (!hide_vert.is_empty()) {
for (const int vert_i : range) {
hide_vert[vert_i] = BM_elem_flag_test(bm_verts[vert_i], BM_ELEM_HIDDEN);
}
}
});
}
static void bm_to_mesh_edges(const BMesh &bm,
const Span<const BMEdge *> bm_edges,
Mesh &mesh,
MutableSpan<bool> select_edge,
MutableSpan<bool> hide_edge,
MutableSpan<bool> sharp_edge,
MutableSpan<bool> uv_seams)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.edata, mesh.edata);
MutableSpan<MEdge> dst_edges = mesh.edges_for_write();
threading::parallel_for(dst_edges.index_range(), 512, [&](const IndexRange range) {
for (const int edge_i : range) {
const BMEdge &src_edge = *bm_edges[edge_i];
MEdge &dst_edge = dst_edges[edge_i];
dst_edge.v1 = BM_elem_index_get(src_edge.v1);
dst_edge.v2 = BM_elem_index_get(src_edge.v2);
bmesh_block_copy_to_mesh_attributes(info, edge_i, src_edge.head.data);
}
if (!select_edge.is_empty()) {
for (const int edge_i : range) {
select_edge[edge_i] = BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SELECT);
}
}
if (!hide_edge.is_empty()) {
for (const int edge_i : range) {
hide_edge[edge_i] = BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_HIDDEN);
}
}
if (!sharp_edge.is_empty()) {
for (const int edge_i : range) {
sharp_edge[edge_i] = !BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SMOOTH);
}
}
if (!uv_seams.is_empty()) {
for (const int edge_i : range) {
uv_seams[edge_i] = BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SEAM);
}
}
});
}
static void bm_to_mesh_faces(const BMesh &bm,
const Span<const BMFace *> bm_faces,
Mesh &mesh,
MutableSpan<bool> select_poly,
MutableSpan<bool> hide_poly,
MutableSpan<bool> sharp_faces,
MutableSpan<int> material_indices)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.pdata, mesh.pdata);
MutableSpan<MPoly> dst_polys = mesh.polys_for_write();
threading::parallel_for(dst_polys.index_range(), 1024, [&](const IndexRange range) {
for (const int face_i : range) {
const BMFace &src_face = *bm_faces[face_i];
MPoly &dst_poly = dst_polys[face_i];
dst_poly.totloop = src_face.len;
dst_poly.loopstart = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face));
bmesh_block_copy_to_mesh_attributes(info, face_i, src_face.head.data);
}
if (!select_poly.is_empty()) {
for (const int face_i : range) {
select_poly[face_i] = BM_elem_flag_test(bm_faces[face_i], BM_ELEM_SELECT);
}
}
if (!hide_poly.is_empty()) {
for (const int face_i : range) {
hide_poly[face_i] = BM_elem_flag_test(bm_faces[face_i], BM_ELEM_HIDDEN);
}
}
if (!material_indices.is_empty()) {
for (const int face_i : range) {
material_indices[face_i] = bm_faces[face_i]->mat_nr;
}
}
if (!sharp_faces.is_empty()) {
for (const int face_i : range) {
sharp_faces[face_i] = !BM_elem_flag_test(bm_faces[face_i], BM_ELEM_SMOOTH);
}
}
});
}
static void bm_to_mesh_loops(const BMesh &bm, const Span<const BMLoop *> bm_loops, Mesh &mesh)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.ldata, mesh.ldata);
MutableSpan<MLoop> dst_loops = mesh.loops_for_write();
threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) {
for (const int loop_i : range) {
const BMLoop &src_loop = *bm_loops[loop_i];
MLoop &dst_loop = dst_loops[loop_i];
dst_loop.v = BM_elem_index_get(src_loop.v);
dst_loop.e = BM_elem_index_get(src_loop.e);
bmesh_block_copy_to_mesh_attributes(info, loop_i, src_loop.head.data);
}
});
}
} // namespace blender
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
{
using namespace blender;
@@ -1480,206 +1680,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
multires_topology_changed(me);
}
namespace blender {
static void bm_vert_table_build(BMesh &bm,
MutableSpan<const BMVert *> table,
bool &need_select_vert,
bool &need_hide_vert)
{
char hflag = 0;
BMIter iter;
int i;
BMVert *vert;
BM_ITER_MESH_INDEX (vert, &iter, &bm, BM_VERTS_OF_MESH, i) {
BM_elem_index_set(vert, i); /* set_inline */
table[i] = vert;
hflag |= vert->head.hflag;
}
need_select_vert = (hflag & BM_ELEM_SELECT) != 0;
need_hide_vert = (hflag & BM_ELEM_HIDDEN) != 0;
}
static void bm_edge_table_build(BMesh &bm,
MutableSpan<const BMEdge *> table,
bool &need_select_edge,
bool &need_hide_edge,
bool &need_sharp_edge,
bool &need_uv_seams)
{
char hflag = 0;
BMIter iter;
int i;
BMEdge *edge;
BM_ITER_MESH_INDEX (edge, &iter, &bm, BM_EDGES_OF_MESH, i) {
BM_elem_index_set(edge, i); /* set_inline */
table[i] = edge;
hflag |= edge->head.hflag;
}
need_select_edge = (hflag & BM_ELEM_SELECT) != 0;
need_hide_edge = (hflag & BM_ELEM_HIDDEN) != 0;
need_sharp_edge = (hflag & BM_ELEM_SMOOTH) != 0;
need_uv_seams = (hflag & BM_ELEM_SEAM) != 0;
}
static void bm_face_loop_table_build(BMesh &bm,
MutableSpan<const BMFace *> face_table,
MutableSpan<const BMLoop *> loop_table,
bool &need_select_poly,
bool &need_hide_poly,
bool &need_sharp_face,
bool &need_material_index)
{
char hflag = 0;
BMIter iter;
int face_i = 0;
int loop_i = 0;
BMFace *face;
BM_ITER_MESH_INDEX (face, &iter, &bm, BM_FACES_OF_MESH, face_i) {
BM_elem_index_set(face, face_i); /* set_inline */
face_table[face_i] = face;
hflag |= face->head.hflag;
need_sharp_face |= (face->head.hflag & BM_ELEM_SMOOTH) == 0;
need_material_index |= face->mat_nr != 0;
BMLoop *loop = BM_FACE_FIRST_LOOP(face);
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
BM_elem_index_set(loop, loop_i); /* set_inline */
loop_table[loop_i] = loop;
loop = loop->next;
loop_i++;
}
}
need_select_poly = (hflag & BM_ELEM_SELECT) != 0;
need_hide_poly = (hflag & BM_ELEM_HIDDEN) != 0;
}
static void bm_to_mesh_verts(const BMesh &bm,
const Span<const BMVert *> bm_verts,
Mesh &mesh,
MutableSpan<bool> select_vert,
MutableSpan<bool> hide_vert)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.vdata, mesh.vdata);
MutableSpan<float3> dst_vert_positions = mesh.vert_positions_for_write();
threading::parallel_for(dst_vert_positions.index_range(), 1024, [&](const IndexRange range) {
for (const int vert_i : range) {
const BMVert &src_vert = *bm_verts[vert_i];
copy_v3_v3(dst_vert_positions[vert_i], src_vert.co);
bmesh_block_copy_to_mesh_attributes(info, vert_i, src_vert.head.data);
}
if (!select_vert.is_empty()) {
for (const int vert_i : range) {
select_vert[vert_i] = BM_elem_flag_test(bm_verts[vert_i], BM_ELEM_SELECT);
}
}
if (!hide_vert.is_empty()) {
for (const int vert_i : range) {
hide_vert[vert_i] = BM_elem_flag_test(bm_verts[vert_i], BM_ELEM_HIDDEN);
}
}
});
}
static void bm_to_mesh_edges(const BMesh &bm,
const Span<const BMEdge *> bm_edges,
Mesh &mesh,
MutableSpan<bool> select_edge,
MutableSpan<bool> hide_edge,
MutableSpan<bool> sharp_edge,
MutableSpan<bool> uv_seams)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.edata, mesh.edata);
MutableSpan<MEdge> dst_edges = mesh.edges_for_write();
threading::parallel_for(dst_edges.index_range(), 512, [&](const IndexRange range) {
for (const int edge_i : range) {
const BMEdge &src_edge = *bm_edges[edge_i];
MEdge &dst_edge = dst_edges[edge_i];
dst_edge.v1 = BM_elem_index_get(src_edge.v1);
dst_edge.v2 = BM_elem_index_get(src_edge.v2);
bmesh_block_copy_to_mesh_attributes(info, edge_i, src_edge.head.data);
}
if (!select_edge.is_empty()) {
for (const int edge_i : range) {
select_edge[edge_i] = BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SELECT);
}
}
if (!hide_edge.is_empty()) {
for (const int edge_i : range) {
hide_edge[edge_i] = BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_HIDDEN);
}
}
if (!sharp_edge.is_empty()) {
for (const int edge_i : range) {
sharp_edge[edge_i] = !BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SMOOTH);
}
}
if (!uv_seams.is_empty()) {
for (const int edge_i : range) {
uv_seams[edge_i] = BM_elem_flag_test(bm_edges[edge_i], BM_ELEM_SEAM);
}
}
});
}
static void bm_to_mesh_faces(const BMesh &bm,
const Span<const BMFace *> bm_faces,
Mesh &mesh,
MutableSpan<bool> select_poly,
MutableSpan<bool> hide_poly,
MutableSpan<bool> sharp_faces,
MutableSpan<int> material_indices)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.pdata, mesh.pdata);
MutableSpan<MPoly> dst_polys = mesh.polys_for_write();
threading::parallel_for(dst_polys.index_range(), 1024, [&](const IndexRange range) {
for (const int face_i : range) {
const BMFace &src_face = *bm_faces[face_i];
MPoly &dst_poly = dst_polys[face_i];
dst_poly.totloop = src_face.len;
dst_poly.loopstart = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face));
bmesh_block_copy_to_mesh_attributes(info, face_i, src_face.head.data);
}
if (!select_poly.is_empty()) {
for (const int face_i : range) {
select_poly[face_i] = BM_elem_flag_test(bm_faces[face_i], BM_ELEM_SELECT);
}
}
if (!hide_poly.is_empty()) {
for (const int face_i : range) {
hide_poly[face_i] = BM_elem_flag_test(bm_faces[face_i], BM_ELEM_HIDDEN);
}
}
if (!material_indices.is_empty()) {
for (const int face_i : range) {
material_indices[face_i] = bm_faces[face_i]->mat_nr;
}
}
if (!sharp_faces.is_empty()) {
for (const int face_i : range) {
sharp_faces[face_i] = !BM_elem_flag_test(bm_faces[face_i], BM_ELEM_SMOOTH);
}
}
});
}
static void bm_to_mesh_loops(const BMesh &bm, const Span<const BMLoop *> bm_loops, Mesh &mesh)
{
const Vector<BMeshToMeshLayerInfo> info = bm_to_mesh_copy_info_calc(bm.ldata, mesh.ldata);
MutableSpan<MLoop> dst_loops = mesh.loops_for_write();
threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) {
for (const int loop_i : range) {
const BMLoop &src_loop = *bm_loops[loop_i];
MLoop &dst_loop = dst_loops[loop_i];
dst_loop.v = BM_elem_index_get(src_loop.v);
dst_loop.e = BM_elem_index_get(src_loop.e);
bmesh_block_copy_to_mesh_attributes(info, loop_i, src_loop.head.data);
}
});
}
} // namespace blender
/* NOTE: The function is called from multiple threads with the same input BMesh and different
* mesh objects. */
void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra)