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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user