Blender  V2.93
MOD_decimate.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 by the Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BLI_utildefines.h"
25 
26 #include "BLI_math.h"
27 
28 #include "BLT_translation.h"
29 
30 #include "DNA_defaults.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_screen_types.h"
35 
36 #include "MEM_guardedalloc.h"
37 
38 #include "BKE_context.h"
39 #include "BKE_deform.h"
40 #include "BKE_mesh.h"
41 #include "BKE_screen.h"
42 
43 #include "UI_interface.h"
44 #include "UI_resources.h"
45 
46 #include "RNA_access.h"
47 
48 #include "DEG_depsgraph_query.h"
49 
50 #include "bmesh.h"
51 #include "bmesh_tools.h"
52 
53 // #define USE_TIMEIT
54 
55 #ifdef USE_TIMEIT
56 # include "PIL_time.h"
57 # include "PIL_time_utildefines.h"
58 #endif
59 
60 #include "MOD_ui_common.h"
61 #include "MOD_util.h"
62 
63 static void initData(ModifierData *md)
64 {
66 
68 
70 }
71 
72 static void requiredDataMask(Object *UNUSED(ob),
73  ModifierData *md,
74  CustomData_MeshMasks *r_cddata_masks)
75 {
77 
78  /* ask for vertexgroups if we need them */
79  if (dmd->defgrp_name[0] != '\0' && (dmd->defgrp_factor > 0.0f)) {
80  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
81  }
82 }
83 
85  const ModifierEvalContext *ctx)
86 {
87  Object *ob_orig = DEG_get_original_object(ctx->object);
89 }
90 
91 static void updateFaceCount(const ModifierEvalContext *ctx,
93  int face_count)
94 {
95  dmd->face_count = face_count;
96 
97  if (DEG_is_active(ctx->depsgraph)) {
98  /* update for display only */
99  DecimateModifierData *dmd_orig = getOriginalModifierData(dmd, ctx);
100  dmd_orig->face_count = face_count;
101  }
102 }
103 
104 static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
105 {
107  Mesh *mesh = meshData, *result = NULL;
108  BMesh *bm;
109  bool calc_face_normal;
110  float *vweights = NULL;
111 
112 #ifdef USE_TIMEIT
113  TIMEIT_START(decim);
114 #endif
115 
116  /* Set up front so we don't show invalid info in the UI. */
117  updateFaceCount(ctx, dmd, mesh->totpoly);
118 
119  switch (dmd->mode) {
121  if (dmd->percent == 1.0f) {
122  return mesh;
123  }
124  calc_face_normal = true;
125  break;
127  if (dmd->iter == 0) {
128  return mesh;
129  }
130  calc_face_normal = false;
131  break;
133  if (dmd->angle == 0.0f) {
134  return mesh;
135  }
136  calc_face_normal = true;
137  break;
138  default:
139  return mesh;
140  }
141 
142  if (dmd->face_count <= 3) {
143  BKE_modifier_set_error(ctx->object, md, "Modifier requires more than 3 input faces");
144  return mesh;
145  }
146 
147  if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) {
148  if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) {
149  MDeformVert *dvert;
150  int defgrp_index;
151 
152  MOD_get_vgroup(ctx->object, mesh, dmd->defgrp_name, &dvert, &defgrp_index);
153 
154  if (dvert) {
155  const uint vert_tot = mesh->totvert;
156  uint i;
157 
158  vweights = MEM_malloc_arrayN(vert_tot, sizeof(float), __func__);
159 
160  if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) {
161  for (i = 0; i < vert_tot; i++) {
162  vweights[i] = 1.0f - BKE_defvert_find_weight(&dvert[i], defgrp_index);
163  }
164  }
165  else {
166  for (i = 0; i < vert_tot; i++) {
167  vweights[i] = BKE_defvert_find_weight(&dvert[i], defgrp_index);
168  }
169  }
170  }
171  }
172  }
173 
175  &(struct BMeshCreateParams){0},
176  &(struct BMeshFromMeshParams){
177  .calc_face_normal = calc_face_normal,
178  .cd_mask_extra = {.vmask = CD_MASK_ORIGINDEX,
179  .emask = CD_MASK_ORIGINDEX,
180  .pmask = CD_MASK_ORIGINDEX},
181  });
182 
183  switch (dmd->mode) {
185  const bool do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
186  const int symmetry_axis = (dmd->flag & MOD_DECIM_FLAG_SYMMETRY) ? dmd->symmetry_axis : -1;
187  const float symmetry_eps = 0.00002f;
189  dmd->percent,
190  vweights,
191  dmd->defgrp_factor,
192  do_triangulate,
193  symmetry_axis,
194  symmetry_eps);
195  break;
196  }
199  break;
200  }
202  const bool do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
203  BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit);
204  break;
205  }
206  }
207 
208  if (vweights) {
209  MEM_freeN(vweights);
210  }
211 
212  updateFaceCount(ctx, dmd, bm->totface);
213 
215  /* make sure we never alloc'd these */
217  BLI_assert(bm->vtable == NULL && bm->etable == NULL && bm->ftable == NULL);
218 
219  BM_mesh_free(bm);
220 
221 #ifdef USE_TIMEIT
222  TIMEIT_END(decim);
223 #endif
224 
225  result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
226 
227  return result;
228 }
229 
230 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
231 {
232  uiLayout *sub, *row;
233  uiLayout *layout = panel->layout;
234 
235  PointerRNA ob_ptr;
237 
238  int decimate_type = RNA_enum_get(ptr, "decimate_type");
239  char count_info[32];
240  snprintf(count_info, 32, "%s: %d", IFACE_("Face Count"), RNA_int_get(ptr, "face_count"));
241 
242  uiItemR(layout, ptr, "decimate_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
243 
244  uiLayoutSetPropSep(layout, true);
245 
246  if (decimate_type == MOD_DECIM_MODE_COLLAPSE) {
247  uiItemR(layout, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
248 
249  row = uiLayoutRowWithHeading(layout, true, IFACE_("Symmetry"));
250  uiLayoutSetPropDecorate(row, false);
251  sub = uiLayoutRow(row, true);
252  uiItemR(sub, ptr, "use_symmetry", 0, "", ICON_NONE);
253  sub = uiLayoutRow(sub, true);
254  uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_symmetry"));
255  uiItemR(sub, ptr, "symmetry_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
256  uiItemDecoratorR(row, ptr, "symmetry_axis", 0);
257 
258  uiItemR(layout, ptr, "use_collapse_triangulate", 0, NULL, ICON_NONE);
259 
260  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
261  sub = uiLayoutRow(layout, true);
262  bool has_vertex_group = RNA_string_length(ptr, "vertex_group") != 0;
263  uiLayoutSetActive(sub, has_vertex_group);
264  uiItemR(sub, ptr, "vertex_group_factor", 0, NULL, ICON_NONE);
265  }
266  else if (decimate_type == MOD_DECIM_MODE_UNSUBDIV) {
267  uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
268  }
269  else { /* decimate_type == MOD_DECIM_MODE_DISSOLVE. */
270  uiItemR(layout, ptr, "angle_limit", 0, NULL, ICON_NONE);
271  uiLayout *col = uiLayoutColumn(layout, false);
272  uiItemR(col, ptr, "delimit", 0, NULL, ICON_NONE);
273  uiItemR(layout, ptr, "use_dissolve_boundaries", 0, NULL, ICON_NONE);
274  }
275  uiItemL(layout, count_info, ICON_NONE);
276 
277  modifier_panel_end(layout, ptr);
278 }
279 
280 static void panelRegister(ARegionType *region_type)
281 {
283 }
284 
286  /* name */ "Decimate",
287  /* structName */ "DecimateModifierData",
288  /* structSize */ sizeof(DecimateModifierData),
289  /* srna */ &RNA_DecimateModifier,
292  /* icon */ ICON_MOD_DECIM,
293 
294  /* copyData */ BKE_modifier_copydata_generic,
295 
296  /* deformVerts */ NULL,
297  /* deformMatrices */ NULL,
298  /* deformVertsEM */ NULL,
299  /* deformMatricesEM */ NULL,
300  /* modifyMesh */ modifyMesh,
301  /* modifyHair */ NULL,
302  /* modifyGeometrySet */ NULL,
303  /* modifyVolume */ NULL,
304 
305  /* initData */ initData,
306  /* requiredDataMask */ requiredDataMask,
307  /* freeData */ NULL,
308  /* isDisabled */ NULL,
309  /* updateDepsgraph */ NULL,
310  /* dependsOnTime */ NULL,
311  /* dependsOnNormals */ NULL,
312  /* foreachIDLink */ NULL,
313  /* foreachTexLink */ NULL,
314  /* freeRuntimeData */ NULL,
315  /* panelRegister */ panelRegister,
316  /* blendWrite */ NULL,
317  /* blendRead */ NULL,
318 };
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
Definition: deform.c:632
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:81
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_Nonconstructive
Definition: BKE_modifier.h:63
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:58
unsigned int uint
Definition: BLI_sys_types.h:83
#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:69
#define IFACE_(msgid)
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:331
struct Object * DEG_get_original_object(struct Object *object)
#define CD_MASK_NORMAL
#define CD_MASK_ORIGINDEX
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
@ 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:285
static void updateFaceCount(const ModifierEvalContext *ctx, DecimateModifierData *dmd, int face_count)
Definition: MOD_decimate.c:91
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
Definition: MOD_decimate.c:104
static DecimateModifierData * getOriginalModifierData(const DecimateModifierData *dmd, const ModifierEvalContext *ctx)
Definition: MOD_decimate.c:84
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_decimate.c:230
static void initData(ModifierData *md)
Definition: MOD_decimate.c:63
static void panelRegister(ARegionType *region_type)
Definition: MOD_decimate.c:280
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
Definition: MOD_decimate.c:72
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
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:254
Platform independent time functions.
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define TIMEIT_END(var)
StructRNA RNA_DecimateModifier
#define C
Definition: RandGen.cpp:39
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
void uiLayoutSetActive(uiLayout *layout, bool active)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
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)
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_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, const BMO_Delimit delimit)
void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, float vweight_factor, const bool do_triangulate, const int symmetry_axis, const float symmetry_eps)
BM_mesh_decimate.
void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.c:307
uint col
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
int RNA_string_length(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6539
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
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:153
struct Object * object
Definition: BKE_modifier.h:154
struct uiLayout * layout
PointerRNA * ptr
Definition: wm_files.c:3157