Blender  V3.3
MOD_decimate.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 #include "BLI_utildefines.h"
9 
10 #include "BLI_math.h"
11 
12 #include "BLT_translation.h"
13 
14 #include "DNA_defaults.h"
15 #include "DNA_mesh_types.h"
16 #include "DNA_meshdata_types.h"
17 #include "DNA_object_types.h"
18 #include "DNA_screen_types.h"
19 
20 #include "MEM_guardedalloc.h"
21 
22 #include "BKE_context.h"
23 #include "BKE_deform.h"
24 #include "BKE_mesh.h"
25 #include "BKE_screen.h"
26 
27 #include "UI_interface.h"
28 #include "UI_resources.h"
29 
30 #include "RNA_access.h"
31 #include "RNA_prototypes.h"
32 
33 #include "DEG_depsgraph_query.h"
34 
35 #include "bmesh.h"
36 #include "bmesh_tools.h"
37 
38 // #define USE_TIMEIT
39 
40 #ifdef USE_TIMEIT
41 # include "PIL_time.h"
42 # include "PIL_time_utildefines.h"
43 #endif
44 
45 #include "MOD_ui_common.h"
46 #include "MOD_util.h"
47 
48 static void initData(ModifierData *md)
49 {
51 
53 
55 }
56 
57 static void requiredDataMask(Object *UNUSED(ob),
58  ModifierData *md,
59  CustomData_MeshMasks *r_cddata_masks)
60 {
62 
63  /* ask for vertexgroups if we need them */
64  if (dmd->defgrp_name[0] != '\0' && (dmd->defgrp_factor > 0.0f)) {
65  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
66  }
67 }
68 
70  const ModifierEvalContext *ctx)
71 {
72  Object *ob_orig = DEG_get_original_object(ctx->object);
74 }
75 
76 static void updateFaceCount(const ModifierEvalContext *ctx,
78  int face_count)
79 {
80  dmd->face_count = face_count;
81 
82  if (DEG_is_active(ctx->depsgraph)) {
83  /* update for display only */
84  DecimateModifierData *dmd_orig = getOriginalModifierData(dmd, ctx);
85  dmd_orig->face_count = face_count;
86  }
87 }
88 
89 static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
90 {
92  Mesh *mesh = meshData, *result = NULL;
93  BMesh *bm;
94  bool calc_vert_normal;
95  bool calc_face_normal;
96  float *vweights = NULL;
97 
98 #ifdef USE_TIMEIT
99  TIMEIT_START(decim);
100 #endif
101 
102  /* Set up front so we don't show invalid info in the UI. */
103  updateFaceCount(ctx, dmd, mesh->totpoly);
104 
105  switch (dmd->mode) {
107  if (dmd->percent == 1.0f) {
108  return mesh;
109  }
110  calc_face_normal = true;
111  calc_vert_normal = true;
112  break;
114  if (dmd->iter == 0) {
115  return mesh;
116  }
117  calc_face_normal = false;
118  calc_vert_normal = false;
119  break;
121  if (dmd->angle == 0.0f) {
122  return mesh;
123  }
124  calc_face_normal = true;
125  calc_vert_normal = false;
126  break;
127  default:
128  return mesh;
129  }
130 
131  if (dmd->face_count <= 3) {
132  BKE_modifier_set_error(ctx->object, md, "Modifier requires more than 3 input faces");
133  return mesh;
134  }
135 
136  if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) {
137  if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) {
138  MDeformVert *dvert;
139  int defgrp_index;
140 
141  MOD_get_vgroup(ctx->object, mesh, dmd->defgrp_name, &dvert, &defgrp_index);
142 
143  if (dvert) {
144  const uint vert_tot = mesh->totvert;
145  uint i;
146 
147  vweights = MEM_malloc_arrayN(vert_tot, sizeof(float), __func__);
148 
149  if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) {
150  for (i = 0; i < vert_tot; i++) {
151  vweights[i] = 1.0f - BKE_defvert_find_weight(&dvert[i], defgrp_index);
152  }
153  }
154  else {
155  for (i = 0; i < vert_tot; i++) {
156  vweights[i] = BKE_defvert_find_weight(&dvert[i], defgrp_index);
157  }
158  }
159  }
160  }
161  }
162 
164  &(struct BMeshCreateParams){0},
165  &(struct BMeshFromMeshParams){
166  .calc_face_normal = calc_face_normal,
167  .calc_vert_normal = calc_vert_normal,
168  .cd_mask_extra = {.vmask = CD_MASK_ORIGINDEX,
169  .emask = CD_MASK_ORIGINDEX,
170  .pmask = CD_MASK_ORIGINDEX},
171  });
172 
173  switch (dmd->mode) {
175  const bool do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
176  const int symmetry_axis = (dmd->flag & MOD_DECIM_FLAG_SYMMETRY) ? dmd->symmetry_axis : -1;
177  const float symmetry_eps = 0.00002f;
179  dmd->percent,
180  vweights,
181  dmd->defgrp_factor,
182  do_triangulate,
183  symmetry_axis,
184  symmetry_eps);
185  break;
186  }
189  break;
190  }
192  const bool do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
193  BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit);
194  break;
195  }
196  }
197 
198  if (vweights) {
199  MEM_freeN(vweights);
200  }
201 
202  updateFaceCount(ctx, dmd, bm->totface);
203 
205  /* make sure we never alloc'd these */
207  BLI_assert(bm->vtable == NULL && bm->etable == NULL && bm->ftable == NULL);
208 
209  BM_mesh_free(bm);
210 
211 #ifdef USE_TIMEIT
212  TIMEIT_END(decim);
213 #endif
214 
215  return result;
216 }
217 
218 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
219 {
220  uiLayout *sub, *row;
221  uiLayout *layout = panel->layout;
222 
223  PointerRNA ob_ptr;
225 
226  int decimate_type = RNA_enum_get(ptr, "decimate_type");
227  char count_info[64];
228  snprintf(count_info, 32, TIP_("Face Count: %d"), RNA_int_get(ptr, "face_count"));
229 
230  uiItemR(layout, ptr, "decimate_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
231 
232  uiLayoutSetPropSep(layout, true);
233 
234  if (decimate_type == MOD_DECIM_MODE_COLLAPSE) {
235  uiItemR(layout, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
236 
237  row = uiLayoutRowWithHeading(layout, true, IFACE_("Symmetry"));
238  uiLayoutSetPropDecorate(row, false);
239  sub = uiLayoutRow(row, true);
240  uiItemR(sub, ptr, "use_symmetry", 0, "", ICON_NONE);
241  sub = uiLayoutRow(sub, true);
242  uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_symmetry"));
243  uiItemR(sub, ptr, "symmetry_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
244  uiItemDecoratorR(row, ptr, "symmetry_axis", 0);
245 
246  uiItemR(layout, ptr, "use_collapse_triangulate", 0, NULL, ICON_NONE);
247 
248  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
249  sub = uiLayoutRow(layout, true);
250  bool has_vertex_group = RNA_string_length(ptr, "vertex_group") != 0;
251  uiLayoutSetActive(sub, has_vertex_group);
252  uiItemR(sub, ptr, "vertex_group_factor", 0, NULL, ICON_NONE);
253  }
254  else if (decimate_type == MOD_DECIM_MODE_UNSUBDIV) {
255  uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
256  }
257  else { /* decimate_type == MOD_DECIM_MODE_DISSOLVE. */
258  uiItemR(layout, ptr, "angle_limit", 0, NULL, ICON_NONE);
259  uiLayout *col = uiLayoutColumn(layout, false);
260  uiItemR(col, ptr, "delimit", 0, NULL, ICON_NONE);
261  uiItemR(layout, ptr, "use_dissolve_boundaries", 0, NULL, ICON_NONE);
262  }
263  uiItemL(layout, count_info, ICON_NONE);
264 
265  modifier_panel_end(layout, ptr);
266 }
267 
268 static void panelRegister(ARegionType *region_type)
269 {
271 }
272 
274  /* name */ N_("Decimate"),
275  /* structName */ "DecimateModifierData",
276  /* structSize */ sizeof(DecimateModifierData),
277  /* srna */ &RNA_DecimateModifier,
280  /* icon */ ICON_MOD_DECIM,
281 
282  /* copyData */ BKE_modifier_copydata_generic,
283 
284  /* deformVerts */ NULL,
285  /* deformMatrices */ NULL,
286  /* deformVertsEM */ NULL,
287  /* deformMatricesEM */ NULL,
288  /* modifyMesh */ modifyMesh,
289  /* modifyGeometrySet */ NULL,
290 
291  /* initData */ initData,
292  /* requiredDataMask */ requiredDataMask,
293  /* freeData */ NULL,
294  /* isDisabled */ NULL,
295  /* updateDepsgraph */ NULL,
296  /* dependsOnTime */ NULL,
297  /* dependsOnNormals */ NULL,
298  /* foreachIDLink */ NULL,
299  /* foreachTexLink */ NULL,
300  /* freeRuntimeData */ NULL,
301  /* panelRegister */ panelRegister,
302  /* blendWrite */ NULL,
303  /* blendRead */ NULL,
304 };
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
struct BMesh * BKE_mesh_to_bmesh_ex(const struct Mesh *me, const struct BMeshCreateParams *create_params, const struct BMeshFromMeshParams *convert_params)
struct Mesh * BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, const struct CustomData_MeshMasks *cd_mask_extra, const struct Mesh *me_settings)
@ eModifierTypeFlag_AcceptsCVs
Definition: BKE_modifier.h:67
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_Nonconstructive
Definition: BKE_modifier.h:49
struct ModifierData * BKE_modifiers_findby_name(const struct Object *ob, const char *name)
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:46
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define snprintf
Definition: BLI_winstuff.h:53
#define TIP_(msgid)
#define IFACE_(msgid)
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:312
struct Object * DEG_get_original_object(struct Object *object)
#define CD_MASK_ORIGINDEX
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ MOD_DECIM_FLAG_INVERT_VGROUP
@ MOD_DECIM_FLAG_SYMMETRY
@ MOD_DECIM_FLAG_TRIANGULATE
@ MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS
@ eModifierType_Decimate
struct DecimateModifierData DecimateModifierData
@ MOD_DECIM_MODE_UNSUBDIV
@ MOD_DECIM_MODE_COLLAPSE
@ MOD_DECIM_MODE_DISSOLVE
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
ModifierTypeInfo modifierType_Decimate
Definition: MOD_decimate.c:273
static void updateFaceCount(const ModifierEvalContext *ctx, DecimateModifierData *dmd, int face_count)
Definition: MOD_decimate.c:76
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
Definition: MOD_decimate.c:89
static DecimateModifierData * getOriginalModifierData(const DecimateModifierData *dmd, const ModifierEvalContext *ctx)
Definition: MOD_decimate.c:69
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_decimate.c:218
static void initData(ModifierData *md)
Definition: MOD_decimate.c:48
static void panelRegister(ARegionType *region_type)
Definition: MOD_decimate.c:268
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
Definition: MOD_decimate.c:57
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Definition: MOD_util.c:235
Platform independent time functions.
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define TIMEIT_END(var)
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemL(uiLayout *layout, const char *name, int icon)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemDecoratorR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int index)
void BM_mesh_decimate_collapse(BMesh *bm, float factor, float *vweights, float vweight_factor, bool do_triangulate, int symmetry_axis, float symmetry_eps)
BM_mesh_decimate.
void BM_mesh_decimate_unsubdivide(BMesh *bm, int iterations)
void BM_mesh_decimate_dissolve(BMesh *bm, float angle_limit, bool do_dissolve_boundaries, const BMO_Delimit delimit)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
uint col
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
int RNA_string_length(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5144
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
BMEdge ** etable
Definition: bmesh_class.h:322
struct BLI_mempool * vtoolflagpool
Definition: bmesh_class.h:331
struct BLI_mempool * etoolflagpool
Definition: bmesh_class.h:331
BMVert ** vtable
Definition: bmesh_class.h:321
struct BLI_mempool * ftoolflagpool
Definition: bmesh_class.h:331
BMFace ** ftable
Definition: bmesh_class.h:323
int totface
Definition: bmesh_class.h:297
int totvert
int totpoly
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct Object * object
Definition: BKE_modifier.h:141
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480