forked from blender/blender
main sync #3
@ -1095,6 +1095,80 @@ static Vector<BMeshToMeshLayerInfo> bm_to_mesh_copy_info_calc(const CustomData &
|
|||||||
return infos;
|
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,
|
static void bmesh_block_copy_to_mesh_attributes(const Span<BMeshToMeshLayerInfo> copy_info,
|
||||||
const int mesh_index,
|
const int mesh_index,
|
||||||
const void *block)
|
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)
|
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
|
||||||
{
|
{
|
||||||
using namespace blender;
|
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);
|
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
|
/* NOTE: The function is called from multiple threads with the same input BMesh and different
|
||||||
* mesh objects. */
|
* mesh objects. */
|
||||||
void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra)
|
void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra)
|
||||||
|
Loading…
Reference in New Issue
Block a user