Blender  V2.93
editmesh.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "DNA_listBase.h"
27 #include "DNA_mesh_types.h"
28 #include "DNA_object_types.h"
29 
30 #include "BLI_bitmap.h"
31 #include "BLI_math.h"
32 
33 #include "BKE_DerivedMesh.h"
34 #include "BKE_editmesh.h"
35 #include "BKE_editmesh_cache.h"
36 #include "BKE_lib_id.h"
37 #include "BKE_mesh.h"
38 #include "BKE_mesh_iterators.h"
39 #include "BKE_mesh_wrapper.h"
40 #include "BKE_object.h"
41 
42 BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
43 {
44  BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
45 
46  em->bm = bm;
47  if (do_tessellate) {
49  }
50 
51  return em;
52 }
53 
55 {
56  BMEditMesh *em_copy = MEM_callocN(sizeof(BMEditMesh), __func__);
57  *em_copy = *em;
58 
59  em_copy->mesh_eval_cage = em_copy->mesh_eval_final = NULL;
60  em_copy->bb_cage = NULL;
61 
62  em_copy->bm = BM_mesh_copy(em->bm);
63 
64  /* The tessellation is NOT calculated on the copy here,
65  * because currently all the callers of this function use
66  * it to make a backup copy of the #BMEditMesh to restore
67  * it in the case of errors in an operation. For performance reasons,
68  * in that case it makes more sense to do the
69  * tessellation only when/if that copy ends up getting used. */
70  em_copy->looptris = NULL;
71 
72  /* Copy various settings. */
73  em_copy->selectmode = em->selectmode;
74  em_copy->mat_nr = em->mat_nr;
75 
76  return em_copy;
77 }
78 
86 {
87  BLI_assert(ob->type == OB_MESH);
88  /* sanity check */
89 #if 0 /* disable in mutlti-object edit. */
90 # ifndef NDEBUG
91  if (((Mesh *)ob->data)->edit_mesh) {
92  BLI_assert(((Mesh *)ob->data)->edit_mesh->ob == ob);
93  }
94 # endif
95 #endif
96  return ((Mesh *)ob->data)->edit_mesh;
97 }
98 
100 {
101  /* allocating space before calculating the tessellation */
102 
103  BMesh *bm = em->bm;
104 
105  /* This assumes all faces can be scan-filled, which isn't always true,
106  * worst case we over allocate a little which is acceptable. */
107  const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
108  const int looptris_tot_prev_alloc = em->looptris ?
109  (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) :
110  0;
111 
112  BMLoop *(*looptris)[3];
113 
114  /* this means no reallocs for quad dominant models, for */
115  if ((em->looptris != NULL) &&
116  /* (*em->tottri >= looptris_tot)) */
117  /* Check against allocated size in case we over allocated a little. */
118  ((looptris_tot_prev_alloc >= looptris_tot) &&
119  (looptris_tot_prev_alloc <= looptris_tot * 2))) {
120  looptris = em->looptris;
121  }
122  else {
123  if (em->looptris) {
124  MEM_freeN(em->looptris);
125  }
126  looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__);
127  }
128 
129  em->looptris = looptris;
130 
131  /* after allocating the em->looptris, we're ready to tessellate */
133 }
134 
136 {
138 
139  /* commented because editbmesh_build_data() ensures we get tessfaces */
140 #if 0
141  if (em->mesh_eval_final && em->mesh_eval_final == em->mesh_eval_cage) {
143  }
144  else if (em->mesh_eval_final) {
147  }
148 #endif
149 }
150 
152 {
153  if (em->mesh_eval_cage) {
155  }
156  if (em->mesh_eval_final && em->mesh_eval_final != em->mesh_eval_cage) {
158  }
159  em->mesh_eval_cage = em->mesh_eval_final = NULL;
160 
161  MEM_SAFE_FREE(em->bb_cage);
162 }
163 
164 /*does not free the BMEditMesh struct itself*/
166 {
168 
169  if (em->looptris) {
170  MEM_freeN(em->looptris);
171  }
172 
173  if (em->bm) {
174  BM_mesh_free(em->bm);
175  }
176 }
177 
178 struct CageUserData {
179  int totvert;
182 };
183 
184 static void cage_mapped_verts_callback(void *userData,
185  int index,
186  const float co[3],
187  const float UNUSED(no_f[3]),
188  const short UNUSED(no_s[3]))
189 {
190  struct CageUserData *data = userData;
191 
192  if ((index >= 0 && index < data->totvert) && (!BLI_BITMAP_TEST(data->visit_bitmap, index))) {
193  BLI_BITMAP_ENABLE(data->visit_bitmap, index);
194  copy_v3_v3(data->cos_cage[index], co);
195  }
196 }
197 
199  BMEditMesh *em,
200  struct Scene *scene,
201  Object *ob,
202  int *r_vert_len))[3]
203 {
204  Mesh *cage;
206  struct CageUserData data;
207  float(*cos_cage)[3];
208 
210  cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
211 
212  /* when initializing cage verts, we only want the first cage coordinate for each vertex,
213  * so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
214  visit_bitmap = BLI_BITMAP_NEW(em->bm->totvert, __func__);
215 
216  data.totvert = em->bm->totvert;
217  data.cos_cage = cos_cage;
218  data.visit_bitmap = visit_bitmap;
219 
221 
223 
224  if (r_vert_len) {
225  *r_vert_len = em->bm->totvert;
226  }
227 
228  return cos_cage;
229 }
230 
232  BMEditMesh *em,
233  struct Scene *scene,
234  Object *ob,
235  int *r_vert_len,
236  bool *r_is_alloc))[3]
237 {
238  const float(*coords)[3] = NULL;
239  *r_is_alloc = false;
240 
241  Mesh *me = ob->data;
242 
243  if ((me->runtime.edit_data != NULL) && (me->runtime.edit_data->vertexCos != NULL)) {
244  /* Deformed, and we have deformed coords already. */
245  coords = me->runtime.edit_data->vertexCos;
246  }
247  else if ((em->mesh_eval_final != NULL) &&
248  (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
249  /* If this is an edit-mesh type, leave NULL as we can use the vertex coords. . */
250  }
251  else {
252  /* Constructive modifiers have been used, we need to allocate coordinates. */
253  *r_is_alloc = true;
254  coords = BKE_editmesh_vert_coords_alloc(depsgraph, em, scene, ob, r_vert_len);
255  }
256  return coords;
257 }
258 
260 {
261  return BM_mesh_vert_coords_alloc(em->bm, r_vert_len);
262 }
263 
265 {
266  BMesh *bm = em->bm;
267 
268  /* We need to create custom-loop-normals (CLNORS) data if none exist yet,
269  * otherwise there is no way to edit them.
270  * Similar code to #MESH_OT_customdata_custom_splitnormals_add operator,
271  * we want to keep same shading in case we were using auto-smooth so far.
272  * Note: there is a problem here, which is that if someone starts a normal editing operation on
273  * previously auto-smooth-ed mesh, and cancel that operation, generated CLNORS data remain,
274  * with related sharp edges (and hence auto-smooth is 'lost').
275  * Not sure how critical this is, and how to fix that issue? */
277  if (me->flag & ME_AUTOSMOOTH) {
279  }
280  }
281 
283 }
284 
285 /* If autosmooth not already set, set it */
287 {
288  if (!(me->flag & ME_AUTOSMOOTH)) {
289  me->flag |= ME_AUTOSMOOTH;
291  }
292 }
293 
295 {
296  if (em->bb_cage == NULL) {
297  float min[3], max[3];
298  INIT_MINMAX(min, max);
299  if (em->mesh_eval_cage) {
301  }
302 
303  em->bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage");
305  }
306 
307  return em->bb_cage;
308 }
typedef float(TangentPoint)[2]
struct Mesh * editbmesh_get_eval_cage(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *, struct BMEditMesh *em, const struct CustomData_MeshMasks *dataMask)
bool CustomData_has_layer(const struct CustomData *data, int type)
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.c:1919
void BKE_id_free(struct Main *bmain, void *idv)
@ MESH_FOREACH_NOP
void BKE_mesh_foreach_mapped_vert(struct Mesh *mesh, void(*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), void *userData, MeshForeachFlag flag)
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh)
Definition: mesh_runtime.c:155
bool BKE_mesh_wrapper_minmax(const struct Mesh *me, float min[3], float max[3])
General operations, lookup, etc. for blender objects.
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3])
Definition: object.c:3778
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define INIT_MINMAX(min, max)
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ CD_CUSTOMLOOPNORMAL
These structs are the foundation for all linked lists in the library system.
@ ME_WRAPPER_TYPE_BMESH
@ ME_AUTOSMOOTH
Object is a sort of wrapper for general info.
@ OB_MESH
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
BMesh * BM_mesh_copy(BMesh *bm_old)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_lnorspace_update(BMesh *bm)
Definition: bmesh_mesh.c:1565
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.c:307
float(* BM_mesh_vert_coords_alloc(BMesh *bm, int *r_vert_len))[3]
Definition: bmesh_mesh.c:3066
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
Definition: bmesh_mesh.c:1382
void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot)
BM_mesh_calc_tessellation get the looptris and its number from a certain bmesh.
Scene scene
const Depsgraph * depsgraph
void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, Mesh *me)
Definition: editmesh.c:286
static void editmesh_tessface_calc_intern(BMEditMesh *em)
Definition: editmesh.c:99
void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
Definition: editmesh.c:151
void BKE_editmesh_looptri_calc(BMEditMesh *em)
Definition: editmesh.c:135
BoundBox * BKE_editmesh_cage_boundbox_get(BMEditMesh *em)
Definition: editmesh.c:294
void BKE_editmesh_lnorspace_update(BMEditMesh *em, Mesh *me)
Definition: editmesh.c:264
static void cage_mapped_verts_callback(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
Definition: editmesh.c:184
void BKE_editmesh_free(BMEditMesh *em)
Definition: editmesh.c:165
const float(* BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph, BMEditMesh *em, struct Scene *scene, Object *ob, int *r_vert_len, bool *r_is_alloc))[3]
Definition: editmesh.c:231
BMEditMesh * BKE_editmesh_copy(BMEditMesh *em)
Definition: editmesh.c:54
float(* BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
Definition: editmesh.c:259
float(* BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph, BMEditMesh *em, struct Scene *scene, Object *ob, int *r_vert_len))[3]
Definition: editmesh.c:198
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
BMEditMesh * BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
Definition: editmesh.c:42
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:40
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
#define min(a, b)
Definition: sort.c:51
struct Mesh * mesh_eval_final
Definition: BKE_editmesh.h:63
struct Mesh * mesh_eval_cage
Definition: BKE_editmesh.h:63
struct BoundBox * bb_cage
Definition: BKE_editmesh.h:66
short selectmode
Definition: BKE_editmesh.h:72
struct BMLoop *(* looptris)[3]
Definition: BKE_editmesh.h:60
struct BMesh * bm
Definition: BKE_editmesh.h:52
short mat_nr
Definition: BKE_editmesh.h:73
int totloop
Definition: bmesh_class.h:297
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
BLI_bitmap * visit_bitmap
Definition: editmesh.c:181
float(* cos_cage)[3]
Definition: editmesh.c:180
const float(* vertexCos)[3]
struct EditMeshData * edit_data
float smoothresh
short flag
Mesh_Runtime runtime
void * data
float max