forked from bartvdbraak/blender
bmesh: copy function - replace use of array reallocations with alloca in a static function.
This commit is contained in:
parent
754f93f30d
commit
b2f1720d41
@ -847,25 +847,59 @@ void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *sour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* helper functioon for 'BM_mesh_copy' */
|
||||||
|
static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old,
|
||||||
|
BMVert **vtable, BMEdge **etable,
|
||||||
|
BMFace *f)
|
||||||
|
{
|
||||||
|
BMLoop **loops = BLI_array_alloca(loops, f->len);
|
||||||
|
BMVert **verts = BLI_array_alloca(verts, f->len);
|
||||||
|
BMEdge **edges = BLI_array_alloca(edges, f->len);
|
||||||
|
|
||||||
|
BMFace *f_new;
|
||||||
|
BMLoop *l_iter, *l_first;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||||
|
do {
|
||||||
|
loops[j] = l_iter;
|
||||||
|
verts[j] = vtable[BM_elem_index_get(l_iter->v)];
|
||||||
|
edges[j] = etable[BM_elem_index_get(l_iter->e)];
|
||||||
|
j++;
|
||||||
|
} while ((l_iter = l_iter->next) != l_first);
|
||||||
|
|
||||||
|
f_new = BM_face_create(bm_new, verts, edges, f->len, BM_CREATE_SKIP_CD);
|
||||||
|
|
||||||
|
if (UNLIKELY(f_new == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use totface in case adding some faces fails */
|
||||||
|
BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */
|
||||||
|
|
||||||
|
BM_elem_attrs_copy(bm_old, bm_new, f, f_new);
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
|
||||||
|
do {
|
||||||
|
BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter);
|
||||||
|
j++;
|
||||||
|
} while ((l_iter = l_iter->next) != l_first);
|
||||||
|
|
||||||
|
return f_new;
|
||||||
|
}
|
||||||
|
|
||||||
BMesh *BM_mesh_copy(BMesh *bm_old)
|
BMesh *BM_mesh_copy(BMesh *bm_old)
|
||||||
{
|
{
|
||||||
#define USE_FAST_FACE_COPY
|
|
||||||
|
|
||||||
BMesh *bm_new;
|
BMesh *bm_new;
|
||||||
BMVert *v, *v2, **vtable = NULL;
|
BMVert *v, *v_new, **vtable = NULL;
|
||||||
BMEdge *e, *e2, **edges = NULL, **etable = NULL;
|
BMEdge *e, *e_new, **etable = NULL;
|
||||||
|
BMFace *f, *f_new, **ftable = NULL;
|
||||||
BMElem **eletable;
|
BMElem **eletable;
|
||||||
BLI_array_declare(edges);
|
|
||||||
BMLoop *l, /* *l2, */ **loops = NULL;
|
|
||||||
BLI_array_declare(loops);
|
|
||||||
#ifdef USE_FAST_FACE_COPY
|
|
||||||
BMVert **verts = NULL;
|
|
||||||
BLI_array_declare(verts);
|
|
||||||
#endif
|
|
||||||
BMFace *f, *f2, **ftable = NULL;
|
|
||||||
BMEditSelection *ese;
|
BMEditSelection *ese;
|
||||||
BMIter iter, liter;
|
BMIter iter;
|
||||||
int i, j;
|
int i;
|
||||||
const BMAllocTemplate allocsize = {bm_old->totvert,
|
const BMAllocTemplate allocsize = {bm_old->totvert,
|
||||||
bm_old->totedge,
|
bm_old->totedge,
|
||||||
bm_old->totloop,
|
bm_old->totloop,
|
||||||
@ -888,13 +922,12 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
|
|||||||
etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
|
etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
|
||||||
ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
|
ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
|
||||||
|
|
||||||
v = BM_iter_new(&iter, bm_old, BM_VERTS_OF_MESH, NULL);
|
BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) {
|
||||||
for (i = 0; v; v = BM_iter_step(&iter), i++) {
|
v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); /* copy between meshes so cant use 'example' argument */
|
||||||
v2 = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); /* copy between meshes so cant use 'example' argument */
|
BM_elem_attrs_copy(bm_old, bm_new, v, v_new);
|
||||||
BM_elem_attrs_copy(bm_old, bm_new, v, v2);
|
vtable[i] = v_new;
|
||||||
vtable[i] = v2;
|
|
||||||
BM_elem_index_set(v, i); /* set_inline */
|
BM_elem_index_set(v, i); /* set_inline */
|
||||||
BM_elem_index_set(v2, i); /* set_inline */
|
BM_elem_index_set(v_new, i); /* set_inline */
|
||||||
}
|
}
|
||||||
bm_old->elem_index_dirty &= ~BM_VERT;
|
bm_old->elem_index_dirty &= ~BM_VERT;
|
||||||
bm_new->elem_index_dirty &= ~BM_VERT;
|
bm_new->elem_index_dirty &= ~BM_VERT;
|
||||||
@ -902,17 +935,16 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
|
|||||||
/* safety check */
|
/* safety check */
|
||||||
BLI_assert(i == bm_old->totvert);
|
BLI_assert(i == bm_old->totvert);
|
||||||
|
|
||||||
e = BM_iter_new(&iter, bm_old, BM_EDGES_OF_MESH, NULL);
|
BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) {
|
||||||
for (i = 0; e; e = BM_iter_step(&iter), i++) {
|
e_new = BM_edge_create(bm_new,
|
||||||
e2 = BM_edge_create(bm_new,
|
vtable[BM_elem_index_get(e->v1)],
|
||||||
vtable[BM_elem_index_get(e->v1)],
|
vtable[BM_elem_index_get(e->v2)],
|
||||||
vtable[BM_elem_index_get(e->v2)],
|
e, BM_CREATE_SKIP_CD);
|
||||||
e, BM_CREATE_SKIP_CD);
|
|
||||||
|
|
||||||
BM_elem_attrs_copy(bm_old, bm_new, e, e2);
|
BM_elem_attrs_copy(bm_old, bm_new, e, e_new);
|
||||||
etable[i] = e2;
|
etable[i] = e_new;
|
||||||
BM_elem_index_set(e, i); /* set_inline */
|
BM_elem_index_set(e, i); /* set_inline */
|
||||||
BM_elem_index_set(e2, i); /* set_inline */
|
BM_elem_index_set(e_new, i); /* set_inline */
|
||||||
}
|
}
|
||||||
bm_old->elem_index_dirty &= ~BM_EDGE;
|
bm_old->elem_index_dirty &= ~BM_EDGE;
|
||||||
bm_new->elem_index_dirty &= ~BM_EDGE;
|
bm_new->elem_index_dirty &= ~BM_EDGE;
|
||||||
@ -920,61 +952,14 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
|
|||||||
/* safety check */
|
/* safety check */
|
||||||
BLI_assert(i == bm_old->totedge);
|
BLI_assert(i == bm_old->totedge);
|
||||||
|
|
||||||
f = BM_iter_new(&iter, bm_old, BM_FACES_OF_MESH, NULL);
|
BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) {
|
||||||
for (i = 0; f; f = BM_iter_step(&iter), i++) {
|
|
||||||
BM_elem_index_set(f, i); /* set_inline */
|
BM_elem_index_set(f, i); /* set_inline */
|
||||||
|
|
||||||
BLI_array_empty(loops);
|
f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f);
|
||||||
BLI_array_empty(edges);
|
|
||||||
BLI_array_grow_items(loops, f->len);
|
|
||||||
BLI_array_grow_items(edges, f->len);
|
|
||||||
|
|
||||||
#ifdef USE_FAST_FACE_COPY
|
ftable[i] = f_new;
|
||||||
BLI_array_empty(verts);
|
|
||||||
BLI_array_grow_items(verts, f->len);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
l = BM_iter_new(&liter, bm_old, BM_LOOPS_OF_FACE, f);
|
if (f == bm_old->act_face) bm_new->act_face = f_new;
|
||||||
for (j = 0; j < f->len; j++, l = BM_iter_step(&liter)) {
|
|
||||||
loops[j] = l;
|
|
||||||
edges[j] = etable[BM_elem_index_get(l->e)];
|
|
||||||
|
|
||||||
#ifdef USE_FAST_FACE_COPY
|
|
||||||
verts[j] = vtable[BM_elem_index_get(l->v)];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_FAST_FACE_COPY
|
|
||||||
f2 = BM_face_create(bm_new, verts, edges, f->len, BM_CREATE_SKIP_CD);
|
|
||||||
#else
|
|
||||||
v = vtable[BM_elem_index_get(loops[0]->v)];
|
|
||||||
v2 = vtable[BM_elem_index_get(loops[1]->v)];
|
|
||||||
|
|
||||||
if (!bmesh_verts_in_edge(v, v2, edges[0])) {
|
|
||||||
v = vtable[BM_elem_index_get(loops[BLI_array_count(loops) - 1]->v)];
|
|
||||||
v2 = vtable[BM_elem_index_get(loops[0]->v)];
|
|
||||||
}
|
|
||||||
|
|
||||||
f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, BM_CREATE_SKIP_CD);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (UNLIKELY(f2 == NULL)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* use totface in case adding some faces fails */
|
|
||||||
BM_elem_index_set(f2, (bm_new->totface - 1)); /* set_inline */
|
|
||||||
|
|
||||||
ftable[i] = f2;
|
|
||||||
|
|
||||||
BM_elem_attrs_copy(bm_old, bm_new, f, f2);
|
|
||||||
copy_v3_v3(f2->no, f->no);
|
|
||||||
|
|
||||||
l = BM_iter_new(&liter, bm_new, BM_LOOPS_OF_FACE, f2);
|
|
||||||
for (j = 0; j < f->len; j++, l = BM_iter_step(&liter)) {
|
|
||||||
BM_elem_attrs_copy(bm_old, bm_new, loops[j], l);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == bm_old->act_face) bm_new->act_face = f2;
|
|
||||||
}
|
}
|
||||||
bm_old->elem_index_dirty &= ~BM_FACE;
|
bm_old->elem_index_dirty &= ~BM_FACE;
|
||||||
bm_new->elem_index_dirty &= ~BM_FACE;
|
bm_new->elem_index_dirty &= ~BM_FACE;
|
||||||
@ -1013,12 +998,6 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
|
|||||||
MEM_freeN(vtable);
|
MEM_freeN(vtable);
|
||||||
MEM_freeN(ftable);
|
MEM_freeN(ftable);
|
||||||
|
|
||||||
#ifdef USE_FAST_FACE_COPY
|
|
||||||
BLI_array_free(verts);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BLI_array_free(loops);
|
|
||||||
BLI_array_free(edges);
|
|
||||||
return bm_new;
|
return bm_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user