diff options
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_mesh_duplicate.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh_duplicate.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/source/blender/bmesh/intern/bmesh_mesh_duplicate.c b/source/blender/bmesh/intern/bmesh_mesh_duplicate.c new file mode 100644 index 00000000000..51f9d2eab1d --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_mesh_duplicate.c @@ -0,0 +1,139 @@ +/* + * 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); +} |