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