Blender V2.61 - r43446

MOD_smooth.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software  Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Daniel Dunbar
00022  *                 Ton Roosendaal,
00023  *                 Ben Batt,
00024  *                 Brecht Van Lommel,
00025  *                 Campbell Barton
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  *
00029  */
00030 
00036 #include "DNA_meshdata_types.h"
00037 
00038 #include "BLI_math.h"
00039 #include "BLI_utildefines.h"
00040 #include "BLI_string.h"
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "BKE_cdderivedmesh.h"
00045 #include "BKE_particle.h"
00046 #include "BKE_deform.h"
00047 
00048 #include "MOD_modifiertypes.h"
00049 #include "MOD_util.h"
00050 
00051 
00052 static void initData(ModifierData *md)
00053 {
00054     SmoothModifierData *smd = (SmoothModifierData*) md;
00055 
00056     smd->fac = 0.5f;
00057     smd->repeat = 1;
00058     smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
00059     smd->defgrp_name[0] = '\0';
00060 }
00061 
00062 static void copyData(ModifierData *md, ModifierData *target)
00063 {
00064     SmoothModifierData *smd = (SmoothModifierData*) md;
00065     SmoothModifierData *tsmd = (SmoothModifierData*) target;
00066 
00067     tsmd->fac = smd->fac;
00068     tsmd->repeat = smd->repeat;
00069     tsmd->flag = smd->flag;
00070     BLI_strncpy(tsmd->defgrp_name, smd->defgrp_name, sizeof(tsmd->defgrp_name));
00071 }
00072 
00073 static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
00074 {
00075     SmoothModifierData *smd = (SmoothModifierData*) md;
00076     short flag;
00077 
00078     flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
00079 
00080     /* disable if modifier is off for X, Y and Z or if factor is 0 */
00081     if((smd->fac == 0.0f) || flag == 0) return 1;
00082 
00083     return 0;
00084 }
00085 
00086 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
00087 {
00088     SmoothModifierData *smd = (SmoothModifierData *)md;
00089     CustomDataMask dataMask = 0;
00090 
00091     /* ask for vertexgroups if we need them */
00092     if(smd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
00093 
00094     return dataMask;
00095 }
00096 
00097 static void smoothModifier_do(
00098                   SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
00099      float (*vertexCos)[3], int numVerts)
00100 {
00101     MDeformVert *dvert = NULL;
00102     MEdge *medges = NULL;
00103 
00104     int i, j, numDMEdges, defgrp_index;
00105     unsigned char *uctmp;
00106     float *ftmp, fac, facm;
00107 
00108     ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
00109         "smoothmodifier_f");
00110     if (!ftmp) return;
00111     uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
00112          "smoothmodifier_uc");
00113     if (!uctmp) {
00114         if (ftmp) MEM_freeN(ftmp);
00115         return;
00116     }
00117 
00118     fac = smd->fac;
00119     facm = 1 - fac;
00120 
00121     medges = dm->getEdgeArray(dm);
00122     numDMEdges = dm->getNumEdges(dm);
00123 
00124     modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index);
00125 
00126     /* NOTICE: this can be optimized a little bit by moving the
00127     * if (dvert) out of the loop, if needed */
00128     for (j = 0; j < smd->repeat; j++) {
00129         for (i = 0; i < numDMEdges; i++) {
00130             float fvec[3];
00131             float *v1, *v2;
00132             unsigned int idx1, idx2;
00133 
00134             idx1 = medges[i].v1;
00135             idx2 = medges[i].v2;
00136 
00137             v1 = vertexCos[idx1];
00138             v2 = vertexCos[idx2];
00139 
00140             mid_v3_v3v3(fvec, v1, v2);
00141 
00142             v1 = &ftmp[idx1*3];
00143             v2 = &ftmp[idx2*3];
00144 
00145             if (uctmp[idx1] < 255) {
00146                 uctmp[idx1]++;
00147                 add_v3_v3(v1, fvec);
00148             }
00149             if (uctmp[idx2] < 255) {
00150                 uctmp[idx2]++;
00151                 add_v3_v3(v2, fvec);
00152             }
00153         }
00154 
00155         if (dvert) {
00156             MDeformVert *dv= dvert;
00157             for (i = 0; i < numVerts; i++, dv++) {
00158                 float f, fm, facw, *fp, *v;
00159                 short flag = smd->flag;
00160 
00161                 v = vertexCos[i];
00162                 fp = &ftmp[i*3];
00163 
00164 
00165                 f= defvert_find_weight(dv, defgrp_index);
00166                 if (f <= 0.0f) continue;
00167 
00168                 f *= fac;
00169                 fm = 1.0f - f;
00170 
00171                 /* fp is the sum of uctmp[i] verts, so must be averaged */
00172                 facw = 0.0f;
00173                 if (uctmp[i]) 
00174                     facw = f / (float)uctmp[i];
00175 
00176                 if (flag & MOD_SMOOTH_X)
00177                     v[0] = fm * v[0] + facw * fp[0];
00178                 if (flag & MOD_SMOOTH_Y)
00179                     v[1] = fm * v[1] + facw * fp[1];
00180                 if (flag & MOD_SMOOTH_Z)
00181                     v[2] = fm * v[2] + facw * fp[2];
00182             }
00183         }
00184         else { /* no vertex group */
00185             for (i = 0; i < numVerts; i++) {
00186                 float facw, *fp, *v;
00187                 short flag = smd->flag;
00188 
00189                 v = vertexCos[i];
00190                 fp = &ftmp[i*3];
00191 
00192                 /* fp is the sum of uctmp[i] verts, so must be averaged */
00193                 facw = 0.0f;
00194                 if (uctmp[i]) 
00195                     facw = fac / (float)uctmp[i];
00196 
00197                 if (flag & MOD_SMOOTH_X)
00198                     v[0] = facm * v[0] + facw * fp[0];
00199                 if (flag & MOD_SMOOTH_Y)
00200                     v[1] = facm * v[1] + facw * fp[1];
00201                 if (flag & MOD_SMOOTH_Z)
00202                     v[2] = facm * v[2] + facw * fp[2];
00203             }
00204 
00205         }
00206 
00207         memset(ftmp, 0, 3*sizeof(float)*numVerts);
00208         memset(uctmp, 0, sizeof(unsigned char)*numVerts);
00209     }
00210 
00211     MEM_freeN(ftmp);
00212     MEM_freeN(uctmp);
00213 }
00214 
00215 static void deformVerts(
00216                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
00217        float (*vertexCos)[3], int numVerts, int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
00218 {
00219     DerivedMesh *dm= get_dm(ob, NULL, derivedData, NULL, 0);
00220 
00221     smoothModifier_do((SmoothModifierData *)md, ob, dm,
00222                       vertexCos, numVerts);
00223 
00224     if(dm != derivedData)
00225         dm->release(dm);
00226 }
00227 
00228 static void deformVertsEM(
00229                      ModifierData *md, Object *ob, struct EditMesh *editData,
00230       DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
00231 {
00232     DerivedMesh *dm= get_dm(ob, editData, derivedData, NULL, 0);
00233 
00234     smoothModifier_do((SmoothModifierData *)md, ob, dm,
00235                       vertexCos, numVerts);
00236 
00237     if(dm != derivedData)
00238         dm->release(dm);
00239 }
00240 
00241 
00242 ModifierTypeInfo modifierType_Smooth = {
00243     /* name */              "Smooth",
00244     /* structName */        "SmoothModifierData",
00245     /* structSize */        sizeof(SmoothModifierData),
00246     /* type */              eModifierTypeType_OnlyDeform,
00247     /* flags */             eModifierTypeFlag_AcceptsMesh
00248                             | eModifierTypeFlag_SupportsEditmode,
00249 
00250     /* copyData */          copyData,
00251     /* deformVerts */       deformVerts,
00252     /* deformMatrices */    NULL,
00253     /* deformVertsEM */     deformVertsEM,
00254     /* deformMatricesEM */  NULL,
00255     /* applyModifier */     NULL,
00256     /* applyModifierEM */   NULL,
00257     /* initData */          initData,
00258     /* requiredDataMask */  requiredDataMask,
00259     /* freeData */          NULL,
00260     /* isDisabled */        isDisabled,
00261     /* updateDepgraph */    NULL,
00262     /* dependsOnTime */     NULL,
00263     /* dependsOnNormals */  NULL,
00264     /* foreachObjectLink */ NULL,
00265     /* foreachIDLink */     NULL,
00266     /* foreachTexLink */    NULL,
00267 };