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_math.h" 00032 #include "BLI_rand.h" 00033 #include "BLI_string.h" 00034 #include "BLI_utildefines.h" 00035 00036 #include "DNA_color_types.h" /* CurveMapping. */ 00037 #include "DNA_mesh_types.h" 00038 #include "DNA_meshdata_types.h" 00039 #include "DNA_modifier_types.h" 00040 #include "DNA_object_types.h" 00041 00042 #include "BKE_cdderivedmesh.h" 00043 #include "BKE_colortools.h" /* CurveMapping. */ 00044 #include "BKE_deform.h" 00045 #include "BKE_mesh.h" 00046 #include "BKE_modifier.h" 00047 #include "BKE_texture.h" /* Texture masking. */ 00048 00049 #include "depsgraph_private.h" 00050 #include "MEM_guardedalloc.h" 00051 #include "MOD_util.h" 00052 #include "MOD_weightvg_util.h" 00053 #include "RE_shader_ext.h" /* Texture masking. */ 00054 00055 /* Maps new_w weights in place, using either one of the predifined functions, or a custom curve. 00056 * Return values are in new_w. 00057 * If indices is not NULL, it must be a table of same length as org_w and new_w, mapping to the real 00058 * vertex index (in case the weight tables do not cover the whole vertices...). 00059 * cmap might be NULL, in which case curve mapping mode will return unmodified data. 00060 */ 00061 void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cmap) 00062 { 00063 int i; 00064 00065 /* Return immediately, if we have nothing to do! */ 00066 /* Also security checks... */ 00067 if(((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) 00068 || !ELEM7(falloff_type, MOD_WVG_MAPPING_CURVE, MOD_WVG_MAPPING_SHARP, MOD_WVG_MAPPING_SMOOTH, 00069 MOD_WVG_MAPPING_ROOT, MOD_WVG_MAPPING_SPHERE, MOD_WVG_MAPPING_RANDOM, 00070 MOD_WVG_MAPPING_STEP)) 00071 return; 00072 00073 /* Map each weight (vertex) to its new value, accordingly to the chosen mode. */ 00074 for(i = 0; i < num; ++i) { 00075 float fac = new_w[i]; 00076 00077 /* Code borrowed from the warp modifier. */ 00078 /* Closely matches PROP_SMOOTH and similar. */ 00079 switch(falloff_type) { 00080 case MOD_WVG_MAPPING_CURVE: 00081 fac = curvemapping_evaluateF(cmap, 0, fac); 00082 break; 00083 case MOD_WVG_MAPPING_SHARP: 00084 fac = fac*fac; 00085 break; 00086 case MOD_WVG_MAPPING_SMOOTH: 00087 fac = 3.0f*fac*fac - 2.0f*fac*fac*fac; 00088 break; 00089 case MOD_WVG_MAPPING_ROOT: 00090 fac = (float)sqrt(fac); 00091 break; 00092 case MOD_WVG_MAPPING_SPHERE: 00093 fac = (float)sqrt(2*fac - fac * fac); 00094 break; 00095 case MOD_WVG_MAPPING_RANDOM: 00096 BLI_srand(BLI_rand()); /* random seed */ 00097 fac = BLI_frand()*fac; 00098 break; 00099 case MOD_WVG_MAPPING_STEP: 00100 fac = (fac >= 0.5f)?1.0f:0.0f; 00101 break; 00102 } 00103 00104 new_w[i] = fac; 00105 } 00106 } 00107 00108 /* Applies new_w weights to org_w ones, using either a texture, vgroup or constant value as factor. 00109 * Return values are in org_w. 00110 * If indices is not NULL, it must be a table of same length as org_w and new_w, mapping to the real 00111 * vertex index (in case the weight tables do not cover the whole vertices...). 00112 * XXX The standard “factor” value is assumed in [0.0, 1.0] range. Else, weird results might appear. 00113 */ 00114 void weightvg_do_mask(int num, const int *indices, float *org_w, const float *new_w, 00115 Object *ob, DerivedMesh *dm, float fact, const char defgrp_name[MAX_VGROUP_NAME], 00116 Tex *texture, int tex_use_channel, int tex_mapping, 00117 Object *tex_map_object, const char *tex_uvlayer_name) 00118 { 00119 int ref_didx; 00120 int i; 00121 00122 /* If influence factor is null, nothing to do! */ 00123 if (fact == 0.0f) return; 00124 00125 /* If we want to mask vgroup weights from a texture. */ 00126 if (texture) { 00127 /* The texture coordinates. */ 00128 float (*tex_co)[3]; 00129 /* See mapping note below... */ 00130 MappingInfoModifierData t_map; 00131 float (*v_co)[3]; 00132 00133 /* Use new generic get_texture_coords, but do not modify our DNA struct for it... 00134 * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters ? 00135 * What e.g. if a modifier wants to use several textures ? 00136 * Why use only v_co, and not MVert (or both) ? 00137 */ 00138 t_map.texture = texture; 00139 t_map.map_object = tex_map_object; 00140 BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name)); 00141 t_map.texmapping = tex_mapping; 00142 v_co = MEM_mallocN(sizeof(*v_co) * num, "WeightVG Modifier, TEX mode, v_co"); 00143 dm->getVertCos(dm, v_co); 00144 tex_co = MEM_callocN(sizeof(*tex_co) * num, "WeightVG Modifier, TEX mode, tex_co"); 00145 get_texture_coords(&t_map, ob, dm, v_co, tex_co, num); 00146 MEM_freeN(v_co); 00147 00148 /* For each weight (vertex), make the mix between org and new weights. */ 00149 for(i = 0; i < num; ++i) { 00150 int idx = indices ? indices[i] : i; 00151 TexResult texres; 00152 float h, s, v; /* For HSV color space. */ 00153 00154 texres.nor = NULL; 00155 get_texture_value(texture, tex_co[idx], &texres); 00156 /* Get the good channel value... */ 00157 switch(tex_use_channel) { 00158 case MOD_WVG_MASK_TEX_USE_INT: 00159 org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin*fact))); 00160 break; 00161 case MOD_WVG_MASK_TEX_USE_RED: 00162 org_w[i] = (new_w[i] * texres.tr * fact) + (org_w[i] * (1.0f - (texres.tr*fact))); 00163 break; 00164 case MOD_WVG_MASK_TEX_USE_GREEN: 00165 org_w[i] = (new_w[i] * texres.tg * fact) + (org_w[i] * (1.0f - (texres.tg*fact))); 00166 break; 00167 case MOD_WVG_MASK_TEX_USE_BLUE: 00168 org_w[i] = (new_w[i] * texres.tb * fact) + (org_w[i] * (1.0f - (texres.tb*fact))); 00169 break; 00170 case MOD_WVG_MASK_TEX_USE_HUE: 00171 rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v); 00172 org_w[i] = (new_w[i] * h * fact) + (org_w[i] * (1.0f - (h*fact))); 00173 break; 00174 case MOD_WVG_MASK_TEX_USE_SAT: 00175 rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v); 00176 org_w[i] = (new_w[i] * s * fact) + (org_w[i] * (1.0f - (s*fact))); 00177 break; 00178 case MOD_WVG_MASK_TEX_USE_VAL: 00179 rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v); 00180 org_w[i] = (new_w[i] * v * fact) + (org_w[i] * (1.0f - (v*fact))); 00181 break; 00182 case MOD_WVG_MASK_TEX_USE_ALPHA: 00183 org_w[i] = (new_w[i] * texres.ta * fact) + (org_w[i] * (1.0f - (texres.ta*fact))); 00184 break; 00185 default: 00186 org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin*fact))); 00187 break; 00188 } 00189 } 00190 00191 MEM_freeN(tex_co); 00192 } 00193 else if ((ref_didx = defgroup_name_index(ob, defgrp_name)) != -1) { 00194 MDeformVert *dvert = NULL; 00195 00196 /* Check whether we want to set vgroup weights from a constant weight factor or a vertex 00197 * group. 00198 */ 00199 /* Get vgroup idx from its name. */ 00200 00201 /* Proceed only if vgroup is valid, else use constant factor. */ 00202 /* Get actual dverts (ie vertex group data). */ 00203 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); 00204 /* Proceed only if vgroup is valid, else assume factor = O. */ 00205 if (dvert == NULL) return; 00206 00207 /* For each weight (vertex), make the mix between org and new weights. */ 00208 for (i = 0; i < num; i++) { 00209 int idx = indices ? indices[i] : i; 00210 const float f = defvert_find_weight(&dvert[idx], ref_didx) * fact; 00211 org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f-f)); 00212 /* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */ 00213 } 00214 } 00215 else { 00216 /* Default "influence" behavior. */ 00217 /* For each weight (vertex), make the mix between org and new weights. */ 00218 const float ifact = 1.0f - fact; 00219 for (i = 0; i < num; i++) { 00220 org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact); 00221 } 00222 } 00223 } 00224 00225 00226 00227 00228 /* Applies weights to given vgroup (defgroup), and optionnaly add/remove vertices from the group. 00229 * If dws is not NULL, it must be an array of MDeformWeight pointers of same length as weights (and 00230 * defgrp_idx can then have any value). 00231 * If indices is not NULL, it must be an array of same length as weights, mapping to the real 00232 * vertex index (in case the weight array does not cover the whole vertices...). 00233 */ 00234 void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, MDeformWeight **dws, int num, 00235 const int *indices, const float *weights, int do_add, 00236 float add_thresh, int do_rem, float rem_thresh) 00237 { 00238 int i; 00239 00240 for(i = 0; i < num; i++) { 00241 float w = weights[i]; 00242 MDeformVert *dv = &dvert[indices ? indices[i] : i]; 00243 MDeformWeight *dw = dws ? dws[i] : defvert_find_index(dv, defgrp_idx); 00244 00245 /* Never allow weights out of [0.0, 1.0] range. */ 00246 CLAMP(w, 0.0f, 1.0f); 00247 00248 /* If the vertex is in this vgroup, remove it if needed, or just update it. */ 00249 if(dw != NULL) { 00250 if(do_rem && w < rem_thresh) { 00251 defvert_remove_group(dv, dw); 00252 } 00253 else { 00254 dw->weight = w; 00255 } 00256 } 00257 /* Else, add it if needed! */ 00258 else if(do_add && w > add_thresh) { 00259 defvert_add_index_notest(dv, defgrp_idx, w); 00260 } 00261 } 00262 }