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 * Contributor(s): Campbell Barton 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 * 00022 */ 00023 00028 #include <string.h> 00029 00030 #include "MEM_guardedalloc.h" 00031 00032 #include "BLI_math.h" 00033 #include "BLI_utildefines.h" 00034 #include "BLI_string.h" 00035 00036 #include "BKE_cdderivedmesh.h" 00037 #include "BKE_modifier.h" 00038 #include "BKE_deform.h" 00039 #include "BKE_texture.h" 00040 #include "BKE_colortools.h" 00041 00042 #include "DNA_object_types.h" 00043 #include "DNA_meshdata_types.h" 00044 00045 #include "depsgraph_private.h" 00046 00047 #include "RE_shader_ext.h" 00048 00049 #include "MOD_util.h" 00050 00051 00052 static void initData(ModifierData *md) 00053 { 00054 WarpModifierData *wmd = (WarpModifierData*) md; 00055 00056 wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); 00057 wmd->texture = NULL; 00058 wmd->strength = 1.0f; 00059 wmd->falloff_radius = 1.0f; 00060 wmd->falloff_type = eWarp_Falloff_Smooth; 00061 wmd->flag = 0; 00062 } 00063 00064 static void copyData(ModifierData *md, ModifierData *target) 00065 { 00066 WarpModifierData *wmd = (WarpModifierData*) md; 00067 WarpModifierData *twmd = (WarpModifierData*) target; 00068 00069 twmd->object_from = wmd->object_from; 00070 twmd->object_to = wmd->object_to; 00071 00072 twmd->strength = wmd->strength; 00073 twmd->falloff_radius = wmd->falloff_radius; 00074 twmd->falloff_type = wmd->falloff_type; 00075 BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name)); 00076 twmd->curfalloff = curvemapping_copy(wmd->curfalloff); 00077 00078 /* map info */ 00079 twmd->texture = wmd->texture; 00080 twmd->map_object = wmd->map_object; 00081 BLI_strncpy(twmd->uvlayer_name, wmd->uvlayer_name, sizeof(twmd->uvlayer_name)); 00082 twmd->texmapping= wmd->texmapping; 00083 } 00084 00085 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) 00086 { 00087 WarpModifierData *wmd = (WarpModifierData *)md; 00088 CustomDataMask dataMask = 0; 00089 00090 /* ask for vertexgroups if we need them */ 00091 if(wmd->defgrp_name[0]) dataMask |= (CD_MASK_MDEFORMVERT); 00092 dataMask |= (CD_MASK_MDEFORMVERT); 00093 00094 /* ask for UV coordinates if we need them */ 00095 if(wmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE); 00096 00097 return dataMask; 00098 } 00099 00100 static int dependsOnTime(ModifierData *md) 00101 { 00102 WarpModifierData *wmd = (WarpModifierData *)md; 00103 00104 if(wmd->texture) { 00105 return BKE_texture_dependsOnTime(wmd->texture); 00106 } 00107 else { 00108 return 0; 00109 } 00110 } 00111 00112 static void freeData(ModifierData *md) 00113 { 00114 WarpModifierData *wmd = (WarpModifierData *) md; 00115 curvemapping_free(wmd->curfalloff); 00116 } 00117 00118 00119 static int isDisabled(ModifierData *md, int UNUSED(userRenderParams)) 00120 { 00121 WarpModifierData *wmd = (WarpModifierData*) md; 00122 00123 return !(wmd->object_from && wmd->object_to); 00124 } 00125 00126 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData) 00127 { 00128 WarpModifierData *wmd = (WarpModifierData*) md; 00129 00130 walk(userData, ob, &wmd->object_from); 00131 walk(userData, ob, &wmd->object_to); 00132 walk(userData, ob, &wmd->map_object); 00133 } 00134 00135 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) 00136 { 00137 WarpModifierData *wmd = (WarpModifierData*) md; 00138 00139 walk(userData, ob, (ID **)&wmd->texture); 00140 00141 walk(userData, ob, (ID **)&wmd->object_from); 00142 walk(userData, ob, (ID **)&wmd->object_to); 00143 walk(userData, ob, (ID **)&wmd->map_object); 00144 } 00145 00146 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) 00147 { 00148 walk(userData, ob, md, "texture"); 00149 } 00150 00151 static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene), 00152 Object *UNUSED(ob), DagNode *obNode) 00153 { 00154 WarpModifierData *wmd = (WarpModifierData*) md; 00155 00156 if(wmd->object_from && wmd->object_to) { 00157 DagNode *fromNode = dag_get_node(forest, wmd->object_from); 00158 DagNode *toNode = dag_get_node(forest, wmd->object_to); 00159 00160 dag_add_relation(forest, fromNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier1"); 00161 dag_add_relation(forest, toNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier2"); 00162 } 00163 00164 if((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object) { 00165 DagNode *curNode = dag_get_node(forest, wmd->map_object); 00166 dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier3"); 00167 } 00168 } 00169 00170 static void warpModifier_do(WarpModifierData *wmd, Object *ob, 00171 DerivedMesh *dm, float (*vertexCos)[3], int numVerts) 00172 { 00173 float obinv[4][4]; 00174 float mat_from[4][4]; 00175 float mat_from_inv[4][4]; 00176 float mat_to[4][4]; 00177 float mat_unit[4][4]; 00178 float mat_final[4][4]; 00179 00180 float tmat[4][4]; 00181 00182 float strength = wmd->strength; 00183 float fac = 1.0f, weight; 00184 int i; 00185 int defgrp_index; 00186 MDeformVert *dvert, *dv= NULL; 00187 00188 float (*tex_co)[3]= NULL; 00189 00190 if(!(wmd->object_from && wmd->object_to)) 00191 return; 00192 00193 modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index); 00194 00195 if(wmd->curfalloff==NULL) /* should never happen, but bad lib linking could cause it */ 00196 wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); 00197 00198 invert_m4_m4(obinv, ob->obmat); 00199 00200 mult_m4_m4m4(mat_from, obinv, wmd->object_from->obmat); 00201 mult_m4_m4m4(mat_to, obinv, wmd->object_to->obmat); 00202 00203 invert_m4_m4(tmat, mat_from); // swap? 00204 mult_m4_m4m4(mat_final, tmat, mat_to); 00205 00206 invert_m4_m4(mat_from_inv, mat_from); 00207 00208 unit_m4(mat_unit); 00209 00210 if(strength < 0.0f) { 00211 float loc[3]; 00212 strength = -strength; 00213 00214 /* inverted location is not useful, just use the negative */ 00215 copy_v3_v3(loc, mat_final[3]); 00216 invert_m4(mat_final); 00217 negate_v3_v3(mat_final[3], loc); 00218 00219 } 00220 weight= strength; 00221 00222 if(wmd->texture) { 00223 tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "warpModifier_do tex_co"); 00224 get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts); 00225 } 00226 00227 for(i = 0; i < numVerts; i++) { 00228 float *co = vertexCos[i]; 00229 00230 if(wmd->falloff_type==eWarp_Falloff_None || 00231 ((fac=len_v3v3(co, mat_from[3])) < wmd->falloff_radius && (fac=(wmd->falloff_radius-fac)/wmd->falloff_radius)) ) { 00232 00233 /* skip if no vert group found */ 00234 if(dvert && defgrp_index >= 0) { 00235 dv = &dvert[i]; 00236 00237 if(dv) { 00238 weight = defvert_find_weight(dv, defgrp_index) * strength; 00239 if(weight <= 0.0f) /* Should never occure... */ 00240 continue; 00241 } 00242 } 00243 00244 00245 /* closely match PROP_SMOOTH and similar */ 00246 switch(wmd->falloff_type) { 00247 case eWarp_Falloff_None: 00248 fac = 1.0f; 00249 break; 00250 case eWarp_Falloff_Curve: 00251 fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac); 00252 break; 00253 case eWarp_Falloff_Sharp: 00254 fac = fac*fac; 00255 break; 00256 case eWarp_Falloff_Smooth: 00257 fac = 3.0f*fac*fac - 2.0f*fac*fac*fac; 00258 break; 00259 case eWarp_Falloff_Root: 00260 fac = (float)sqrt(fac); 00261 break; 00262 case eWarp_Falloff_Linear: 00263 /* pass */ 00264 break; 00265 case eWarp_Falloff_Const: 00266 fac = 1.0f; 00267 break; 00268 case eWarp_Falloff_Sphere: 00269 fac = (float)sqrt(2*fac - fac * fac); 00270 break; 00271 } 00272 00273 fac *= weight; 00274 00275 if(tex_co) { 00276 TexResult texres; 00277 texres.nor = NULL; 00278 get_texture_value(wmd->texture, tex_co[i], &texres); 00279 fac *= texres.tin; 00280 } 00281 00282 /* into the 'from' objects space */ 00283 mul_m4_v3(mat_from_inv, co); 00284 00285 if(fac >= 1.0f) { 00286 mul_m4_v3(mat_final, co); 00287 } 00288 else if(fac > 0.0f) { 00289 if(wmd->flag & MOD_WARP_VOLUME_PRESERVE) { 00290 /* interpolate the matrix for nicer locations */ 00291 blend_m4_m4m4(tmat, mat_unit, mat_final, fac); 00292 mul_m4_v3(tmat, co); 00293 } 00294 else { 00295 float tvec[3]; 00296 mul_v3_m4v3(tvec, mat_final, co); 00297 interp_v3_v3v3(co, co, tvec, fac); 00298 } 00299 } 00300 00301 /* out of the 'from' objects space */ 00302 mul_m4_v3(mat_from, co); 00303 } 00304 } 00305 00306 if(tex_co) 00307 MEM_freeN(tex_co); 00308 00309 } 00310 00311 static int warp_needs_dm(WarpModifierData *wmd) 00312 { 00313 return wmd->texture || wmd->defgrp_name[0]; 00314 } 00315 00316 static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, 00317 float (*vertexCos)[3], int numVerts, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) 00318 { 00319 DerivedMesh *dm= NULL; 00320 int use_dm= warp_needs_dm((WarpModifierData *)md); 00321 00322 if(use_dm) { 00323 dm= get_cddm(ob, NULL, derivedData, vertexCos); 00324 } 00325 00326 warpModifier_do((WarpModifierData *)md, ob, dm, vertexCos, numVerts); 00327 00328 if(use_dm) { 00329 if(dm != derivedData) dm->release(dm); 00330 } 00331 } 00332 00333 static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *editData, 00334 DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) 00335 { 00336 DerivedMesh *dm = derivedData; 00337 int use_dm= warp_needs_dm((WarpModifierData *)md); 00338 00339 if(use_dm) { 00340 if(!derivedData) 00341 dm = CDDM_from_editmesh(editData, ob->data); 00342 } 00343 00344 deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0); 00345 00346 if(use_dm) { 00347 if(!derivedData) dm->release(dm); 00348 } 00349 } 00350 00351 00352 ModifierTypeInfo modifierType_Warp = { 00353 /* name */ "Warp", 00354 /* structName */ "WarpModifierData", 00355 /* structSize */ sizeof(WarpModifierData), 00356 /* type */ eModifierTypeType_OnlyDeform, 00357 /* flags */ eModifierTypeFlag_AcceptsCVs 00358 | eModifierTypeFlag_SupportsEditmode, 00359 /* copyData */ copyData, 00360 /* deformVerts */ deformVerts, 00361 /* deformMatrices */ NULL, 00362 /* deformVertsEM */ deformVertsEM, 00363 /* deformMatricesEM */ NULL, 00364 /* applyModifier */ 0, 00365 /* applyModifierEM */ 0, 00366 /* initData */ initData, 00367 /* requiredDataMask */ requiredDataMask, 00368 /* freeData */ freeData, 00369 /* isDisabled */ isDisabled, 00370 /* updateDepgraph */ updateDepgraph, 00371 /* dependsOnTime */ dependsOnTime, 00372 /* dependsOnNormals */ NULL, 00373 /* foreachObjectLink */ foreachObjectLink, 00374 /* foreachIDLink */ foreachIDLink, 00375 /* foreachTexLink */ foreachTexLink, 00376 };