138 lines
4.4 KiB
C
138 lines
4.4 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
/** \file
|
|
* \ingroup bmesh
|
|
*
|
|
* Duplicate geometry from one mesh from another.
|
|
*/
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_alloca.h"
|
|
#include "BLI_math_vector.h"
|
|
|
|
#include "bmesh.h"
|
|
#include "intern/bmesh_private.h" /* for element checking */
|
|
|
|
static BMVert *bm_vert_copy(BMesh *bm_src, BMesh *bm_dst, BMVert *v_src)
|
|
{
|
|
BMVert *v_dst = BM_vert_create(bm_dst, v_src->co, NULL, BM_CREATE_SKIP_CD);
|
|
BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
|
|
return v_dst;
|
|
}
|
|
|
|
static BMEdge *bm_edge_copy_with_arrays(BMesh *bm_src,
|
|
BMesh *bm_dst,
|
|
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, NULL, BM_CREATE_SKIP_CD);
|
|
BM_elem_attrs_copy(bm_src, 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)
|
|
{
|
|
BMFace *f_dst;
|
|
BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
|
|
BMEdge **edar = BLI_array_alloca(edar, f_src->len);
|
|
BMLoop *l_iter_src, *l_iter_dst, *l_first_src;
|
|
int i;
|
|
|
|
l_first_src = BM_FACE_FIRST_LOOP(f_src);
|
|
|
|
/* Lookup verts & edges. */
|
|
l_iter_src = l_first_src;
|
|
i = 0;
|
|
do {
|
|
vtar[i] = verts_dst[BM_elem_index_get(l_iter_src->v)];
|
|
edar[i] = edges_dst[BM_elem_index_get(l_iter_src->e)];
|
|
i++;
|
|
} while ((l_iter_src = l_iter_src->next) != l_first_src);
|
|
|
|
/* Create new face. */
|
|
f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, NULL, BM_CREATE_SKIP_CD);
|
|
|
|
/* Copy attributes. */
|
|
BM_elem_attrs_copy(bm_src, 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);
|
|
} while ((void)(l_iter_dst = l_iter_dst->next), (l_iter_src = l_iter_src->next) != l_first_src);
|
|
|
|
return f_dst;
|
|
}
|
|
|
|
/**
|
|
* Geometry must be completely isolated.
|
|
*/
|
|
void BM_mesh_copy_arrays(BMesh *bm_src,
|
|
BMesh *bm_dst,
|
|
BMVert **verts_src,
|
|
uint verts_src_len,
|
|
BMEdge **edges_src,
|
|
uint edges_src_len,
|
|
BMFace **faces_src,
|
|
uint faces_src_len)
|
|
{
|
|
/* Vertices. */
|
|
BMVert **verts_dst = MEM_mallocN(sizeof(*verts_dst) * verts_src_len, __func__);
|
|
for (uint i = 0; i < verts_src_len; i++) {
|
|
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);
|
|
BM_elem_index_set(v_dst, i); /* set_ok */
|
|
verts_dst[i] = v_dst;
|
|
}
|
|
bm_src->elem_index_dirty |= BM_VERT;
|
|
bm_dst->elem_index_dirty &= ~BM_VERT;
|
|
|
|
/* Edges. */
|
|
BMEdge **edges_dst = MEM_mallocN(sizeof(*edges_dst) * edges_src_len, __func__);
|
|
for (uint i = 0; i < edges_src_len; i++) {
|
|
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);
|
|
BM_elem_index_set(e_dst, i);
|
|
edges_dst[i] = e_dst;
|
|
}
|
|
bm_src->elem_index_dirty |= BM_EDGE;
|
|
bm_dst->elem_index_dirty &= ~BM_EDGE;
|
|
|
|
/* 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);
|
|
BM_elem_index_set(f_dst, i);
|
|
}
|
|
bm_dst->elem_index_dirty &= ~BM_FACE;
|
|
|
|
/* Cleanup. */
|
|
MEM_freeN(verts_dst);
|
|
MEM_freeN(edges_dst);
|
|
}
|