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