Welcome to mirror list, hosted at ThFree Co, Russian Federation.

bmesh_core.h « intern « bmesh « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a885df51bd34beddab1d2df448841a7dc6cfcf18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
/*
 * 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.
 */

#pragma once

/** \file
 * \ingroup bmesh
 */

BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, bool copy_verts, bool copy_edges);

typedef enum eBMCreateFlag {
  BM_CREATE_NOP = 0,
  /** Faces and edges only. */
  BM_CREATE_NO_DOUBLE = (1 << 1),
  /**
   * Skip custom-data - for all element types data,
   * use if we immediately write custom-data into the element so this skips copying from 'example'
   * arguments or setting defaults, speeds up conversion when data is converted all at once.
   */
  BM_CREATE_SKIP_CD = (1 << 2),
} eBMCreateFlag;

/**
 * \brief Main function for creating a new vertex.
 */
BMVert *BM_vert_create(BMesh *bm,
                       const float co[3],
                       const BMVert *v_example,
                       eBMCreateFlag create_flag);
/**
 * \brief Main function for creating a new edge.
 *
 * \note Duplicate edges are supported by the API however users should _never_ see them.
 * so unless you need a unique edge or know the edge won't exist,
 * you should call with \a no_double = true.
 */
BMEdge *BM_edge_create(
    BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, eBMCreateFlag create_flag);
/**
 * Main face creation function
 *
 * \param bm: The mesh
 * \param verts: A sorted array of verts size of len
 * \param edges: A sorted array of edges size of len
 * \param len: Length of the face
 * \param create_flag: Options for creating the face
 */
BMFace *BM_face_create(BMesh *bm,
                       BMVert **verts,
                       BMEdge **edges,
                       int len,
                       const BMFace *f_example,
                       eBMCreateFlag create_flag);
/**
 * Wrapper for #BM_face_create when you don't have an edge array
 */
BMFace *BM_face_create_verts(BMesh *bm,
                             BMVert **vert_arr,
                             int len,
                             const BMFace *f_example,
                             eBMCreateFlag create_flag,
                             bool create_edges);

/**
 * Kills all edges associated with \a f, along with any other faces containing those edges.
 */
void BM_face_edges_kill(BMesh *bm, BMFace *f);
/**
 * kills all verts associated with \a f, along with any other faces containing
 * those vertices
 */
void BM_face_verts_kill(BMesh *bm, BMFace *f);

/**
 * A version of #BM_face_kill which removes edges and verts
 * which have no remaining connected geometry.
 */
void BM_face_kill_loose(BMesh *bm, BMFace *f);

/**
 * Kills \a f and its loops.
 */
void BM_face_kill(BMesh *bm, BMFace *f);
/**
 * Kills \a e and all faces that use it.
 */
void BM_edge_kill(BMesh *bm, BMEdge *e);
/**
 * Kills \a v and all edges that use it.
 */
void BM_vert_kill(BMesh *bm, BMVert *v);

/**
 * \brief Splice Edge
 *
 * Splice two unique edges which share the same two vertices into one edge.
 *  (\a e_src into \a e_dst, removing e_src).
 *
 * \return Success
 *
 * \note Edges must already have the same vertices.
 */
bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src);
/**
 * \brief Splice Vert
 *
 * Merges two verts into one
 * (\a v_src into \a v_dst, removing \a v_src).
 *
 * \return Success
 *
 * \warning This doesn't work for collapsing edges,
 * where \a v and \a vtarget are connected by an edge
 * (assert checks for this case).
 */
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src);
/**
 * Check if splicing vertices would create any double edges.
 *
 * \note assume caller will handle case where verts share an edge.
 */
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);

/**
 * \brief Loop Reverse
 *
 * Changes the winding order of a face from CW to CCW or vice versa.
 *
 * \param cd_loop_mdisp_offset: Cached result of `CustomData_get_offset(&bm->ldata, CD_MDISPS)`.
 * \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp,
 * (use when flipping normals, disable when mirroring, eg: symmetrize).
 */
void bmesh_kernel_loop_reverse(BMesh *bm,
                               BMFace *f,
                               int cd_loop_mdisp_offset,
                               bool use_loop_mdisp_flip);

/**
 * Avoid calling this where possible,
 * low level function so both face pointers remain intact but point to swapped data.
 * \note must be from the same bmesh.
 */
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);

/**
 * \brief Join Connected Faces
 *
 * Joins a collected group of faces into one. Only restriction on
 * the input data is that the faces must be connected to each other.
 *
 * \return The newly created combine BMFace.
 *
 * \note If a pair of faces share multiple edges,
 * the pair of faces will be joined at every edge.
 *
 * \note this is a generic, flexible join faces function,
 * almost everything uses this, including #BM_faces_join_pair
 */
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, bool do_del);
/**
 * High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate
 */
void BM_vert_separate(BMesh *bm,
                      BMVert *v,
                      BMEdge **e_in,
                      int e_in_len,
                      bool copy_select,
                      BMVert ***r_vout,
                      int *r_vout_len);
/**
 * A version of #BM_vert_separate which takes a flag.
 */
void BM_vert_separate_hflag(
    BMesh *bm, BMVert *v, char hflag, bool copy_select, BMVert ***r_vout, int *r_vout_len);
void BM_vert_separate_tested_edges(
    BMesh *bm, BMVert *v_dst, BMVert *v_src, bool (*testfn)(BMEdge *, void *arg), void *arg);

/**
 * BMesh Kernel: For modifying structure.
 *
 * Names are on the verbose side but these are only for low-level access.
 */
/**
 * \brief Separate Vert
 *
 * Separates all disjoint fans that meet at a vertex, making a unique
 * vertex for each region. returns an array of all resulting vertices.
 *
 * \note this is a low level function, bm_edge_separate needs to run on edges first
 * or, the faces sharing verts must not be sharing edges for them to split at least.
 *
 * \return Success
 */
void bmesh_kernel_vert_separate(
    BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, bool copy_select);
/**
 * \brief Separate Edge
 *
 * Separates a single edge into two edge: the original edge and
 * a new edge that has only \a l_sep in its radial.
 *
 * \return Success
 *
 * \note Does nothing if \a l_sep is already the only loop in the
 * edge radial.
 */
void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, bool copy_select);

/**
 * \brief Split Face Make Edge (SFME)
 *
 * \warning this is a low level function, most likely you want to use #BM_face_split()
 *
 * Takes as input two vertices in a single face.
 * An edge is created which divides the original face into two distinct regions.
 * One of the regions is assigned to the original face and it is closed off.
 * The second region has a new face assigned to it.
 *
 * \par Examples:
 * <pre>
 *     Before:               After:
 *      +--------+           +--------+
 *      |        |           |        |
 *      |        |           |   f1   |
 *     v1   f1   v2          v1======v2
 *      |        |           |   f2   |
 *      |        |           |        |
 *      +--------+           +--------+
 * </pre>
 *
 * \note the input vertices can be part of the same edge. This will
 * result in a two edged face. This is desirable for advanced construction
 * tools and particularly essential for edge bevel. Because of this it is
 * up to the caller to decide what to do with the extra edge.
 *
 * \note If \a holes is NULL, then both faces will lose
 * all holes from the original face.  Also, you cannot split between
 * a hole vert and a boundary vert; that case is handled by higher-
 * level wrapping functions (when holes are fully implemented, anyway).
 *
 * \note that holes represents which holes goes to the new face, and of
 * course this requires removing them from the existing face first, since
 * you cannot have linked list links inside multiple lists.
 *
 * \return A BMFace pointer
 */
BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
                                          BMFace *f,
                                          BMLoop *l_v1,
                                          BMLoop *l_v2,
                                          BMLoop **r_l,
#ifdef USE_BMESH_HOLES
                                          ListBase *holes,
#endif
                                          BMEdge *example,
                                          bool no_double);

/**
 * \brief Split Edge Make Vert (SEMV)
 *
 * Takes \a e edge and splits it into two, creating a new vert.
 * \a tv should be one end of \a e : the newly created edge
 * will be attached to that end and is returned in \a r_e.
 *
 * \par Examples:
 *
 * <pre>
 *                     E
 *     Before: OV-------------TV
 *                 E       RE
 *     After:  OV------NV-----TV
 * </pre>
 *
 * \return The newly created BMVert pointer.
 */
BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
/**
 * \brief Join Edge Kill Vert (JEKV)
 *
 * Takes an edge \a e_kill and pointer to one of its vertices \a v_kill
 * and collapses the edge on that vertex.
 *
 * \par Examples:
 *
 * <pre>
 *     Before:    e_old  e_kill
 *              +-------+-------+
 *              |       |       |
 *              v_old   v_kill  v_target
 *
 *     After:           e_old
 *              +---------------+
 *              |               |
 *              v_old           v_target
 * </pre>
 *
 * \par Restrictions:
 * KV is a vertex that must have a valance of exactly two. Furthermore
 * both edges in KV's disk cycle (OE and KE) must be unique (no double edges).
 *
 * \return The resulting edge, NULL for failure.
 *
 * \note This euler has the possibility of creating
 * faces with just 2 edges. It is up to the caller to decide what to do with
 * these faces.
 */
BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
                                         BMEdge *e_kill,
                                         BMVert *v_kill,
                                         bool do_del,
                                         bool check_edge_exists,
                                         bool kill_degenerate_faces,
                                         bool kill_duplicate_faces);
/**
 * \brief Join Vert Kill Edge (JVKE)
 *
 * Collapse an edge, merging surrounding data.
 *
 * Unlike #BM_vert_collapse_edge & #bmesh_kernel_join_edge_kill_vert
 * which only handle 2 valence verts,
 * this can handle any number of connected edges/faces.
 *
 * <pre>
 * Before: -> After:
 * +-+-+-+    +-+-+-+
 * | | | |    | \ / |
 * +-+-+-+    +--+--+
 * | | | |    | / \ |
 * +-+-+-+    +-+-+-+
 * </pre>
 */
BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
                                         BMEdge *e_kill,
                                         BMVert *v_kill,
                                         bool do_del,
                                         bool check_edge_exists,
                                         bool kill_degenerate_faces);
/**
 * \brief Join Face Kill Edge (JFKE)
 *
 * Takes two faces joined by a single 2-manifold edge and fuses them together.
 * The edge shared by the faces must not be connected to any other edges which have
 * Both faces in its radial cycle
 *
 * \par Examples:
 * <pre>
 *           A                   B
 *      +--------+           +--------+
 *      |        |           |        |
 *      |   f1   |           |   f1   |
 *     v1========v2 = Ok!    v1==V2==v3 == Wrong!
 *      |   f2   |           |   f2   |
 *      |        |           |        |
 *      +--------+           +--------+
 * </pre>
 *
 * In the example A, faces \a f1 and \a f2 are joined by a single edge,
 * and the euler can safely be used.
 * In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error.
 * The caller in this case should call #bmesh_kernel_join_edge_kill_vert on the extra edges
 * before attempting to fuse \a f1 and \a f2.
 *
 * \note The order of arguments decides whether or not certain per-face attributes are present
 * in the resultant face. For instance vertex winding, material index, smooth flags,
 * etc are inherited from \a f1, not \a f2.
 *
 * \return A BMFace pointer
 */
BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);

/**
 * \brief Un-glue Region Make Vert (URMV)
 *
 * Disconnects a face from its vertex fan at loop \a l_sep
 *
 * \return The newly created BMVert
 *
 * \note Will be a no-op and return original vertex if only two edges at that vertex.
 */
BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep);
/**
 * A version of #bmesh_kernel_unglue_region_make_vert that disconnects multiple loops at once.
 * The loops must all share the same vertex, can be in any order
 * and are all moved to use a single new vertex - which is returned.
 *
 * This function handles the details of finding fans boundaries.
 */
BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len);
/**
 * This function assumes l_sep is a part of a larger fan which has already been
 * isolated by calling #bmesh_kernel_edge_separate to segregate it radially.
 */
BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep);