Blender  V3.3
MOD_smooth.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 "MEM_guardedalloc.h"
9 
10 #include "BLI_utildefines.h"
11 
12 #include "BLI_math.h"
13 
14 #include "BLT_translation.h"
15 
16 #include "DNA_defaults.h"
17 #include "DNA_mesh_types.h"
18 #include "DNA_meshdata_types.h"
19 #include "DNA_object_types.h"
20 #include "DNA_screen_types.h"
21 
22 #include "BKE_context.h"
23 #include "BKE_deform.h"
24 #include "BKE_editmesh.h"
25 #include "BKE_lib_id.h"
26 #include "BKE_mesh.h"
27 #include "BKE_mesh_wrapper.h"
28 #include "BKE_particle.h"
29 #include "BKE_screen.h"
30 
31 #include "UI_interface.h"
32 #include "UI_resources.h"
33 
34 #include "RNA_access.h"
35 #include "RNA_prototypes.h"
36 
37 #include "MOD_modifiertypes.h"
38 #include "MOD_ui_common.h"
39 #include "MOD_util.h"
40 
41 static void initData(ModifierData *md)
42 {
44 
46 
48 }
49 
50 static bool isDisabled(const struct Scene *UNUSED(scene),
51  ModifierData *md,
52  bool UNUSED(useRenderParams))
53 {
55 
56  const short flag = smd->flag & (MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z);
57 
58  /* disable if modifier is off for X, Y and Z or if factor is 0 */
59  if (smd->fac == 0.0f || flag == 0) {
60  return true;
61  }
62 
63  return false;
64 }
65 
66 static void requiredDataMask(Object *UNUSED(ob),
67  ModifierData *md,
68  CustomData_MeshMasks *r_cddata_masks)
69 {
71 
72  /* ask for vertexgroups if we need them */
73  if (smd->defgrp_name[0] != '\0') {
74  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
75  }
76 }
77 
78 static void smoothModifier_do(
79  SmoothModifierData *smd, Object *ob, Mesh *mesh, float (*vertexCos)[3], int verts_num)
80 {
81  if (mesh == NULL) {
82  return;
83  }
84 
85  float(*accumulated_vecs)[3] = MEM_calloc_arrayN(
86  (size_t)verts_num, sizeof(*accumulated_vecs), __func__);
87  if (!accumulated_vecs) {
88  return;
89  }
90 
91  uint *accumulated_vecs_count = MEM_calloc_arrayN(
92  (size_t)verts_num, sizeof(*accumulated_vecs_count), __func__);
93  if (!accumulated_vecs_count) {
94  MEM_freeN(accumulated_vecs);
95  return;
96  }
97 
98  const float fac_new = smd->fac;
99  const float fac_orig = 1.0f - fac_new;
100  const bool invert_vgroup = (smd->flag & MOD_SMOOTH_INVERT_VGROUP) != 0;
101 
102  MEdge *medges = mesh->medge;
103  const int edges_num = mesh->totedge;
104 
105  MDeformVert *dvert;
106  int defgrp_index;
107  MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index);
108 
109  for (int j = 0; j < smd->repeat; j++) {
110  if (j != 0) {
111  memset(accumulated_vecs, 0, sizeof(*accumulated_vecs) * (size_t)verts_num);
112  memset(accumulated_vecs_count, 0, sizeof(*accumulated_vecs_count) * (size_t)verts_num);
113  }
114 
115  for (int i = 0; i < edges_num; i++) {
116  float fvec[3];
117  const uint idx1 = medges[i].v1;
118  const uint idx2 = medges[i].v2;
119 
120  mid_v3_v3v3(fvec, vertexCos[idx1], vertexCos[idx2]);
121 
122  accumulated_vecs_count[idx1]++;
123  add_v3_v3(accumulated_vecs[idx1], fvec);
124 
125  accumulated_vecs_count[idx2]++;
126  add_v3_v3(accumulated_vecs[idx2], fvec);
127  }
128 
129  const short flag = smd->flag;
130  if (dvert) {
131  MDeformVert *dv = dvert;
132  for (int i = 0; i < verts_num; i++, dv++) {
133  float *vco_orig = vertexCos[i];
134  if (accumulated_vecs_count[i] > 0) {
135  mul_v3_fl(accumulated_vecs[i], 1.0f / (float)accumulated_vecs_count[i]);
136  }
137  float *vco_new = accumulated_vecs[i];
138 
139  const float f_vgroup = invert_vgroup ? (1.0f - BKE_defvert_find_weight(dv, defgrp_index)) :
140  BKE_defvert_find_weight(dv, defgrp_index);
141  if (f_vgroup <= 0.0f) {
142  continue;
143  }
144  const float f_new = f_vgroup * fac_new;
145  const float f_orig = 1.0f - f_new;
146 
147  if (flag & MOD_SMOOTH_X) {
148  vco_orig[0] = f_orig * vco_orig[0] + f_new * vco_new[0];
149  }
150  if (flag & MOD_SMOOTH_Y) {
151  vco_orig[1] = f_orig * vco_orig[1] + f_new * vco_new[1];
152  }
153  if (flag & MOD_SMOOTH_Z) {
154  vco_orig[2] = f_orig * vco_orig[2] + f_new * vco_new[2];
155  }
156  }
157  }
158  else { /* no vertex group */
159  for (int i = 0; i < verts_num; i++) {
160  float *vco_orig = vertexCos[i];
161  if (accumulated_vecs_count[i] > 0) {
162  mul_v3_fl(accumulated_vecs[i], 1.0f / (float)accumulated_vecs_count[i]);
163  }
164  float *vco_new = accumulated_vecs[i];
165 
166  if (flag & MOD_SMOOTH_X) {
167  vco_orig[0] = fac_orig * vco_orig[0] + fac_new * vco_new[0];
168  }
169  if (flag & MOD_SMOOTH_Y) {
170  vco_orig[1] = fac_orig * vco_orig[1] + fac_new * vco_new[1];
171  }
172  if (flag & MOD_SMOOTH_Z) {
173  vco_orig[2] = fac_orig * vco_orig[2] + fac_new * vco_new[2];
174  }
175  }
176  }
177  }
178 
179  MEM_freeN(accumulated_vecs);
180  MEM_freeN(accumulated_vecs_count);
181 }
182 
183 static void deformVerts(ModifierData *md,
184  const ModifierEvalContext *ctx,
185  Mesh *mesh,
186  float (*vertexCos)[3],
187  int verts_num)
188 {
190  Mesh *mesh_src = NULL;
191 
192  /* mesh_src is needed for vgroups, and taking edges into account. */
193  mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
194 
195  smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, verts_num);
196 
197  if (!ELEM(mesh_src, NULL, mesh)) {
198  BKE_id_free(NULL, mesh_src);
199  }
200 }
201 
202 static void deformVertsEM(ModifierData *md,
203  const ModifierEvalContext *ctx,
204  struct BMEditMesh *editData,
205  Mesh *mesh,
206  float (*vertexCos)[3],
207  int verts_num)
208 {
210  Mesh *mesh_src = NULL;
211 
212  /* mesh_src is needed for vgroups, and taking edges into account. */
213  mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, verts_num, false, false);
214 
215  /* TODO(campbell): use edit-mode data only (remove this line). */
217 
218  smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, verts_num);
219 
220  if (!ELEM(mesh_src, NULL, mesh)) {
221  BKE_id_free(NULL, mesh_src);
222  }
223 }
224 
225 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
226 {
227  uiLayout *row, *col;
228  uiLayout *layout = panel->layout;
230 
231  PointerRNA ob_ptr;
233 
234  uiLayoutSetPropSep(layout, true);
235 
236  row = uiLayoutRowWithHeading(layout, true, IFACE_("Axis"));
237  uiItemR(row, ptr, "use_x", toggles_flag, NULL, ICON_NONE);
238  uiItemR(row, ptr, "use_y", toggles_flag, NULL, ICON_NONE);
239  uiItemR(row, ptr, "use_z", toggles_flag, NULL, ICON_NONE);
240 
241  col = uiLayoutColumn(layout, false);
242  uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE);
243  uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
244 
245  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
246 
247  modifier_panel_end(layout, ptr);
248 }
249 
250 static void panelRegister(ARegionType *region_type)
251 {
253 }
254 
256  /* name */ N_("Smooth"),
257  /* structName */ "SmoothModifierData",
258  /* structSize */ sizeof(SmoothModifierData),
259  /* srna */ &RNA_SmoothModifier,
260  /* type */ eModifierTypeType_OnlyDeform,
263  /* icon */ ICON_MOD_SMOOTH,
264 
265  /* copyData */ BKE_modifier_copydata_generic,
266 
267  /* deformVerts */ deformVerts,
268  /* deformMatrices */ NULL,
269  /* deformVertsEM */ deformVertsEM,
270  /* deformMatricesEM */ NULL,
271  /* modifyMesh */ NULL,
272  /* modifyGeometrySet */ NULL,
273 
274  /* initData */ initData,
275  /* requiredDataMask */ requiredDataMask,
276  /* freeData */ NULL,
277  /* isDisabled */ isDisabled,
278  /* updateDepsgraph */ NULL,
279  /* dependsOnTime */ NULL,
280  /* dependsOnNormals */ NULL,
281  /* foreachIDLink */ NULL,
282  /* foreachTexLink */ NULL,
283  /* freeRuntimeData */ NULL,
284  /* panelRegister */ panelRegister,
285  /* blendWrite */ NULL,
286  /* blendRead */ NULL,
287 };
typedef float(TangentPoint)[2]
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.cc:94
@ eModifierTypeFlag_AcceptsCVs
Definition: BKE_modifier.h:67
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:44
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE void mul_v3_fl(float r[3], float f)
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
MINLINE void add_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
#define CD_MASK_MDEFORMVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ MOD_SMOOTH_Y
@ MOD_SMOOTH_INVERT_VGROUP
@ MOD_SMOOTH_X
@ MOD_SMOOTH_Z
struct SmoothModifierData SmoothModifierData
@ eModifierType_Smooth
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float(*vertexCos)[3], int verts_num)
Definition: MOD_smooth.c:183
static void deformVertsEM(ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *editData, Mesh *mesh, float(*vertexCos)[3], int verts_num)
Definition: MOD_smooth.c:202
ModifierTypeInfo modifierType_Smooth
Definition: MOD_smooth.c:255
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
Definition: MOD_smooth.c:50
static void smoothModifier_do(SmoothModifierData *smd, Object *ob, Mesh *mesh, float(*vertexCos)[3], int verts_num)
Definition: MOD_smooth.c:78
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_smooth.c:225
static void initData(ModifierData *md)
Definition: MOD_smooth.c:41
static void panelRegister(ARegionType *region_type)
Definition: MOD_smooth.c:250
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
Definition: MOD_smooth.c:66
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)
Mesh * MOD_deform_mesh_eval_get(Object *ob, struct BMEditMesh *em, Mesh *mesh, const float(*vertexCos)[3], const int verts_num, const bool use_normals, const bool use_orco)
Definition: MOD_util.c:167
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Definition: MOD_util.c:235
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_FORCE_BLANK_DECORATE
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
Scene scene
uint col
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
unsigned int v1
unsigned int v2
struct MEdge * medge
int totedge
struct Object * object
Definition: BKE_modifier.h:141
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480