Blender V4.3
MOD_decimate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_string.h"
10#include "BLI_utildefines.h"
11
12#include "BLT_translation.hh"
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_deform.hh"
23#include "BKE_mesh.hh"
24
25#include "UI_interface.hh"
26#include "UI_resources.hh"
27
28#include "RNA_access.hh"
29#include "RNA_prototypes.hh"
30
32
33#include "GEO_randomize.hh"
34
35#include "bmesh.hh"
36#include "bmesh_tools.hh"
37
38// #define USE_TIMEIT
39
40#ifdef USE_TIMEIT
41# include "BLI_time.h"
42# include "BLI_time_utildefines.h"
43#endif
44
45#include "MOD_ui_common.hh"
46#include "MOD_util.hh"
47
56
57static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
58{
60
61 /* Ask for vertex-groups if we need them. */
62 if (dmd->defgrp_name[0] != '\0' && (dmd->defgrp_factor > 0.0f)) {
63 r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
64 }
65}
66
73
74static void updateFaceCount(const ModifierEvalContext *ctx,
76 int face_count)
77{
78 dmd->face_count = face_count;
79
80 if (DEG_is_active(ctx->depsgraph)) {
81 /* update for display only */
83 dmd_orig->face_count = face_count;
84 }
85}
86
87static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
88{
90 Mesh *mesh = meshData, *result = nullptr;
91 BMesh *bm;
92 bool calc_vert_normal;
93 bool calc_face_normal;
94 float *vweights = nullptr;
95
96#ifdef USE_TIMEIT
97 TIMEIT_START(decim);
98#endif
99
100 /* Set up front so we don't show invalid info in the UI. */
101 updateFaceCount(ctx, dmd, mesh->faces_num);
102
103 switch (dmd->mode) {
105 if (dmd->percent == 1.0f) {
106 return mesh;
107 }
108 calc_face_normal = true;
109 calc_vert_normal = true;
110 break;
112 if (dmd->iter == 0) {
113 return mesh;
114 }
115 calc_face_normal = false;
116 calc_vert_normal = false;
117 break;
119 if (dmd->angle == 0.0f) {
120 return mesh;
121 }
122 calc_face_normal = true;
123 calc_vert_normal = false;
124 break;
125 default:
126 return mesh;
127 }
128
129 if (dmd->face_count <= 3) {
130 BKE_modifier_set_error(ctx->object, md, "Modifier requires more than 3 input faces");
131 return mesh;
132 }
133
134 if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) {
135 if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) {
136 const MDeformVert *dvert;
137 int defgrp_index;
138
139 MOD_get_vgroup(ctx->object, mesh, dmd->defgrp_name, &dvert, &defgrp_index);
140
141 if (dvert) {
142 const uint vert_tot = mesh->verts_num;
143 uint i;
144
145 vweights = static_cast<float *>(MEM_malloc_arrayN(vert_tot, sizeof(float), __func__));
146
148 for (i = 0; i < vert_tot; i++) {
149 vweights[i] = 1.0f - BKE_defvert_find_weight(&dvert[i], defgrp_index);
150 }
151 }
152 else {
153 for (i = 0; i < vert_tot; i++) {
154 vweights[i] = BKE_defvert_find_weight(&dvert[i], defgrp_index);
155 }
156 }
157 }
158 }
159 }
160
161 BMeshCreateParams create_params{};
162 BMeshFromMeshParams convert_params{};
163 convert_params.calc_face_normal = calc_face_normal;
164 convert_params.calc_vert_normal = calc_vert_normal;
165 convert_params.cd_mask_extra.vmask = CD_MASK_ORIGINDEX;
166 convert_params.cd_mask_extra.emask = CD_MASK_ORIGINDEX;
167 convert_params.cd_mask_extra.pmask = CD_MASK_ORIGINDEX;
168
169 bm = BKE_mesh_to_bmesh_ex(mesh, &create_params, &convert_params);
170
171 switch (dmd->mode) {
173 const bool do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
174 const int symmetry_axis = (dmd->flag & MOD_DECIM_FLAG_SYMMETRY) ? dmd->symmetry_axis : -1;
175 const float symmetry_eps = 0.00002f;
177 dmd->percent,
178 vweights,
179 dmd->defgrp_factor,
180 do_triangulate,
181 symmetry_axis,
182 symmetry_eps);
183 break;
184 }
187 break;
188 }
190 const bool do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
191 BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit);
192 break;
193 }
194 }
195
196 if (vweights) {
197 MEM_freeN(vweights);
198 }
199
200 updateFaceCount(ctx, dmd, bm->totface);
201
202 /* Make sure we never allocated these. */
203 BLI_assert(bm->vtoolflagpool == nullptr && bm->etoolflagpool == nullptr &&
204 bm->ftoolflagpool == nullptr);
205
206 result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh);
207
209
211
212#ifdef USE_TIMEIT
213 TIMEIT_END(decim);
214#endif
215
216 return result;
217}
218
219static void panel_draw(const bContext * /*C*/, Panel *panel)
220{
221 uiLayout *sub, *row;
222 uiLayout *layout = panel->layout;
223
224 PointerRNA ob_ptr;
226
227 int decimate_type = RNA_enum_get(ptr, "decimate_type");
228 char count_info[64];
229 SNPRINTF(count_info, RPT_("Face Count: %d"), RNA_int_get(ptr, "face_count"));
230
231 uiItemR(layout, ptr, "decimate_type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
232
233 uiLayoutSetPropSep(layout, true);
234
235 if (decimate_type == MOD_DECIM_MODE_COLLAPSE) {
236 uiItemR(layout, ptr, "ratio", UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
237
238 row = uiLayoutRowWithHeading(layout, true, IFACE_("Symmetry"));
239 uiLayoutSetPropDecorate(row, false);
240 sub = uiLayoutRow(row, true);
241 uiItemR(sub, ptr, "use_symmetry", UI_ITEM_NONE, "", ICON_NONE);
242 sub = uiLayoutRow(sub, true);
243 uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_symmetry"));
244 uiItemR(sub, ptr, "symmetry_axis", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
245 uiItemDecoratorR(row, ptr, "symmetry_axis", 0);
246
247 uiItemR(layout, ptr, "use_collapse_triangulate", UI_ITEM_NONE, nullptr, ICON_NONE);
248
249 modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", nullptr);
250 sub = uiLayoutRow(layout, true);
251 bool has_vertex_group = RNA_string_length(ptr, "vertex_group") != 0;
252 uiLayoutSetActive(sub, has_vertex_group);
253 uiItemR(sub, ptr, "vertex_group_factor", UI_ITEM_NONE, nullptr, ICON_NONE);
254 }
255 else if (decimate_type == MOD_DECIM_MODE_UNSUBDIV) {
256 uiItemR(layout, ptr, "iterations", UI_ITEM_NONE, nullptr, ICON_NONE);
257 }
258 else { /* decimate_type == MOD_DECIM_MODE_DISSOLVE. */
259 uiItemR(layout, ptr, "angle_limit", UI_ITEM_NONE, nullptr, ICON_NONE);
260 uiLayout *col = uiLayoutColumn(layout, false);
261 uiItemR(col, ptr, "delimit", UI_ITEM_NONE, nullptr, ICON_NONE);
262 uiItemR(layout, ptr, "use_dissolve_boundaries", UI_ITEM_NONE, nullptr, ICON_NONE);
263 }
264 uiItemL(layout, count_info, ICON_NONE);
265
266 modifier_panel_end(layout, ptr);
267}
268
269static void panel_register(ARegionType *region_type)
270{
272}
273
275 /*idname*/ "Decimate",
276 /*name*/ N_("Decimate"),
277 /*struct_name*/ "DecimateModifierData",
278 /*struct_size*/ sizeof(DecimateModifierData),
279 /*srna*/ &RNA_DecimateModifier,
282 /*icon*/ ICON_MOD_DECIM,
283
284 /*copy_data*/ BKE_modifier_copydata_generic,
285
286 /*deform_verts*/ nullptr,
287 /*deform_matrices*/ nullptr,
288 /*deform_verts_EM*/ nullptr,
289 /*deform_matrices_EM*/ nullptr,
290 /*modify_mesh*/ modify_mesh,
291 /*modify_geometry_set*/ nullptr,
292
293 /*init_data*/ init_data,
294 /*required_data_mask*/ required_data_mask,
295 /*free_data*/ nullptr,
296 /*is_disabled*/ nullptr,
297 /*update_depsgraph*/ nullptr,
298 /*depends_on_time*/ nullptr,
299 /*depends_on_normals*/ nullptr,
300 /*foreach_ID_link*/ nullptr,
301 /*foreach_tex_link*/ nullptr,
302 /*free_runtime_data*/ nullptr,
303 /*panel_register*/ panel_register,
304 /*blend_write*/ nullptr,
305 /*blend_read*/ nullptr,
306 /*foreach_cache*/ nullptr,
307};
support for deformation groups and hooks.
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:770
Mesh * BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, const CustomData_MeshMasks *cd_mask_extra, const Mesh *me_settings)
BMesh * BKE_mesh_to_bmesh_ex(const Mesh *mesh, const BMeshCreateParams *create_params, const BMeshFromMeshParams *convert_params)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_AcceptsMesh
ModifierData * BKE_modifiers_findby_name(const Object *ob, const char *name)
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition BLI_assert.h:50
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
unsigned int uint
Platform independent time functions.
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define TIMEIT_END(var)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define RPT_(msgid)
#define IFACE_(msgid)
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:318
Object * DEG_get_original_object(Object *object)
#define CD_MASK_ORIGINDEX
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
@ MOD_DECIM_FLAG_INVERT_VGROUP
@ MOD_DECIM_FLAG_SYMMETRY
@ MOD_DECIM_FLAG_TRIANGULATE
@ MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS
@ eModifierType_Decimate
@ MOD_DECIM_MODE_UNSUBDIV
@ MOD_DECIM_MODE_COLLAPSE
@ MOD_DECIM_MODE_DISSOLVE
struct DecimateModifierData DecimateModifierData
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static DecimateModifierData * getOriginalModifierData(const DecimateModifierData *dmd, const ModifierEvalContext *ctx)
static void panel_register(ARegionType *region_type)
ModifierTypeInfo modifierType_Decimate
static void updateFaceCount(const ModifierEvalContext *ctx, DecimateModifierData *dmd, int face_count)
static void panel_draw(const bContext *, Panel *panel)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
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(const Object *ob, const Mesh *mesh, const char *name, const MDeformVert **dvert, int *defgrp_index)
Definition MOD_util.cc:159
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiItemL(uiLayout *layout, const char *name, int icon)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
#define UI_ITEM_NONE
void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
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.
uint col
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void debug_randomize_mesh_order(Mesh *mesh)
Definition randomize.cc:220
int RNA_int_get(PointerRNA *ptr, const char *name)
int RNA_string_length(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
struct BLI_mempool * vtoolflagpool
struct BLI_mempool * etoolflagpool
struct BLI_mempool * ftoolflagpool
int totface
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126