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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user