SVN maintenance.
[blender.git] / source / blender / modifiers / intern / MOD_smooth.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
22 *
23 * Contributor(s): Daniel Dunbar
24 *                 Ton Roosendaal,
25 *                 Ben Batt,
26 *                 Brecht Van Lommel,
27 *                 Campbell Barton
28 *
29 * ***** END GPL LICENSE BLOCK *****
30 *
31 */
32
33 #include "stddef.h"
34 #include "string.h"
35 #include "stdarg.h"
36 #include "math.h"
37 #include "float.h"
38
39 #include "BLI_kdtree.h"
40 #include "BLI_rand.h"
41 #include "BLI_uvproject.h"
42
43 #include "MEM_guardedalloc.h"
44
45 #include "DNA_armature_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_key_types.h"
49 #include "DNA_material_types.h"
50 #include "DNA_object_fluidsim.h"
51
52
53 #include "BKE_action.h"
54 #include "BKE_bmesh.h"
55 #include "BKE_cloth.h"
56 #include "BKE_cdderivedmesh.h"
57 #include "BKE_displist.h"
58 #include "BKE_fluidsim.h"
59 #include "BKE_global.h"
60 #include "BKE_multires.h"
61 #include "BKE_key.h"
62 #include "BKE_lattice.h"
63 #include "BKE_material.h"
64 #include "BKE_mesh.h"
65 #include "BKE_modifier.h"
66 #include "BKE_object.h"
67 #include "BKE_paint.h"
68 #include "BKE_particle.h"
69 #include "BKE_pointcache.h"
70 #include "BKE_scene.h"
71 #include "BKE_smoke.h"
72 #include "BKE_softbody.h"
73 #include "BKE_subsurf.h"
74 #include "BKE_texture.h"
75
76 #include "depsgraph_private.h"
77 #include "BKE_deform.h"
78 #include "BKE_shrinkwrap.h"
79
80 #include "LOD_decimation.h"
81
82 #include "CCGSubSurf.h"
83
84 #include "RE_shader_ext.h"
85
86 #include "MOD_modifiertypes.h"
87 #include "MOD_util.h"
88
89
90 static void initData(ModifierData *md)
91 {
92         SmoothModifierData *smd = (SmoothModifierData*) md;
93
94         smd->fac = 0.5f;
95         smd->repeat = 1;
96         smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
97         smd->defgrp_name[0] = '\0';
98 }
99
100 static void copyData(ModifierData *md, ModifierData *target)
101 {
102         SmoothModifierData *smd = (SmoothModifierData*) md;
103         SmoothModifierData *tsmd = (SmoothModifierData*) target;
104
105         tsmd->fac = smd->fac;
106         tsmd->repeat = smd->repeat;
107         tsmd->flag = smd->flag;
108         strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
109 }
110
111 static int isDisabled(ModifierData *md, int useRenderParams)
112 {
113         SmoothModifierData *smd = (SmoothModifierData*) md;
114         short flag;
115
116         flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
117
118         /* disable if modifier is off for X, Y and Z or if factor is 0 */
119         if((smd->fac == 0.0f) || flag == 0) return 1;
120
121         return 0;
122 }
123
124 static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
125 {
126         SmoothModifierData *smd = (SmoothModifierData *)md;
127         CustomDataMask dataMask = 0;
128
129         /* ask for vertexgroups if we need them */
130         if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
131
132         return dataMask;
133 }
134
135 static void smoothModifier_do(
136                                   SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
137          float (*vertexCos)[3], int numVerts)
138 {
139         MDeformVert *dvert = NULL;
140         MEdge *medges = NULL;
141
142         int i, j, numDMEdges, defgrp_index;
143         unsigned char *uctmp;
144         float *ftmp, fac, facm;
145
146         ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
147                 "smoothmodifier_f");
148         if (!ftmp) return;
149         uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
150                  "smoothmodifier_uc");
151         if (!uctmp) {
152                 if (ftmp) MEM_freeN(ftmp);
153                 return;
154         }
155
156         fac = smd->fac;
157         facm = 1 - fac;
158
159         medges = dm->getEdgeArray(dm);
160         numDMEdges = dm->getNumEdges(dm);
161
162         defgrp_index = defgroup_name_index(ob, smd->defgrp_name);
163
164         if (defgrp_index >= 0)
165                 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
166
167         /* NOTICE: this can be optimized a little bit by moving the
168         * if (dvert) out of the loop, if needed */
169         for (j = 0; j < smd->repeat; j++) {
170                 for (i = 0; i < numDMEdges; i++) {
171                         float fvec[3];
172                         float *v1, *v2;
173                         unsigned int idx1, idx2;
174
175                         idx1 = medges[i].v1;
176                         idx2 = medges[i].v2;
177
178                         v1 = vertexCos[idx1];
179                         v2 = vertexCos[idx2];
180
181                         fvec[0] = (v1[0] + v2[0]) / 2.0;
182                         fvec[1] = (v1[1] + v2[1]) / 2.0;
183                         fvec[2] = (v1[2] + v2[2]) / 2.0;
184
185                         v1 = &ftmp[idx1*3];
186                         v2 = &ftmp[idx2*3];
187
188                         if (uctmp[idx1] < 255) {
189                                 uctmp[idx1]++;
190                                 add_v3_v3v3(v1, v1, fvec);
191                         }
192                         if (uctmp[idx2] < 255) {
193                                 uctmp[idx2]++;
194                                 add_v3_v3v3(v2, v2, fvec);
195                         }
196                 }
197
198                 if (dvert) {
199                         for (i = 0; i < numVerts; i++) {
200                                 MDeformWeight *dw = NULL;
201                                 float f, fm, facw, *fp, *v;
202                                 int k;
203                                 short flag = smd->flag;
204
205                                 v = vertexCos[i];
206                                 fp = &ftmp[i*3];
207
208                                 for (k = 0; k < dvert[i].totweight; ++k) {
209                                         if(dvert[i].dw[k].def_nr == defgrp_index) {
210                                                 dw = &dvert[i].dw[k];
211                                                 break;
212                                         }
213                                 }
214                                 if (!dw) continue;
215
216                                 f = fac * dw->weight;
217                                 fm = 1.0f - f;
218
219                                 /* fp is the sum of uctmp[i] verts, so must be averaged */
220                                 facw = 0.0f;
221                                 if (uctmp[i]) 
222                                         facw = f / (float)uctmp[i];
223
224                                 if (flag & MOD_SMOOTH_X)
225                                         v[0] = fm * v[0] + facw * fp[0];
226                                 if (flag & MOD_SMOOTH_Y)
227                                         v[1] = fm * v[1] + facw * fp[1];
228                                 if (flag & MOD_SMOOTH_Z)
229                                         v[2] = fm * v[2] + facw * fp[2];
230                         }
231                 }
232                 else { /* no vertex group */
233                         for (i = 0; i < numVerts; i++) {
234                                 float facw, *fp, *v;
235                                 short flag = smd->flag;
236
237                                 v = vertexCos[i];
238                                 fp = &ftmp[i*3];
239
240                                 /* fp is the sum of uctmp[i] verts, so must be averaged */
241                                 facw = 0.0f;
242                                 if (uctmp[i]) 
243                                         facw = fac / (float)uctmp[i];
244
245                                 if (flag & MOD_SMOOTH_X)
246                                         v[0] = facm * v[0] + facw * fp[0];
247                                 if (flag & MOD_SMOOTH_Y)
248                                         v[1] = facm * v[1] + facw * fp[1];
249                                 if (flag & MOD_SMOOTH_Z)
250                                         v[2] = facm * v[2] + facw * fp[2];
251                         }
252
253                 }
254
255                 memset(ftmp, 0, 3*sizeof(float)*numVerts);
256                 memset(uctmp, 0, sizeof(unsigned char)*numVerts);
257         }
258
259         MEM_freeN(ftmp);
260         MEM_freeN(uctmp);
261 }
262
263 static void deformVerts(
264                                            ModifierData *md, Object *ob, DerivedMesh *derivedData,
265            float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
266 {
267         DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0);
268
269         smoothModifier_do((SmoothModifierData *)md, ob, dm,
270                            vertexCos, numVerts);
271
272         if(dm != derivedData)
273                 dm->release(dm);
274 }
275
276 static void deformVertsEM(
277                                          ModifierData *md, Object *ob, EditMesh *editData,
278           DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
279 {
280         DerivedMesh *dm= get_dm(md->scene, ob, editData, derivedData, NULL, 0);
281
282         smoothModifier_do((SmoothModifierData *)md, ob, dm,
283                            vertexCos, numVerts);
284
285         if(dm != derivedData)
286                 dm->release(dm);
287 }
288
289
290 ModifierTypeInfo modifierType_Smooth = {
291         /* name */              "Smooth",
292         /* structName */        "SmoothModifierData",
293         /* structSize */        sizeof(SmoothModifierData),
294         /* type */              eModifierTypeType_OnlyDeform,
295         /* flags */             eModifierTypeFlag_AcceptsMesh | 
296                                                         eModifierTypeFlag_SupportsEditmode,
297
298         /* copyData */          copyData,
299         /* deformVerts */       deformVerts,
300         /* deformVertsEM */     deformVertsEM,
301         /* deformMatricesEM */  0,
302         /* applyModifier */     0,
303         /* applyModifierEM */   0,
304         /* initData */          initData,
305         /* requiredDataMask */  requiredDataMask,
306         /* freeData */          0,
307         /* isDisabled */        isDisabled,
308         /* updateDepgraph */    0,
309         /* dependsOnTime */     0,
310         /* foreachObjectLink */ 0,
311         /* foreachIDLink */     0,
312 };