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