Blender V2.61 - r43446

MOD_simpledeform.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 #include "DNA_object_types.h"
00038 
00039 #include "BLI_math.h"
00040 #include "BLI_string.h"
00041 #include "BLI_utildefines.h"
00042 
00043 #include "BKE_cdderivedmesh.h"
00044 #include "BKE_lattice.h"
00045 #include "BKE_modifier.h"
00046 #include "BKE_deform.h"
00047 #include "BKE_shrinkwrap.h"
00048 
00049 
00050 #include "depsgraph_private.h"
00051 
00052 #include "MOD_util.h"
00053 
00054 
00055 
00056 /* Clamps/Limits the given coordinate to:  limits[0] <= co[axis] <= limits[1]
00057  * The amount of clamp is saved on dcut */
00058 static void axis_limit(int axis, const float limits[2], float co[3], float dcut[3])
00059 {
00060     float val = co[axis];
00061     if(limits[0] > val) val = limits[0];
00062     if(limits[1] < val) val = limits[1];
00063 
00064     dcut[axis] = co[axis] - val;
00065     co[axis] = val;
00066 }
00067 
00068 static void simpleDeform_taper(const float factor, const float dcut[3], float *co)
00069 {
00070     float x = co[0], y = co[1], z = co[2];
00071     float scale = z*factor;
00072 
00073     co[0] = x + x*scale;
00074     co[1] = y + y*scale;
00075     co[2] = z;
00076 
00077     if(dcut)
00078     {
00079         co[0] += dcut[0];
00080         co[1] += dcut[1];
00081         co[2] += dcut[2];
00082     }
00083 }
00084 
00085 static void simpleDeform_stretch(const float factor, const float dcut[3], float *co)
00086 {
00087     float x = co[0], y = co[1], z = co[2];
00088     float scale;
00089 
00090     scale = (z*z*factor-factor + 1.0f);
00091 
00092     co[0] = x*scale;
00093     co[1] = y*scale;
00094     co[2] = z*(1.0f+factor);
00095 
00096 
00097     if(dcut)
00098     {
00099         co[0] += dcut[0];
00100         co[1] += dcut[1];
00101         co[2] += dcut[2];
00102     }
00103 }
00104 
00105 static void simpleDeform_twist(const float factor, const float *dcut, float *co)
00106 {
00107     float x = co[0], y = co[1], z = co[2];
00108     float theta, sint, cost;
00109 
00110     theta = z*factor;
00111     sint  = sin(theta);
00112     cost  = cos(theta);
00113 
00114     co[0] = x*cost - y*sint;
00115     co[1] = x*sint + y*cost;
00116     co[2] = z;
00117 
00118     if(dcut)
00119     {
00120         co[0] += dcut[0];
00121         co[1] += dcut[1];
00122         co[2] += dcut[2];
00123     }
00124 }
00125 
00126 static void simpleDeform_bend(const float factor, const float dcut[3], float *co)
00127 {
00128     float x = co[0], y = co[1], z = co[2];
00129     float theta, sint, cost;
00130 
00131     theta = x*factor;
00132     sint = sin(theta);
00133     cost = cos(theta);
00134 
00135     if(fabsf(factor) > 1e-7f)
00136     {
00137         co[0] = -(y-1.0f/factor)*sint;
00138         co[1] =  (y-1.0f/factor)*cost + 1.0f/factor;
00139         co[2] = z;
00140     }
00141 
00142 
00143     if(dcut)
00144     {
00145         co[0] += cost*dcut[0];
00146         co[1] += sint*dcut[0];
00147         co[2] += dcut[2];
00148     }
00149 
00150 }
00151 
00152 
00153 /* simple deform modifier */
00154 static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
00155 {
00156     static const float lock_axis[2] = {0.0f, 0.0f};
00157 
00158     int i;
00159     int limit_axis = 0;
00160     float smd_limit[2], smd_factor;
00161     SpaceTransform *transf = NULL, tmp_transf;
00162     void (*simpleDeform_callback)(const float factor, const float dcut[3], float *co) = NULL;   //Mode callback
00163     int vgroup;
00164     MDeformVert *dvert;
00165 
00166     //Safe-check
00167     if(smd->origin == ob) smd->origin = NULL;                   //No self references
00168 
00169     if(smd->limit[0] < 0.0f) smd->limit[0] = 0.0f;
00170     if(smd->limit[0] > 1.0f) smd->limit[0] = 1.0f;
00171 
00172     smd->limit[0] = MIN2(smd->limit[0], smd->limit[1]);         //Upper limit >= than lower limit
00173 
00174     //Calculate matrixs do convert between coordinate spaces
00175     if(smd->origin)
00176     {
00177         transf = &tmp_transf;
00178 
00179         if(smd->originOpts & MOD_SIMPLEDEFORM_ORIGIN_LOCAL)
00180         {
00181             space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat);
00182         }
00183         else
00184         {
00185             copy_m4_m4(transf->local2target, smd->origin->obmat);
00186             invert_m4_m4(transf->target2local, transf->local2target);
00187         }
00188     }
00189 
00190     //Setup vars
00191     limit_axis  = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z
00192 
00193     //Update limits if needed
00194     {
00195         float lower =  FLT_MAX;
00196         float upper = -FLT_MAX;
00197 
00198         for(i=0; i<numVerts; i++)
00199         {
00200             float tmp[3];
00201             copy_v3_v3(tmp, vertexCos[i]);
00202 
00203             if(transf) space_transform_apply(transf, tmp);
00204 
00205             lower = MIN2(lower, tmp[limit_axis]);
00206             upper = MAX2(upper, tmp[limit_axis]);
00207         }
00208 
00209 
00210         //SMD values are normalized to the BV, calculate the absolut values
00211         smd_limit[1] = lower + (upper-lower)*smd->limit[1];
00212         smd_limit[0] = lower + (upper-lower)*smd->limit[0];
00213 
00214         smd_factor   = smd->factor / MAX2(FLT_EPSILON, smd_limit[1]-smd_limit[0]);
00215     }
00216 
00217     modifier_get_vgroup(ob, dm, smd->vgroup_name, &dvert, &vgroup);
00218 
00219     switch(smd->mode)
00220     {
00221         case MOD_SIMPLEDEFORM_MODE_TWIST:   simpleDeform_callback = simpleDeform_twist;     break;
00222         case MOD_SIMPLEDEFORM_MODE_BEND:    simpleDeform_callback = simpleDeform_bend;      break;
00223         case MOD_SIMPLEDEFORM_MODE_TAPER:   simpleDeform_callback = simpleDeform_taper;     break;
00224         case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch;   break;
00225         default:
00226             return; //No simpledeform mode?
00227     }
00228 
00229     for(i=0; i<numVerts; i++)
00230     {
00231         float weight = defvert_array_find_weight_safe(dvert, i, vgroup);
00232 
00233         if(weight != 0.0f)
00234         {
00235             float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
00236 
00237             if(transf) space_transform_apply(transf, vertexCos[i]);
00238 
00239             copy_v3_v3(co, vertexCos[i]);
00240 
00241             //Apply axis limits
00242             if(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) //Bend mode shoulnt have any lock axis
00243             {
00244                 if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut);
00245                 if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut);
00246             }
00247             axis_limit(limit_axis, smd_limit, co, dcut);
00248 
00249             simpleDeform_callback(smd_factor, dcut, co);        //Apply deform
00250             interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); //Use vertex weight has coef of linear interpolation
00251 
00252             if(transf) space_transform_invert(transf, vertexCos[i]);
00253         }
00254     }
00255 }
00256 
00257 
00258 
00259 
00260 /* SimpleDeform */
00261 static void initData(ModifierData *md)
00262 {
00263     SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
00264 
00265     smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST;
00266     smd->axis = 0;
00267 
00268     smd->origin   =  NULL;
00269     smd->factor   =  0.35f;
00270     smd->limit[0] =  0.0f;
00271     smd->limit[1] =  1.0f;
00272 }
00273 
00274 static void copyData(ModifierData *md, ModifierData *target)
00275 {
00276     SimpleDeformModifierData *smd  = (SimpleDeformModifierData*)md;
00277     SimpleDeformModifierData *tsmd = (SimpleDeformModifierData*)target;
00278 
00279     tsmd->mode  = smd->mode;
00280     tsmd->axis  = smd->axis;
00281     tsmd->origin= smd->origin;
00282     tsmd->originOpts= smd->originOpts;
00283     tsmd->factor= smd->factor;
00284     memcpy(tsmd->limit, smd->limit, sizeof(tsmd->limit));
00285     BLI_strncpy(tsmd->vgroup_name, smd->vgroup_name, sizeof(tsmd->vgroup_name));
00286 }
00287 
00288 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
00289 {
00290     SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
00291     CustomDataMask dataMask = 0;
00292 
00293     /* ask for vertexgroups if we need them */
00294     if(smd->vgroup_name[0])
00295         dataMask |= CD_MASK_MDEFORMVERT;
00296 
00297     return dataMask;
00298 }
00299 
00300 static void foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
00301 {
00302     SimpleDeformModifierData *smd  = (SimpleDeformModifierData*)md;
00303     walk(userData, ob, &smd->origin);
00304 }
00305 
00306 static void updateDepgraph(ModifierData *md, DagForest *forest,
00307                         struct Scene *UNUSED(scene),
00308                         Object *UNUSED(ob),
00309                         DagNode *obNode)
00310 {
00311     SimpleDeformModifierData *smd  = (SimpleDeformModifierData*)md;
00312 
00313     if (smd->origin)
00314         dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
00315 }
00316 
00317 static void deformVerts(ModifierData *md, Object *ob,
00318                         DerivedMesh *derivedData,
00319                         float (*vertexCos)[3],
00320                         int numVerts,
00321                         int UNUSED(useRenderParams),
00322                         int UNUSED(isFinalCalc))
00323 {
00324     DerivedMesh *dm = derivedData;
00325     CustomDataMask dataMask = requiredDataMask(ob, md);
00326 
00327     /* we implement requiredDataMask but thats not really useful since
00328        mesh_calc_modifiers pass a NULL derivedData */
00329     if(dataMask)
00330         dm= get_dm(ob, NULL, dm, NULL, 0);
00331 
00332     SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
00333 
00334     if(dm != derivedData)
00335         dm->release(dm);
00336 }
00337 
00338 static void deformVertsEM(ModifierData *md, Object *ob,
00339                         struct EditMesh *editData,
00340                         DerivedMesh *derivedData,
00341                         float (*vertexCos)[3],
00342                         int numVerts)
00343 {
00344     DerivedMesh *dm = derivedData;
00345     CustomDataMask dataMask = requiredDataMask(ob, md);
00346 
00347     /* we implement requiredDataMask but thats not really useful since
00348        mesh_calc_modifiers pass a NULL derivedData */
00349     if(dataMask)
00350         dm= get_dm(ob, editData, dm, NULL, 0);
00351 
00352     SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts);
00353 
00354     if(dm != derivedData)
00355         dm->release(dm);
00356 }
00357 
00358 
00359 ModifierTypeInfo modifierType_SimpleDeform = {
00360     /* name */              "SimpleDeform",
00361     /* structName */        "SimpleDeformModifierData",
00362     /* structSize */        sizeof(SimpleDeformModifierData),
00363     /* type */              eModifierTypeType_OnlyDeform,
00364 
00365     /* flags */             eModifierTypeFlag_AcceptsMesh
00366                             | eModifierTypeFlag_AcceptsCVs
00367                             | eModifierTypeFlag_SupportsEditmode
00368                             | eModifierTypeFlag_EnableInEditmode,
00369 
00370     /* copyData */          copyData,
00371     /* deformVerts */       deformVerts,
00372     /* deformMatrices */    NULL,
00373     /* deformVertsEM */     deformVertsEM,
00374     /* deformMatricesEM */  NULL,
00375     /* applyModifier */     NULL,
00376     /* applyModifierEM */   NULL,
00377     /* initData */          initData,
00378     /* requiredDataMask */  requiredDataMask,
00379     /* freeData */          NULL,
00380     /* isDisabled */        NULL,
00381     /* updateDepgraph */    updateDepgraph,
00382     /* dependsOnTime */     NULL,
00383     /* dependsOnNormals */  NULL,
00384     /* foreachObjectLink */ foreachObjectLink,
00385     /* foreachIDLink */     NULL,
00386     /* foreachTexLink */    NULL,
00387 };