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