Blender  V3.3
sculpt_dyntopo.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_hash.h"
12 #include "BLI_math.h"
13 #include "BLI_task.h"
14 
15 #include "BLT_translation.h"
16 
17 #include "DNA_mesh_types.h"
18 #include "DNA_meshdata_types.h"
19 #include "DNA_modifier_types.h"
20 
21 #include "BKE_brush.h"
22 #include "BKE_context.h"
23 #include "BKE_global.h"
24 #include "BKE_main.h"
25 #include "BKE_mesh.h"
26 #include "BKE_mesh_mapping.h"
27 #include "BKE_modifier.h"
28 #include "BKE_object.h"
29 #include "BKE_paint.h"
30 #include "BKE_particle.h"
31 #include "BKE_pbvh.h"
32 #include "BKE_pointcache.h"
33 #include "BKE_scene.h"
34 #include "BKE_screen.h"
35 
36 #include "DEG_depsgraph.h"
37 
38 #include "WM_api.h"
39 #include "WM_message.h"
40 #include "WM_toolsystem.h"
41 #include "WM_types.h"
42 
43 #include "ED_object.h"
44 #include "ED_screen.h"
45 #include "ED_sculpt.h"
46 #include "ED_undo.h"
47 #include "ED_view3d.h"
48 #include "paint_intern.h"
49 #include "sculpt_intern.h"
50 
51 #include "RNA_access.h"
52 #include "RNA_define.h"
53 
54 #include "UI_interface.h"
55 #include "UI_resources.h"
56 
57 #include "bmesh.h"
58 #include "bmesh_tools.h"
59 
60 #include <math.h>
61 #include <stdlib.h>
62 
64 {
65  if (bm->totloop != bm->totface * 3) {
68  }
69 }
70 
72 {
73  SculptSession *ss = ob->sculpt;
74 
75  /* Clear out any existing DM and PBVH. */
76  if (ss->pbvh) {
77  BKE_pbvh_free(ss->pbvh);
78  ss->pbvh = NULL;
79  }
80 
81  MEM_SAFE_FREE(ss->pmap);
82 
84 
86 
87  /* Tag to rebuild PBVH in depsgraph. */
89 }
90 
92 {
93  int cd_node_layer_index;
94 
95  char layer_id[] = "_dyntopo_node_id";
96 
97  cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT32, layer_id);
98  if (cd_node_layer_index == -1) {
99  BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT32, layer_id);
100  cd_node_layer_index = CustomData_get_named_layer_index(
101  &ss->bm->vdata, CD_PROP_INT32, layer_id);
102  }
103 
105  &ss->bm->vdata,
107  cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT32));
108 
109  ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
110 
111  cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT32, layer_id);
112  if (cd_node_layer_index == -1) {
113  BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT32, layer_id);
114  cd_node_layer_index = CustomData_get_named_layer_index(
115  &ss->bm->pdata, CD_PROP_INT32, layer_id);
116  }
117 
119  &ss->bm->pdata,
121  cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT32));
122 
123  ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
124 }
125 
127 {
128  SculptSession *ss = ob->sculpt;
129  Mesh *me = ob->data;
130  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
131 
132  SCULPT_pbvh_clear(ob);
133 
135  0;
136 
137  /* Dynamic topology doesn't ensure selection state is valid, so remove T36280. */
139 
140  /* Create triangles-only BMesh. */
141  ss->bm = BM_mesh_create(&allocsize,
142  &((struct BMeshCreateParams){
143  .use_toolflags = false,
144  }));
145 
147  me,
148  (&(struct BMeshFromMeshParams){
149  .calc_face_normal = true,
150  .calc_vert_normal = true,
151  .use_shapekey = true,
152  .active_shapekey = ob->shapenr,
153  }));
157  /* Make sure the data for existing faces are initialized. */
158  if (me->totpoly != ss->bm->totface) {
160  }
161 
162  /* Enable dynamic topology. */
164 
165  /* Enable logging for undo/redo. */
166  ss->bm_log = BM_log_create(ss->bm);
167 
168  /* Update dependency graph, so modifiers that depend on dyntopo being enabled
169  * are re-evaluated and the PBVH is re-created. */
172 }
173 
174 /* Free the sculpt BMesh and BMLog
175  *
176  * If 'unode' is given, the BMesh's data is copied out to the unode
177  * before the BMesh is deleted so that it can be restored from. */
179  Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, SculptUndoNode *unode)
180 {
181  SculptSession *ss = ob->sculpt;
182  Mesh *me = ob->data;
183 
184  SCULPT_pbvh_clear(ob);
185 
186  if (unode) {
187  /* Free all existing custom data. */
188  CustomData_free(&me->vdata, me->totvert);
189  CustomData_free(&me->edata, me->totedge);
190  CustomData_free(&me->fdata, me->totface);
191  CustomData_free(&me->ldata, me->totloop);
192  CustomData_free(&me->pdata, me->totpoly);
193 
194  /* Copy over stored custom data. */
195  SculptUndoNodeGeometry *geometry = &unode->geometry_bmesh_enter;
196  me->totvert = geometry->totvert;
197  me->totloop = geometry->totloop;
198  me->totpoly = geometry->totpoly;
199  me->totedge = geometry->totedge;
200  me->totface = 0;
202  &geometry->vdata, &me->vdata, CD_MASK_MESH.vmask, CD_DUPLICATE, geometry->totvert);
204  &geometry->edata, &me->edata, CD_MASK_MESH.emask, CD_DUPLICATE, geometry->totedge);
206  &geometry->ldata, &me->ldata, CD_MASK_MESH.lmask, CD_DUPLICATE, geometry->totloop);
208  &geometry->pdata, &me->pdata, CD_MASK_MESH.pmask, CD_DUPLICATE, geometry->totpoly);
209 
211  }
212  else {
213  BKE_sculptsession_bm_to_me(ob, true);
214 
215  /* Reset Face Sets as they are no longer valid. */
218  }
220  for (int i = 0; i < me->totpoly; i++) {
221  ss->face_sets[i] = 1;
222  }
223  me->face_sets_color_default = 1;
224 
225  /* Sync the visibility to vertices manually as the pmap is still not initialized. */
226  for (int i = 0; i < me->totvert; i++) {
227  me->mvert[i].flag &= ~ME_HIDE;
228  }
229  }
230 
231  /* Clear data. */
233 
234  /* Typically valid but with global-undo they can be NULL, see: T36234. */
235  if (ss->bm) {
236  BM_mesh_free(ss->bm);
237  ss->bm = NULL;
238  }
239  if (ss->bm_log) {
240  BM_log_free(ss->bm_log);
241  ss->bm_log = NULL;
242  }
243 
246 
247  /* Update dependency graph, so modifiers that depend on dyntopo being enabled
248  * are re-evaluated and the PBVH is re-created. */
251 }
252 
254 {
255  Main *bmain = CTX_data_main(C);
260 }
261 
264  Scene *scene,
265  Object *ob)
266 {
267  SculptSession *ss = ob->sculpt;
268  if (ss->bm != NULL) {
269  /* May be false in background mode. */
270  const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true;
271  if (use_undo) {
272  SCULPT_undo_push_begin(ob, "Dynamic topology disable");
274  }
276  if (use_undo) {
278  }
279  }
280 }
281 
284  Scene *scene,
285  Object *ob)
286 {
287  SculptSession *ss = ob->sculpt;
288  if (ss->bm == NULL) {
289  /* May be false in background mode. */
290  const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true;
291  if (use_undo) {
292  SCULPT_undo_push_begin(ob, "Dynamic topology enable");
293  }
295  if (use_undo) {
298  }
299  }
300 }
301 
303 {
304  Main *bmain = CTX_data_main(C);
308  SculptSession *ss = ob->sculpt;
309 
310  WM_cursor_wait(true);
311 
312  if (ss->bm) {
314  }
315  else {
317  }
318 
319  WM_cursor_wait(false);
321 
322  return OPERATOR_FINISHED;
323 }
324 
326 {
327  uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Warning!"), ICON_ERROR);
328  uiLayout *layout = UI_popup_menu_layout(pup);
329 
331  const char *msg_error = TIP_("Vertex Data Detected!");
332  const char *msg = TIP_("Dyntopo will not preserve vertex colors, UVs, or other customdata");
333  uiItemL(layout, msg_error, ICON_INFO);
334  uiItemL(layout, msg, ICON_NONE);
335  uiItemS(layout);
336  }
337 
338  if (flag & DYNTOPO_WARN_MODIFIER) {
339  const char *msg_error = TIP_("Generative Modifiers Detected!");
340  const char *msg = TIP_(
341  "Keeping the modifiers will increase polycount when returning to object mode");
342 
343  uiItemL(layout, msg_error, ICON_INFO);
344  uiItemL(layout, msg, ICON_NONE);
345  uiItemS(layout);
346  }
347 
348  uiItemFullO_ptr(layout, ot, IFACE_("OK"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, NULL);
349 
350  UI_popup_menu_end(C, pup);
351 
352  return OPERATOR_INTERFACE;
353 }
354 
356 {
357  Mesh *me = ob->data;
358  SculptSession *ss = ob->sculpt;
359 
360  enum eDynTopoWarnFlag flag = 0;
361 
362  BLI_assert(ss->bm == NULL);
363  UNUSED_VARS_NDEBUG(ss);
364 
365  for (int i = 0; i < CD_NUMTYPES; i++) {
367  if (CustomData_has_layer(&me->vdata, i)) {
368  flag |= DYNTOPO_WARN_VDATA;
369  }
370  if (CustomData_has_layer(&me->edata, i)) {
371  flag |= DYNTOPO_WARN_EDATA;
372  }
373  if (CustomData_has_layer(&me->ldata, i)) {
374  flag |= DYNTOPO_WARN_LDATA;
375  }
376  }
377  }
378 
379  {
380  VirtualModifierData virtualModifierData;
381  ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
382 
383  /* Exception for shape keys because we can edit those. */
384  for (; md; md = md->next) {
385  const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
387  continue;
388  }
389 
390  if (mti->type == eModifierTypeType_Constructive) {
391  flag |= DYNTOPO_WARN_MODIFIER;
392  break;
393  }
394  }
395  }
396 
397  return flag;
398 }
399 
401  wmOperator *op,
402  const wmEvent *UNUSED(event))
403 {
405  SculptSession *ss = ob->sculpt;
406 
407  if (!ss->bm) {
410 
411  if (flag) {
412  /* The mesh has customdata that will be lost, let the user confirm this is OK. */
413  return dyntopo_warning_popup(C, op->type, flag);
414  }
415  }
416 
418 }
419 
421 {
422  /* Identifiers. */
423  ot->name = "Dynamic Topology Toggle";
424  ot->idname = "SCULPT_OT_dynamic_topology_toggle";
425  ot->description = "Dynamic topology alters the mesh topology while sculpting";
426 
427  /* API callbacks. */
431 
433 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
void CustomData_free(struct CustomData *data, int totelem)
Definition: customdata.cc:2373
@ CD_CALLOC
@ CD_DUPLICATE
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
bool CustomData_has_layer(const struct CustomData *data, int type)
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name)
int CustomData_get_layer_index(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
int CustomData_get_n_offset(const struct CustomData *data, int type, int n)
const CustomData_MeshMasks CD_MASK_MESH
Definition: customdata.cc:2065
void BKE_mesh_update_customdata_pointers(struct Mesh *me, bool do_ensure_tess_cd)
Definition: mesh.cc:874
void BKE_mesh_mselect_clear(struct Mesh *me)
Definition: mesh.cc:1695
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
struct ModifierData * BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, struct VirtualModifierData *data)
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:47
General operations, lookup, etc. for blender objects.
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.cc:1774
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder)
Definition: paint.c:1401
void BKE_particlesystem_reset_all(struct Object *object)
A BVH for high poly meshes.
void BKE_pbvh_free(PBVH *pbvh)
Definition: pbvh.c:663
#define PTCACHE_RESET_OUTDATED
int BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode)
Definition: pointcache.c:2930
void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.cc:2648
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define ELEM(...)
#define TIP_(msgid)
#define IFACE_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ CD_FLAG_TEMPORARY
@ CD_PAINT_MASK
@ CD_MFACE
@ CD_ORIGINDEX
@ CD_NUMTYPES
@ CD_PROP_INT32
@ CD_SCULPT_FACE_SETS
@ CD_MEDGE
@ CD_MVERT
@ ME_SCULPT_DYNAMIC_TOPOLOGY
@ ME_HIDE
@ eModifierMode_Realtime
@ MOD_TRIANGULATE_NGON_EARCLIP
@ MOD_TRIANGULATE_QUAD_BEAUTY
@ SCULPT_DYNTOPO_SMOOTH_SHADING
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
struct UndoStack * ED_undo_stack_get(void)
Definition: ed_undo.c:473
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition: RandGen.cpp:25
void uiItemL(uiLayout *layout, const char *name, int icon)
struct uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void uiItemS(uiLayout *layout)
void uiItemFullO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, struct IDProperty *properties, wmOperatorCallContext context, int flag, struct PointerRNA *r_opptr)
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL()
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_SCENE
Definition: WM_types.h:328
#define ND_TOOLSETTINGS
Definition: WM_types.h:397
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:839
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
Definition: bmesh_interp.c:857
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMLog * BM_log_create(BMesh *bm)
Definition: bmesh_log.c:461
void BM_log_free(BMLog *log)
Definition: bmesh_log.c:539
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
Definition: bmesh_mesh.cc:125
#define BMALLOC_TEMPLATE_FROM_ME(...)
Definition: bmesh_mesh.h:197
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
void BM_mesh_normals_update(BMesh *bm)
void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const int min_vertices, const bool tag_only, BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_facemap_double_out)
Scene scene
const Depsgraph * depsgraph
#define G(x, y, z)
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:3957
static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
static void SCULPT_dynamic_topology_disable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, SculptUndoNode *unode)
enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob)
void SCULPT_pbvh_clear(Object *ob)
void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot)
static int dyntopo_warning_popup(bContext *C, wmOperatorType *ot, enum eDynTopoWarnFlag flag)
void sculpt_dynamic_topology_disable_with_undo(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
void SCULPT_dynamic_topology_disable(bContext *C, SculptUndoNode *unode)
void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
void SCULPT_dyntopo_node_layers_add(SculptSession *ss)
void SCULPT_dynamic_topology_triangulate(BMesh *bm)
static void sculpt_dynamic_topology_enable_with_undo(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
void SCULPT_undo_push_begin(struct Object *ob, const char *name)
Definition: sculpt_undo.c:1545
void SCULPT_undo_push_end(struct Object *ob)
Definition: sculpt_undo.c:1575
eDynTopoWarnFlag
@ DYNTOPO_WARN_LDATA
@ DYNTOPO_WARN_MODIFIER
@ DYNTOPO_WARN_VDATA
@ DYNTOPO_WARN_EDATA
SculptUndoNode * SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt_undo.c:1419
@ SCULPT_UNDO_DYNTOPO_END
@ SCULPT_UNDO_DYNTOPO_BEGIN
CustomData vdata
Definition: bmesh_class.h:337
int totloop
Definition: bmesh_class.h:297
CustomData pdata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
CustomDataLayer * layers
Definition: BKE_main.h:121
CustomData vdata
struct MVert * mvert
uint16_t flag
int totedge
int totvert
int totface
CustomData pdata
CustomData fdata
int totpoly
int face_sets_color_default
CustomData edata
int totloop
CustomData ldata
struct ModifierData * next
ModifierTypeType type
Definition: BKE_modifier.h:160
struct SculptSession * sculpt
void * data
struct ToolSettings * toolsettings
int cd_face_node_offset
Definition: BKE_paint.h:541
bool bm_smooth_shading
Definition: BKE_paint.h:542
int cd_vert_node_offset
Definition: BKE_paint.h:540
int * face_sets
Definition: BKE_paint.h:536
int * pmap_mem
Definition: BKE_paint.h:517
struct BMesh * bm
Definition: BKE_paint.h:539
struct BMLog * bm_log
Definition: BKE_paint.h:544
struct MeshElemMap * pmap
Definition: BKE_paint.h:516
struct PBVH * pbvh
Definition: BKE_paint.h:550
SculptUndoNodeGeometry geometry_bmesh_enter
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct wmOperatorType * type
void WM_cursor_wait(bool val)
Definition: wm_cursors.c:209
void WM_main_add_notifier(unsigned int type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479