Blender V4.3
bmesh_mesh_duplicate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include "MEM_guardedalloc.h"
12
13#include "BLI_alloca.h"
14
15#include "bmesh.hh"
16
17static BMVert *bm_vert_copy(BMesh *bm_dst,
18 const std::optional<BMCustomDataCopyMap> &cd_vert_map,
19 BMVert *v_src)
20{
21 BMVert *v_dst = BM_vert_create(bm_dst, v_src->co, nullptr, BM_CREATE_SKIP_CD);
22 if (cd_vert_map.has_value()) {
23 BM_elem_attrs_copy(bm_dst, cd_vert_map.value(), v_src, v_dst);
24 }
25 else {
26 BM_elem_attrs_copy(bm_dst, v_src, v_dst);
27 }
28 return v_dst;
29}
30
32 const std::optional<BMCustomDataCopyMap> &cd_edge_map,
33 BMEdge *e_src,
34 BMVert **verts_dst)
35{
36 BMVert *e_dst_v1 = verts_dst[BM_elem_index_get(e_src->v1)];
37 BMVert *e_dst_v2 = verts_dst[BM_elem_index_get(e_src->v2)];
38 BMEdge *e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, nullptr, BM_CREATE_SKIP_CD);
39 if (cd_edge_map.has_value()) {
40 BM_elem_attrs_copy(bm_dst, cd_edge_map.value(), e_src, e_dst);
41 }
42 else {
43 BM_elem_attrs_copy(bm_dst, e_src, e_dst);
44 }
45 return e_dst;
46}
47
49 const std::optional<BMCustomDataCopyMap> cd_face_map,
50 const std::optional<BMCustomDataCopyMap> &cd_loop_map,
51 BMFace *f_src,
52 BMVert **verts_dst,
53 BMEdge **edges_dst)
54{
55 BMFace *f_dst;
56 BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
57 BMEdge **edar = BLI_array_alloca(edar, f_src->len);
58 BMLoop *l_iter_src, *l_iter_dst, *l_first_src;
59 int i;
60
61 l_first_src = BM_FACE_FIRST_LOOP(f_src);
62
63 /* Lookup verts & edges. */
64 l_iter_src = l_first_src;
65 i = 0;
66 do {
67 vtar[i] = verts_dst[BM_elem_index_get(l_iter_src->v)];
68 edar[i] = edges_dst[BM_elem_index_get(l_iter_src->e)];
69 i++;
70 } while ((l_iter_src = l_iter_src->next) != l_first_src);
71
72 /* Create new face. */
73 f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, nullptr, BM_CREATE_SKIP_CD);
74
75 /* Copy attributes. */
76 if (cd_face_map.has_value()) {
77 BM_elem_attrs_copy(bm_dst, cd_face_map.value(), f_src, f_dst);
78 }
79 else {
80 BM_elem_attrs_copy(bm_dst, f_src, f_dst);
81 }
82
83 /* Copy per-loop custom data. */
84 l_iter_src = l_first_src;
85 l_iter_dst = BM_FACE_FIRST_LOOP(f_dst);
86 do {
87 if (cd_loop_map.has_value()) {
88 BM_elem_attrs_copy(bm_dst, cd_loop_map.value(), l_iter_src, l_iter_dst);
89 }
90 else {
91 BM_elem_attrs_copy(bm_dst, l_iter_src, l_iter_dst);
92 }
93 } while ((void)(l_iter_dst = l_iter_dst->next), (l_iter_src = l_iter_src->next) != l_first_src);
94
95 return f_dst;
96}
97
99 BMesh *bm_dst,
100 BMVert **verts_src,
101 uint verts_src_len,
102 BMEdge **edges_src,
103 uint edges_src_len,
104 BMFace **faces_src,
105 uint faces_src_len)
106{
107 const std::optional<BMCustomDataCopyMap> cd_vert_map =
108 (bm_src == bm_dst) ? std::nullopt :
109 std::optional<BMCustomDataCopyMap>{
110 CustomData_bmesh_copy_map_calc(bm_src->vdata, bm_dst->vdata)};
111 const std::optional<BMCustomDataCopyMap> cd_edge_map =
112 (bm_src == bm_dst) ? std::nullopt :
113 std::optional<BMCustomDataCopyMap>{
114 CustomData_bmesh_copy_map_calc(bm_src->edata, bm_dst->edata)};
115 const std::optional<BMCustomDataCopyMap> cd_face_map =
116 (bm_src == bm_dst) ? std::nullopt :
117 std::optional<BMCustomDataCopyMap>{
118 CustomData_bmesh_copy_map_calc(bm_src->pdata, bm_dst->pdata)};
119 const std::optional<BMCustomDataCopyMap> cd_loop_map =
120 (bm_src == bm_dst) ? std::nullopt :
121 std::optional<BMCustomDataCopyMap>{
122 CustomData_bmesh_copy_map_calc(bm_src->ldata, bm_dst->ldata)};
123
124 /* Vertices. */
125 BMVert **verts_dst = static_cast<BMVert **>(
126 MEM_mallocN(sizeof(*verts_dst) * verts_src_len, __func__));
127 for (uint i = 0; i < verts_src_len; i++) {
128 BMVert *v_src = verts_src[i];
129 BM_elem_index_set(v_src, i); /* set_dirty! */
130
131 BMVert *v_dst = bm_vert_copy(bm_dst, cd_vert_map, v_src);
132 BM_elem_index_set(v_dst, i); /* set_ok */
133 verts_dst[i] = v_dst;
134 }
135 bm_src->elem_index_dirty |= BM_VERT;
136 bm_dst->elem_index_dirty &= ~BM_VERT;
137
138 /* Edges. */
139 BMEdge **edges_dst = static_cast<BMEdge **>(
140 MEM_mallocN(sizeof(*edges_dst) * edges_src_len, __func__));
141 for (uint i = 0; i < edges_src_len; i++) {
142 BMEdge *e_src = edges_src[i];
143 BM_elem_index_set(e_src, i); /* set_dirty! */
144
145 BMEdge *e_dst = bm_edge_copy_with_arrays(bm_dst, cd_edge_map, e_src, verts_dst);
146 BM_elem_index_set(e_dst, i);
147 edges_dst[i] = e_dst;
148 }
149 bm_src->elem_index_dirty |= BM_EDGE;
150 bm_dst->elem_index_dirty &= ~BM_EDGE;
151
152 /* Faces. */
153 for (uint i = 0; i < faces_src_len; i++) {
154 BMFace *f_src = faces_src[i];
156 bm_dst, cd_face_map, cd_loop_map, f_src, verts_dst, edges_dst);
157 BM_elem_index_set(f_dst, i);
158 }
159 bm_dst->elem_index_dirty &= ~BM_FACE;
160
161 /* Cleanup. */
162 MEM_freeN(verts_dst);
163 MEM_freeN(edges_dst);
164}
BMCustomDataCopyMap CustomData_bmesh_copy_map_calc(const CustomData &src, const CustomData &dst, eCustomDataMask mask_exclude=0)
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:25
unsigned int uint
Read Guarded memory(de)allocation.
#define BM_FACE_FIRST_LOOP(p)
void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMVert *src, BMVert *dst)
BMFace * BM_face_create(BMesh *bm, BMVert *const *verts, BMEdge *const *edges, const int len, const BMFace *f_example, const eBMCreateFlag create_flag)
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
Definition bmesh_core.cc:43
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
@ BM_CREATE_SKIP_CD
Definition bmesh_core.hh:32
#define BM_elem_index_get(ele)
#define BM_elem_index_set(ele, index)
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)
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)
static BMVert * bm_vert_copy(BMesh *bm_dst, const std::optional< BMCustomDataCopyMap > &cd_vert_map, BMVert *v_src)
static BMEdge * bm_edge_copy_with_arrays(BMesh *bm_dst, const std::optional< BMCustomDataCopyMap > &cd_edge_map, BMEdge *e_src, BMVert **verts_dst)
#define BM_EDGE
#define BM_VERT
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
BMVert * v1
BMVert * v2
struct BMVert * v
struct BMEdge * e
struct BMLoop * next
float co[3]
char elem_index_dirty
CustomData vdata
CustomData edata
CustomData pdata
CustomData ldata