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) 2011 by Bastien Montagne. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): None yet. 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 * 00025 */ 00026 00031 #include "BLI_utildefines.h" 00032 #include "BLI_math.h" 00033 #include "BLI_string.h" 00034 00035 #include "DNA_mesh_types.h" 00036 #include "DNA_meshdata_types.h" 00037 #include "DNA_modifier_types.h" 00038 #include "DNA_object_types.h" 00039 00040 #include "BKE_cdderivedmesh.h" 00041 #include "BKE_deform.h" 00042 #include "BKE_mesh.h" 00043 #include "BKE_modifier.h" 00044 #include "BKE_texture.h" /* Texture masking. */ 00045 00046 #include "depsgraph_private.h" 00047 #include "MEM_guardedalloc.h" 00048 #include "MOD_util.h" 00049 #include "MOD_weightvg_util.h" 00050 00051 00055 static float mix_weight(float weight, float weight2, char mix_mode) 00056 { 00057 #if 0 00058 /* 00059 * XXX Don't know why, but the switch version takes many CPU time, 00060 * and produces lag in realtime playback... 00061 */ 00062 switch (mix_mode) 00063 { 00064 case MOD_WVG_MIX_ADD: 00065 return (weight + weight2); 00066 case MOD_WVG_MIX_SUB: 00067 return (weight - weight2); 00068 case MOD_WVG_MIX_MUL: 00069 return (weight * weight2); 00070 case MOD_WVG_MIX_DIV: 00071 /* Avoid dividing by zero (or really small values). */ 00072 if (0.0 <= weight2 < MOD_WVG_ZEROFLOOR) 00073 weight2 = MOD_WVG_ZEROFLOOR; 00074 else if (-MOD_WVG_ZEROFLOOR < weight2) 00075 weight2 = -MOD_WVG_ZEROFLOOR; 00076 return (weight / weight2); 00077 case MOD_WVG_MIX_DIF: 00078 return (weight < weight2 ? weight2 - weight : weight - weight2); 00079 case MOD_WVG_MIX_AVG: 00080 return (weight + weight2) / 2.0; 00081 case MOD_WVG_MIX_SET: 00082 default: 00083 return weight2; 00084 } 00085 #endif 00086 if (mix_mode == MOD_WVG_MIX_SET) 00087 return weight2; 00088 else if (mix_mode == MOD_WVG_MIX_ADD) 00089 return (weight + weight2); 00090 else if (mix_mode == MOD_WVG_MIX_SUB) 00091 return (weight - weight2); 00092 else if (mix_mode == MOD_WVG_MIX_MUL) 00093 return (weight * weight2); 00094 else if (mix_mode == MOD_WVG_MIX_DIV) { 00095 /* Avoid dividing by zero (or really small values). */ 00096 if (weight2 < 0.0f && weight2 > -MOD_WVG_ZEROFLOOR) 00097 weight2 = -MOD_WVG_ZEROFLOOR; 00098 else if (weight2 >= 0.0f && weight2 < MOD_WVG_ZEROFLOOR) 00099 weight2 = MOD_WVG_ZEROFLOOR; 00100 return (weight / weight2); 00101 } 00102 else if (mix_mode == MOD_WVG_MIX_DIF) 00103 return (weight < weight2 ? weight2 - weight : weight - weight2); 00104 else if (mix_mode == MOD_WVG_MIX_AVG) 00105 return (weight + weight2) * 0.5f; 00106 else return weight2; 00107 } 00108 00109 /************************************** 00110 * Modifiers functions. * 00111 **************************************/ 00112 static void initData(ModifierData *md) 00113 { 00114 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00115 00116 wmd->default_weight_a = 0.0f; 00117 wmd->default_weight_b = 0.0f; 00118 wmd->mix_mode = MOD_WVG_MIX_SET; 00119 wmd->mix_set = MOD_WVG_SET_AND; 00120 00121 wmd->mask_constant = 1.0f; 00122 wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */ 00123 wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL; 00124 } 00125 00126 static void copyData(ModifierData *md, ModifierData *target) 00127 { 00128 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00129 WeightVGMixModifierData *twmd = (WeightVGMixModifierData*) target; 00130 00131 BLI_strncpy(twmd->defgrp_name_a, wmd->defgrp_name_a, sizeof(twmd->defgrp_name_a)); 00132 BLI_strncpy(twmd->defgrp_name_b, wmd->defgrp_name_b, sizeof(twmd->defgrp_name_b)); 00133 twmd->default_weight_a = wmd->default_weight_a; 00134 twmd->default_weight_b = wmd->default_weight_b; 00135 twmd->mix_mode = wmd->mix_mode; 00136 twmd->mix_set = wmd->mix_set; 00137 00138 twmd->mask_constant = wmd->mask_constant; 00139 BLI_strncpy(twmd->mask_defgrp_name, wmd->mask_defgrp_name, sizeof(twmd->mask_defgrp_name)); 00140 twmd->mask_texture = wmd->mask_texture; 00141 twmd->mask_tex_use_channel = wmd->mask_tex_use_channel; 00142 twmd->mask_tex_mapping = wmd->mask_tex_mapping; 00143 twmd->mask_tex_map_obj = wmd->mask_tex_map_obj; 00144 BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name, sizeof(twmd->mask_tex_uvlayer_name)); 00145 } 00146 00147 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) 00148 { 00149 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00150 CustomDataMask dataMask = 0; 00151 00152 /* We need vertex groups! */ 00153 dataMask |= CD_MASK_MDEFORMVERT; 00154 00155 /* Ask for UV coordinates if we need them. */ 00156 if(wmd->mask_tex_mapping == MOD_DISP_MAP_UV) 00157 dataMask |= CD_MASK_MTFACE; 00158 00159 return dataMask; 00160 } 00161 00162 static int dependsOnTime(ModifierData *md) 00163 { 00164 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00165 00166 if(wmd->mask_texture) 00167 return BKE_texture_dependsOnTime(wmd->mask_texture); 00168 return 0; 00169 } 00170 00171 static void foreachObjectLink(ModifierData *md, Object *ob, 00172 void (*walk)(void *userData, Object *ob, Object **obpoin), 00173 void *userData) 00174 { 00175 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00176 walk(userData, ob, &wmd->mask_tex_map_obj); 00177 } 00178 00179 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) 00180 { 00181 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00182 00183 walk(userData, ob, (ID **)&wmd->mask_texture); 00184 00185 foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); 00186 } 00187 00188 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) 00189 { 00190 walk(userData, ob, md, "mask_texture"); 00191 } 00192 00193 static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene), 00194 Object *UNUSED(ob), DagNode *obNode) 00195 { 00196 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00197 DagNode *curNode; 00198 00199 if(wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) { 00200 curNode = dag_get_node(forest, wmd->mask_tex_map_obj); 00201 00202 dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, 00203 "WeightVGMix Modifier"); 00204 } 00205 00206 if(wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) 00207 dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, 00208 "WeightVGMix Modifier"); 00209 } 00210 00211 static int isDisabled(ModifierData *md, int UNUSED(useRenderParams)) 00212 { 00213 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00214 /* If no vertex group, bypass. */ 00215 return (wmd->defgrp_name_a[0] == '\0'); 00216 } 00217 00218 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, 00219 int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) 00220 { 00221 WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md; 00222 DerivedMesh *dm = derivedData; 00223 MDeformVert *dvert = NULL; 00224 MDeformWeight **dw1, **tdw1, **dw2, **tdw2; 00225 int numVerts; 00226 int defgrp_idx, defgrp_idx2 = -1; 00227 float *org_w; 00228 float *new_w; 00229 int *tidx, *indices = NULL; 00230 int numIdx = 0; 00231 int i; 00232 00233 /* Get number of verts. */ 00234 numVerts = dm->getNumVerts(dm); 00235 00236 /* Check if we can just return the original mesh. 00237 * Must have verts and therefore verts assigned to vgroups to do anything useful! 00238 */ 00239 if ((numVerts == 0) || (ob->defbase.first == NULL)) 00240 return dm; 00241 00242 /* Get vgroup idx from its name. */ 00243 defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name_a); 00244 if (defgrp_idx < 0) 00245 return dm; 00246 /* Get seconf vgroup idx from its name, if given. */ 00247 if (wmd->defgrp_name_b[0] != (char)0) { 00248 defgrp_idx2 = defgroup_name_index(ob, wmd->defgrp_name_b); 00249 if (defgrp_idx2 < 0) 00250 return dm; 00251 } 00252 00253 dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts); 00254 00255 /* Find out which vertices to work on. */ 00256 tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGMix Modifier, tidx"); 00257 tdw1 = MEM_mallocN(sizeof(MDeformWeight*) * numVerts, "WeightVGMix Modifier, tdw1"); 00258 tdw2 = MEM_mallocN(sizeof(MDeformWeight*) * numVerts, "WeightVGMix Modifier, tdw2"); 00259 switch (wmd->mix_set) { 00260 case MOD_WVG_SET_A: 00261 /* All vertices in first vgroup. */ 00262 for (i = 0; i < numVerts; i++) { 00263 MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx); 00264 if(dw) { 00265 tdw1[numIdx] = dw; 00266 tdw2[numIdx] = defvert_find_index(&dvert[i], defgrp_idx2); 00267 tidx[numIdx++] = i; 00268 } 00269 } 00270 break; 00271 case MOD_WVG_SET_B: 00272 /* All vertices in second vgroup. */ 00273 for (i = 0; i < numVerts; i++) { 00274 MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx2); 00275 if(dw) { 00276 tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_idx); 00277 tdw2[numIdx] = dw; 00278 tidx[numIdx++] = i; 00279 } 00280 } 00281 break; 00282 case MOD_WVG_SET_OR: 00283 /* All vertices in one vgroup or the other. */ 00284 for (i = 0; i < numVerts; i++) { 00285 MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); 00286 MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); 00287 if(adw || bdw) { 00288 tdw1[numIdx] = adw; 00289 tdw2[numIdx] = bdw; 00290 tidx[numIdx++] = i; 00291 } 00292 } 00293 break; 00294 case MOD_WVG_SET_AND: 00295 /* All vertices in both vgroups. */ 00296 for (i = 0; i < numVerts; i++) { 00297 MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); 00298 MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); 00299 if(adw && bdw) { 00300 tdw1[numIdx] = adw; 00301 tdw2[numIdx] = bdw; 00302 tidx[numIdx++] = i; 00303 } 00304 } 00305 break; 00306 case MOD_WVG_SET_ALL: 00307 default: 00308 /* Use all vertices. */ 00309 for (i = 0; i < numVerts; i++) { 00310 tdw1[i] = defvert_find_index(&dvert[i], defgrp_idx); 00311 tdw2[i] = defvert_find_index(&dvert[i], defgrp_idx2); 00312 } 00313 numIdx = -1; 00314 break; 00315 } 00316 if(numIdx == 0) { 00317 /* Use no vertices! Hence, return org data. */ 00318 MEM_freeN(tdw1); 00319 MEM_freeN(tdw2); 00320 MEM_freeN(tidx); 00321 return dm; 00322 } 00323 if (numIdx != -1) { 00324 indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGMix Modifier, indices"); 00325 memcpy(indices, tidx, sizeof(int) * numIdx); 00326 dw1 = MEM_mallocN(sizeof(MDeformWeight*) * numIdx, "WeightVGMix Modifier, dw1"); 00327 memcpy(dw1, tdw1, sizeof(MDeformWeight*) * numIdx); 00328 MEM_freeN(tdw1); 00329 dw2 = MEM_mallocN(sizeof(MDeformWeight*) * numIdx, "WeightVGMix Modifier, dw2"); 00330 memcpy(dw2, tdw2, sizeof(MDeformWeight*) * numIdx); 00331 MEM_freeN(tdw2); 00332 } 00333 else { 00334 /* Use all vertices. */ 00335 numIdx = numVerts; 00336 /* Just copy MDeformWeight pointers arrays, they will be freed at the end. */ 00337 dw1 = tdw1; 00338 dw2 = tdw2; 00339 } 00340 MEM_freeN(tidx); 00341 00342 org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, org_w"); 00343 new_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, new_w"); 00344 00345 /* Mix weights. */ 00346 for (i = 0; i < numIdx; i++) { 00347 float weight2 = 0.0; 00348 org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a; 00349 weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b; 00350 00351 new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode); 00352 } 00353 00354 /* Do masking. */ 00355 weightvg_do_mask(numIdx, indices, org_w, new_w, ob, dm, wmd->mask_constant, 00356 wmd->mask_defgrp_name, wmd->mask_texture, wmd->mask_tex_use_channel, 00357 wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); 00358 00359 /* Update (add to) vgroup. 00360 * XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup. 00361 */ 00362 weightvg_update_vg(dvert, defgrp_idx, dw1, numIdx, indices, org_w, TRUE, -FLT_MAX, FALSE, 0.0f); 00363 00364 /* Freeing stuff. */ 00365 MEM_freeN(org_w); 00366 MEM_freeN(new_w); 00367 MEM_freeN(dw1); 00368 MEM_freeN(dw2); 00369 00370 if (indices) 00371 MEM_freeN(indices); 00372 00373 /* Return the vgroup-modified mesh. */ 00374 return dm; 00375 } 00376 00377 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, 00378 struct EditMesh *UNUSED(editData), 00379 DerivedMesh *derivedData) 00380 { 00381 return applyModifier(md, ob, derivedData, 0, 1); 00382 } 00383 00384 00385 ModifierTypeInfo modifierType_WeightVGMix = { 00386 /* name */ "VertexWeightMix", 00387 /* structName */ "WeightVGMixModifierData", 00388 /* structSize */ sizeof(WeightVGMixModifierData), 00389 /* type */ eModifierTypeType_NonGeometrical, 00390 /* flags */ eModifierTypeFlag_AcceptsMesh 00391 /* |eModifierTypeFlag_SupportsMapping*/ 00392 |eModifierTypeFlag_SupportsEditmode, 00393 00394 /* copyData */ copyData, 00395 /* deformVerts */ NULL, 00396 /* deformMatrices */ NULL, 00397 /* deformVertsEM */ NULL, 00398 /* deformMatricesEM */ NULL, 00399 /* applyModifier */ applyModifier, 00400 /* applyModifierEM */ applyModifierEM, 00401 /* initData */ initData, 00402 /* requiredDataMask */ requiredDataMask, 00403 /* freeData */ NULL, 00404 /* isDisabled */ isDisabled, 00405 /* updateDepgraph */ updateDepgraph, 00406 /* dependsOnTime */ dependsOnTime, 00407 /* dependsOnNormals */ NULL, 00408 /* foreachObjectLink */ foreachObjectLink, 00409 /* foreachIDLink */ foreachIDLink, 00410 /* foreachTexLink */ foreachTexLink, 00411 };