BMesh: optimize attribute copying by reusing BMCustomDataCopyMap

Continuation of fix for #115776. Removes attribute copy functions
that calculate the map inline, this is error prone as it's easy to
call these functions from a loop which may result in poor performance.
This commit is contained in:
Campbell Barton
2023-12-09 23:16:21 +11:00
parent 2c85561fc3
commit 15cff1fddb
10 changed files with 226 additions and 170 deletions

View File

@@ -341,88 +341,6 @@ void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMLoop
dst->head.hflag = src->head.hflag & ~BM_ELEM_SELECT;
}
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMVert *src, BMVert *dst)
{
if (bm_src == bm_dst) {
BM_elem_attrs_copy(*bm_dst, src, dst);
}
else {
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(bm_src->vdata, bm_dst->vdata);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
}
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMEdge *src, BMEdge *dst)
{
if (bm_src == bm_dst) {
BM_elem_attrs_copy(*bm_dst, src, dst);
}
else {
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(bm_src->edata, bm_dst->edata);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
}
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMFace *src, BMFace *dst)
{
if (bm_src == bm_dst) {
BM_elem_attrs_copy(*bm_dst, src, dst);
}
else {
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(bm_src->pdata, bm_dst->pdata);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
}
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMLoop *src, BMLoop *dst)
{
if (bm_src == bm_dst) {
BM_elem_attrs_copy(*bm_dst, src, dst);
}
else {
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(bm_src->ldata, bm_dst->ldata);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
}
void BM_elem_attrs_copy(const BMesh *bm_src,
BMesh *bm_dst,
const eCustomDataMask exclude,
const BMVert *src,
BMVert *dst)
{
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(
bm_src->vdata, bm_dst->vdata, exclude);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
void BM_elem_attrs_copy(const BMesh *bm_src,
BMesh *bm_dst,
const eCustomDataMask exclude,
const BMEdge *src,
BMEdge *dst)
{
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(
bm_src->edata, bm_dst->edata, exclude);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
void BM_elem_attrs_copy(const BMesh *bm_src,
BMesh *bm_dst,
const eCustomDataMask exclude,
const BMFace *src,
BMFace *dst)
{
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(
bm_src->pdata, bm_dst->pdata, exclude);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
void BM_elem_attrs_copy(const BMesh *bm_src,
BMesh *bm_dst,
const eCustomDataMask exclude,
const BMLoop *src,
BMLoop *dst)
{
const BMCustomDataCopyMap map = CustomData_bmesh_copy_map_calc(
bm_src->ldata, bm_dst->ldata, exclude);
BM_elem_attrs_copy(bm_dst, map, src, dst);
}
void BM_elem_attrs_copy(BMesh &bm, const BMVert *src, BMVert *dst)
{
BLI_assert(src != dst);

View File

@@ -131,34 +131,12 @@ void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMEdge
void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMFace *src, BMFace *dst);
void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMLoop *src, BMLoop *dst);
/**
* Copy attributes between elements in two BMeshes. These functions are often called with both
* pointing to the same BMesh though, so they check for that and use a simpler copy in that case.
*
* \note For better performance when copying more than one block, use the overload with a
* #BMCustomDataCopyMap precalculated map argument.
*/
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMVert *src, BMVert *dst);
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMEdge *src, BMEdge *dst);
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMFace *src, BMFace *dst);
void BM_elem_attrs_copy(const BMesh *bm_src, BMesh *bm_dst, const BMLoop *src, BMLoop *dst);
/** Copy attributes between elements in the same BMesh. */
void BM_elem_attrs_copy(BMesh &bm, const BMVert *src, BMVert *dst);
void BM_elem_attrs_copy(BMesh &bm, const BMEdge *src, BMEdge *dst);
void BM_elem_attrs_copy(BMesh &bm, const BMFace *src, BMFace *dst);
void BM_elem_attrs_copy(BMesh &bm, const BMLoop *src, BMLoop *dst);
/** Copy attributes between two BMesh elements, excluding certain custom data types. */
void BM_elem_attrs_copy(
const BMesh *bm_src, BMesh *bm_dst, eCustomDataMask exclude, const BMVert *src, BMVert *dst);
void BM_elem_attrs_copy(
const BMesh *bm_src, BMesh *bm_dst, eCustomDataMask exclude, const BMEdge *src, BMEdge *dst);
void BM_elem_attrs_copy(
const BMesh *bm_src, BMesh *bm_dst, eCustomDataMask exclude, const BMFace *src, BMFace *dst);
void BM_elem_attrs_copy(
const BMesh *bm_src, BMesh *bm_dst, eCustomDataMask exclude, const BMLoop *src, BMLoop *dst);
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v);
/**

View File

@@ -280,19 +280,18 @@ static BMLoop *bm_face_boundary_add(
return l;
}
BMFace *BM_face_copy(
BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges)
static BMFace *bm_face_copy_impl(BMesh *bm_dst,
BMFace *f,
const bool copy_verts,
const bool copy_edges)
{
BMVert **verts = BLI_array_alloca(verts, f->len);
BMEdge **edges = BLI_array_alloca(edges, f->len);
BMLoop *l_iter;
BMLoop *l_first;
BMLoop *l_copy;
BMFace *f_copy;
int i;
BLI_assert((bm_dst == bm_src) || (copy_verts && copy_edges));
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
i = 0;
do {
@@ -330,15 +329,45 @@ BMFace *BM_face_copy(
f_copy = BM_face_create(bm_dst, verts, edges, f->len, nullptr, BM_CREATE_SKIP_CD);
BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy);
return f_copy;
}
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
l_copy = BM_FACE_FIRST_LOOP(f_copy);
BMFace *BM_face_copy(BMesh *bm_dst,
const BMCustomDataCopyMap &cd_face_map,
const BMCustomDataCopyMap &cd_loop_map,
BMFace *f,
const bool copy_verts,
const bool copy_edges)
{
BMFace *f_copy = bm_face_copy_impl(bm_dst, f, copy_verts, copy_edges);
/* Copy custom-data. */
BM_elem_attrs_copy(bm_dst, cd_face_map, f, f_copy);
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_copy = BM_FACE_FIRST_LOOP(f_copy);
BMLoop *l_iter = l_first;
do {
BM_elem_attrs_copy(bm_src, bm_dst, l_iter, l_copy);
BM_elem_attrs_copy(bm_dst, cd_loop_map, l_iter, l_copy);
l_copy = l_copy->next;
} while ((l_iter = l_iter->next) != l_first);
return f_copy;
}
BMFace *BM_face_copy(BMesh *bm_dst, BMFace *f, const bool copy_verts, const bool copy_edges)
{
BMFace *f_copy = bm_face_copy_impl(bm_dst, f, copy_verts, copy_edges);
/* Copy custom-data. */
BM_elem_attrs_copy(*bm_dst, f, f_copy);
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
BMLoop *l_copy = BM_FACE_FIRST_LOOP(f_copy);
BMLoop *l_iter = l_first;
do {
BM_elem_attrs_copy(*bm_dst, l_iter, l_copy);
l_copy = l_copy->next;
} while ((l_iter = l_iter->next) != l_first);
return f_copy;
}

View File

@@ -8,7 +8,17 @@
* \ingroup bmesh
*/
BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, bool copy_verts, bool copy_edges);
/**
* When copying between different BMesh objects,
* `copy_verts` & `copy_edges` should always be true.
*/
BMFace *BM_face_copy(BMesh *bm,
const BMCustomDataCopyMap &cd_face_map,
const BMCustomDataCopyMap &cd_loop_map,
BMFace *f,
bool copy_verts,
bool copy_edges);
BMFace *BM_face_copy(BMesh *bm, BMFace *f, bool copy_verts, bool copy_edges);
typedef enum eBMCreateFlag {
BM_CREATE_NOP = 0,

View File

@@ -18,27 +18,43 @@
#include "bmesh.hh"
#include "intern/bmesh_private.hh" /* for element checking */
static BMVert *bm_vert_copy(BMesh *bm_src, BMesh *bm_dst, BMVert *v_src)
static BMVert *bm_vert_copy(BMesh *bm_dst,
const std::optional<BMCustomDataCopyMap> &cd_vert_map,
BMVert *v_src)
{
BMVert *v_dst = BM_vert_create(bm_dst, v_src->co, nullptr, BM_CREATE_SKIP_CD);
BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
if (cd_vert_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_vert_map.value(), v_src, v_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, v_src, v_dst);
}
return v_dst;
}
static BMEdge *bm_edge_copy_with_arrays(BMesh *bm_src,
BMesh *bm_dst,
static BMEdge *bm_edge_copy_with_arrays(BMesh *bm_dst,
const std::optional<BMCustomDataCopyMap> &cd_edge_map,
BMEdge *e_src,
BMVert **verts_dst)
{
BMVert *e_dst_v1 = verts_dst[BM_elem_index_get(e_src->v1)];
BMVert *e_dst_v2 = verts_dst[BM_elem_index_get(e_src->v2)];
BMEdge *e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, nullptr, BM_CREATE_SKIP_CD);
BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst);
if (cd_edge_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_edge_map.value(), e_src, e_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, e_src, e_dst);
}
return e_dst;
}
static BMFace *bm_face_copy_with_arrays(
BMesh *bm_src, BMesh *bm_dst, BMFace *f_src, BMVert **verts_dst, BMEdge **edges_dst)
static BMFace *bm_face_copy_with_arrays(BMesh *bm_dst,
const std::optional<BMCustomDataCopyMap> cd_face_map,
const std::optional<BMCustomDataCopyMap> &cd_loop_map,
BMFace *f_src,
BMVert **verts_dst,
BMEdge **edges_dst)
{
BMFace *f_dst;
BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
@@ -61,13 +77,23 @@ static BMFace *bm_face_copy_with_arrays(
f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, nullptr, BM_CREATE_SKIP_CD);
/* Copy attributes. */
BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
if (cd_face_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_face_map.value(), f_src, f_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, f_src, f_dst);
}
/* Copy per-loop custom data. */
l_iter_src = l_first_src;
l_iter_dst = BM_FACE_FIRST_LOOP(f_dst);
do {
BM_elem_attrs_copy(bm_src, bm_dst, l_iter_src, l_iter_dst);
if (cd_loop_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_loop_map.value(), l_iter_src, l_iter_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, l_iter_src, l_iter_dst);
}
} while ((void)(l_iter_dst = l_iter_dst->next), (l_iter_src = l_iter_src->next) != l_first_src);
return f_dst;
@@ -82,6 +108,23 @@ void BM_mesh_copy_arrays(BMesh *bm_src,
BMFace **faces_src,
uint faces_src_len)
{
const std::optional<BMCustomDataCopyMap> cd_vert_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->vdata, bm_dst->vdata)};
const std::optional<BMCustomDataCopyMap> cd_edge_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->edata, bm_dst->edata)};
const std::optional<BMCustomDataCopyMap> cd_face_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->pdata, bm_dst->pdata)};
const std::optional<BMCustomDataCopyMap> cd_loop_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->ldata, bm_dst->ldata)};
/* Vertices. */
BMVert **verts_dst = static_cast<BMVert **>(
MEM_mallocN(sizeof(*verts_dst) * verts_src_len, __func__));
@@ -89,7 +132,7 @@ void BM_mesh_copy_arrays(BMesh *bm_src,
BMVert *v_src = verts_src[i];
BM_elem_index_set(v_src, i); /* set_dirty! */
BMVert *v_dst = bm_vert_copy(bm_src, bm_dst, v_src);
BMVert *v_dst = bm_vert_copy(bm_dst, cd_vert_map, v_src);
BM_elem_index_set(v_dst, i); /* set_ok */
verts_dst[i] = v_dst;
}
@@ -103,7 +146,7 @@ void BM_mesh_copy_arrays(BMesh *bm_src,
BMEdge *e_src = edges_src[i];
BM_elem_index_set(e_src, i); /* set_dirty! */
BMEdge *e_dst = bm_edge_copy_with_arrays(bm_src, bm_dst, e_src, verts_dst);
BMEdge *e_dst = bm_edge_copy_with_arrays(bm_dst, cd_edge_map, e_src, verts_dst);
BM_elem_index_set(e_dst, i);
edges_dst[i] = e_dst;
}
@@ -113,7 +156,8 @@ void BM_mesh_copy_arrays(BMesh *bm_src,
/* Faces. */
for (uint i = 0; i < faces_src_len; i++) {
BMFace *f_src = faces_src[i];
BMFace *f_dst = bm_face_copy_with_arrays(bm_src, bm_dst, f_src, verts_dst, edges_dst);
BMFace *f_dst = bm_face_copy_with_arrays(
bm_dst, cd_face_map, cd_loop_map, f_src, verts_dst, edges_dst);
BM_elem_index_set(f_dst, i);
}
bm_dst->elem_index_dirty &= ~BM_FACE;

View File

@@ -205,7 +205,7 @@ BMFace *BM_face_split(BMesh *bm,
/* do we have a multires layer? */
if (cd_loop_mdisp_offset != -1) {
f_tmp = BM_face_copy(bm, bm, f, false, false);
f_tmp = BM_face_copy(bm, f, false, false);
}
#ifdef USE_BMESH_HOLES
@@ -273,7 +273,7 @@ BMFace *BM_face_split_n(BMesh *bm,
return nullptr;
}
f_tmp = BM_face_copy(bm, bm, f, true, true);
f_tmp = BM_face_copy(bm, f, true, true);
#ifdef USE_BMESH_HOLES
f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, nullptr, example, false);
@@ -467,7 +467,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
/* flag existing faces so we can differentiate oldfaces from new faces */
for (int64_t i = 0; i < oldfaces.size(); i++) {
BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP);
oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true);
oldfaces[i] = BM_face_copy(bm, oldfaces[i], true, true);
BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP);
}
}

View File

@@ -33,7 +33,7 @@
static BMVert *bmo_vert_copy(BMOperator *op,
BMOpSlot *slot_vertmap_out,
BMesh *bm_dst,
BMesh *bm_src,
const std::optional<BMCustomDataCopyMap> &cd_vert_map,
BMVert *v_src,
GHash *vhash)
{
@@ -48,7 +48,12 @@ static BMVert *bmo_vert_copy(BMOperator *op,
BLI_ghash_insert(vhash, v_src, v_dst);
/* Copy attributes */
BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
if (cd_vert_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_vert_map.value(), v_src, v_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, v_src, v_dst);
}
/* Mark the vert for output */
BMO_vert_flag_enable(bm_dst, v_dst, DUPE_NEW);
@@ -66,6 +71,7 @@ static BMEdge *bmo_edge_copy(BMOperator *op,
BMOpSlot *slot_boundarymap_out,
BMesh *bm_dst,
BMesh *bm_src,
const std::optional<BMCustomDataCopyMap> &cd_edge_map,
BMEdge *e_src,
GHash *vhash,
GHash *ehash,
@@ -110,7 +116,12 @@ static BMEdge *bmo_edge_copy(BMOperator *op,
BLI_ghash_insert(ehash, e_src, e_dst);
/* Copy attributes */
BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst);
if (cd_edge_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_edge_map.value(), e_src, e_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, e_src, e_dst);
}
/* Mark the edge for output */
BMO_edge_flag_enable(bm_dst, e_dst, DUPE_NEW);
@@ -134,7 +145,8 @@ static BMEdge *bmo_edge_copy(BMOperator *op,
static BMFace *bmo_face_copy(BMOperator *op,
BMOpSlot *slot_facemap_out,
BMesh *bm_dst,
BMesh *bm_src,
const std::optional<BMCustomDataCopyMap> &cd_face_map,
const std::optional<BMCustomDataCopyMap> &cd_loop_map,
BMFace *f_src,
GHash *vhash,
GHash *ehash)
@@ -162,13 +174,23 @@ static BMFace *bmo_face_copy(BMOperator *op,
BMO_slot_map_elem_insert(op, slot_facemap_out, f_dst, f_src);
/* Copy attributes */
BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
if (cd_face_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_face_map.value(), f_src, f_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, f_src, f_dst);
}
/* copy per-loop custom data */
l_iter_src = l_first_src;
l_iter_dst = BM_FACE_FIRST_LOOP(f_dst);
do {
BM_elem_attrs_copy(bm_src, bm_dst, l_iter_src, l_iter_dst);
if (cd_loop_map.has_value()) {
BM_elem_attrs_copy(bm_dst, cd_loop_map.value(), l_iter_src, l_iter_dst);
}
else {
BM_elem_attrs_copy(*bm_dst, l_iter_src, l_iter_dst);
}
} while ((void)(l_iter_dst = l_iter_dst->next), (l_iter_src = l_iter_src->next) != l_first_src);
/* Mark the face for output */
@@ -205,6 +227,23 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
vhash = BLI_ghash_ptr_new("bmesh dupeops v");
ehash = BLI_ghash_ptr_new("bmesh dupeops e");
const std::optional<BMCustomDataCopyMap> cd_vert_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->vdata, bm_dst->vdata)};
const std::optional<BMCustomDataCopyMap> cd_edge_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->edata, bm_dst->edata)};
const std::optional<BMCustomDataCopyMap> cd_face_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->pdata, bm_dst->pdata)};
const std::optional<BMCustomDataCopyMap> cd_loop_map =
(bm_src == bm_dst) ? std::nullopt :
std::optional<BMCustomDataCopyMap>{
CustomData_bmesh_copy_map_calc(bm_src->ldata, bm_dst->ldata)};
/* duplicate flagged vertices */
BM_ITER_MESH (v, &viter, bm_src, BM_VERTS_OF_MESH) {
if (BMO_vert_flag_test(bm_src, v, DUPE_INPUT) &&
@@ -212,7 +251,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
BMIter iter;
bool isolated = true;
v2 = bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
v2 = bmo_vert_copy(op, slot_vert_map_out, bm_dst, cd_vert_map, v, vhash);
BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
if (BMO_face_flag_test(bm_src, f, DUPE_INPUT)) {
@@ -244,11 +283,11 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
BMO_edge_flag_test(bm_src, e, DUPE_DONE) == false) {
/* make sure that verts are copied */
if (!BMO_vert_flag_test(bm_src, e->v1, DUPE_DONE)) {
bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v1, vhash);
bmo_vert_copy(op, slot_vert_map_out, bm_dst, cd_vert_map, e->v1, vhash);
BMO_vert_flag_enable(bm_src, e->v1, DUPE_DONE);
}
if (!BMO_vert_flag_test(bm_src, e->v2, DUPE_DONE)) {
bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v2, vhash);
bmo_vert_copy(op, slot_vert_map_out, bm_dst, cd_vert_map, e->v2, vhash);
BMO_vert_flag_enable(bm_src, e->v2, DUPE_DONE);
}
/* now copy the actual edge */
@@ -257,6 +296,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
slot_boundary_map_out,
bm_dst,
bm_src,
cd_edge_map,
e,
vhash,
ehash,
@@ -271,7 +311,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
/* vertex pass */
BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
if (!BMO_vert_flag_test(bm_src, v, DUPE_DONE)) {
bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
bmo_vert_copy(op, slot_vert_map_out, bm_dst, cd_vert_map, v, vhash);
BMO_vert_flag_enable(bm_src, v, DUPE_DONE);
}
}
@@ -284,6 +324,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
slot_boundary_map_out,
bm_dst,
bm_src,
cd_edge_map,
e,
vhash,
ehash,
@@ -291,8 +332,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
BMO_edge_flag_enable(bm_src, e, DUPE_DONE);
}
}
bmo_face_copy(op, slot_face_map_out, bm_dst, bm_src, f, vhash, ehash);
bmo_face_copy(op, slot_face_map_out, bm_dst, cd_face_map, cd_loop_map, f, vhash, ehash);
BMO_face_flag_enable(bm_src, f, DUPE_DONE);
}
}

View File

@@ -56,7 +56,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
BMO_face_flag_enable(bm, f_org, EXT_DEL);
f_new = BM_face_copy(bm, bm, f_org, true, true);
f_new = BM_face_copy(bm, f_org, true, true);
BMO_face_flag_enable(bm, f_new, EXT_KEEP);
if (select_history_map) {

View File

@@ -216,6 +216,12 @@ static void mesh_customdatacorrect_face_substitute_set(TransCustomDataLayer *tcl
{
BLI_assert(is_zero_v3(f->no));
BMesh *bm = tcld->bm;
const BMCustomDataCopyMap cd_face_map = CustomData_bmesh_copy_map_calc(tcld->bm_origfaces->pdata,
bm->pdata);
const BMCustomDataCopyMap cd_loop_map = CustomData_bmesh_copy_map_calc(tcld->bm_origfaces->ldata,
bm->ldata);
/* It is impossible to calculate the loops weights of a face without area.
* Find a substitute. */
BMFace *f_substitute = mesh_customdatacorrect_find_best_face_substitute(f);
@@ -228,7 +234,8 @@ static void mesh_customdatacorrect_face_substitute_set(TransCustomDataLayer *tcl
} while ((l_iter = l_iter->next) != l_first);
/* Use the substitute face as the reference during the transformation. */
BMFace *f_substitute_copy = BM_face_copy(tcld->bm_origfaces, bm, f_substitute, true, true);
BMFace *f_substitute_copy = BM_face_copy(
bm, cd_face_map, cd_loop_map, f_substitute, true, true);
/* Hack: reference substitute face in `f_copy->no`.
* `tcld->origfaces` is already used to restore the initial value. */
@@ -255,6 +262,11 @@ static void mesh_customdatacorrect_init_vert(TransCustomDataLayer *tcld,
int j, l_num;
float *loop_weights;
const BMCustomDataCopyMap cd_face_map = CustomData_bmesh_copy_map_calc(tcld->bm_origfaces->pdata,
bm->pdata);
const BMCustomDataCopyMap cd_loop_map = CustomData_bmesh_copy_map_calc(tcld->bm_origfaces->ldata,
bm->ldata);
// BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
l_num = liter.count;
@@ -268,7 +280,7 @@ static void mesh_customdatacorrect_init_vert(TransCustomDataLayer *tcld,
/* Generic custom-data correction. Copy face data. */
void **val_p;
if (!BLI_ghash_ensure_p(tcld->origfaces, l->f, &val_p)) {
BMFace *f_copy = BM_face_copy(tcld->bm_origfaces, bm, l->f, true, true);
BMFace *f_copy = BM_face_copy(bm, cd_face_map, cd_loop_map, l->f, true, true);
*val_p = f_copy;
#ifdef USE_FACE_SUBSTITUTE
if (is_zero_v3(l->f->no)) {
@@ -697,6 +709,8 @@ static void mesh_customdatacorrect_restore(TransInfo *t)
BMesh *bm = tcld->bm;
BMesh *bm_copy = tcld->bm_origfaces;
const BMCustomDataCopyMap cd_loop_map = CustomData_bmesh_copy_map_calc(bm_copy->ldata,
bm->ldata);
GHashIterator gh_iter;
GHASH_ITER (gh_iter, tcld->origfaces) {
@@ -709,7 +723,7 @@ static void mesh_customdatacorrect_restore(TransInfo *t)
l_copy = BM_FACE_FIRST_LOOP(f_copy);
do {
/* TODO: Restore only the elements that transform. */
BM_elem_attrs_copy(bm_copy, bm, l_copy, l_iter);
BM_elem_attrs_copy(bm, cd_loop_map, l_copy, l_iter);
l_copy = l_copy->next;
} while ((l_iter = l_iter->next) != l_first);
}

View File

@@ -1495,33 +1495,42 @@ static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
if (value->ele != self->ele) {
switch (self->ele->head.htype) {
case BM_VERT:
BM_elem_attrs_copy(value->bm,
self->bm,
CD_MASK_BM_ELEM_PYPTR,
case BM_VERT: {
const BMCustomDataCopyMap cd_vert_map = CustomData_bmesh_copy_map_calc(
value->bm->vdata, self->bm->vdata, CD_MASK_BM_ELEM_PYPTR);
BM_elem_attrs_copy(self->bm,
cd_vert_map,
reinterpret_cast<const BMVert *>(value->ele),
reinterpret_cast<BMVert *>(self->ele));
break;
case BM_EDGE:
BM_elem_attrs_copy(value->bm,
self->bm,
CD_MASK_BM_ELEM_PYPTR,
reinterpret_cast<const BMVert *>(value->ele),
reinterpret_cast<BMVert *>(self->ele));
}
case BM_EDGE: {
const BMCustomDataCopyMap cd_edge_map = CustomData_bmesh_copy_map_calc(
value->bm->edata, self->bm->edata, CD_MASK_BM_ELEM_PYPTR);
BM_elem_attrs_copy(self->bm,
cd_edge_map,
reinterpret_cast<const BMEdge *>(value->ele),
reinterpret_cast<BMEdge *>(self->ele));
break;
case BM_FACE:
BM_elem_attrs_copy(value->bm,
self->bm,
CD_MASK_BM_ELEM_PYPTR,
reinterpret_cast<const BMVert *>(value->ele),
reinterpret_cast<BMVert *>(self->ele));
}
case BM_FACE: {
const BMCustomDataCopyMap cd_face_map = CustomData_bmesh_copy_map_calc(
value->bm->pdata, self->bm->pdata, CD_MASK_BM_ELEM_PYPTR);
BM_elem_attrs_copy(self->bm,
cd_face_map,
reinterpret_cast<const BMFace *>(value->ele),
reinterpret_cast<BMFace *>(self->ele));
break;
case BM_LOOP:
BM_elem_attrs_copy(value->bm,
self->bm,
CD_MASK_BM_ELEM_PYPTR,
reinterpret_cast<const BMVert *>(value->ele),
reinterpret_cast<BMVert *>(self->ele));
}
case BM_LOOP: {
const BMCustomDataCopyMap cd_loop_map = CustomData_bmesh_copy_map_calc(
value->bm->ldata, self->bm->ldata, CD_MASK_BM_ELEM_PYPTR);
BM_elem_attrs_copy(self->bm,
cd_loop_map,
reinterpret_cast<const BMLoop *>(value->ele),
reinterpret_cast<BMLoop *>(self->ele));
break;
}
}
}
@@ -1918,7 +1927,7 @@ static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
return nullptr;
}
f_cpy = BM_face_copy(bm, bm, self->f, do_verts, do_edges);
f_cpy = BM_face_copy(bm, self->f, do_verts, do_edges);
if (f_cpy) {
return BPy_BMFace_CreatePyObject(bm, f_cpy);
@@ -2233,7 +2242,14 @@ static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
}
if (py_vert_example) {
BM_elem_attrs_copy(py_vert_example->bm, bm, py_vert_example->v, v);
if (py_vert_example->bm == bm) {
BM_elem_attrs_copy(*bm, py_vert_example->v, v);
}
else {
const BMCustomDataCopyMap cd_vert_map = CustomData_bmesh_copy_map_calc(
py_vert_example->bm->vdata, bm->vdata);
BM_elem_attrs_copy(bm, cd_vert_map, py_vert_example->v, v);
}
}
return BPy_BMVert_CreatePyObject(bm, v);
@@ -2294,7 +2310,14 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
}
if (py_edge_example) {
BM_elem_attrs_copy(py_edge_example->bm, bm, py_edge_example->e, e);
if (py_edge_example->bm == bm) {
BM_elem_attrs_copy(*bm, py_edge_example->e, e);
}
else {
const BMCustomDataCopyMap cd_edge_map = CustomData_bmesh_copy_map_calc(
py_edge_example->bm->edata, bm->edata);
BM_elem_attrs_copy(bm, cd_edge_map, py_edge_example->e, e);
}
}
ret = BPy_BMEdge_CreatePyObject(bm, e);