|
Blender
V2.59
|
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 };