static void waveModifier_do(WaveModifierData *md, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { WaveModifierData *wmd = (WaveModifierData*) md; MVert *mvert = NULL; MDeformVert *dvert = NULL; int defgrp_index; float ctime = BKE_curframe(scene); float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow)); float lifefac = wmd->height; float (*tex_co)[3] = NULL; if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH) mvert = dm->getVertArray(dm); if(wmd->objectcenter){ float mat[4][4]; /* get the control object's location in local coordinates */ invert_m4_m4(ob->imat, ob->obmat); mul_m4_m4m4(mat, wmd->objectcenter->obmat, ob->imat); wmd->startx = mat[3][0]; wmd->starty = mat[3][1]; } /* get the index of the deform group */ defgrp_index = defgroup_name_index(ob, wmd->defgrp_name); if(defgrp_index >= 0){ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); } if(wmd->damp == 0) wmd->damp = 10.0f; if(wmd->lifetime != 0.0) { float x = ctime - wmd->timeoffs; if(x > wmd->lifetime) { lifefac = x - wmd->lifetime; if(lifefac > wmd->damp) lifefac = 0.0; else lifefac = (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp))); } } if(wmd->texture) { tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "waveModifier_do tex_co"); wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts); } if(lifefac != 0.0) { /* avoid divide by zero checks within the loop */ float falloff_inv= wmd->falloff ? 1.0f / wmd->falloff : 1.0; int i; for(i = 0; i < numVerts; i++) { float *co = vertexCos[i]; float x = co[0] - wmd->startx; float y = co[1] - wmd->starty; float amplit= 0.0f; float dist = 0.0f; float falloff_fac = 0.0f; TexResult texres; MDeformWeight *def_weight = NULL; /* get weights */ if(dvert) { int j; for(j = 0; j < dvert[i].totweight; ++j) { if(dvert[i].dw[j].def_nr == defgrp_index) { def_weight = &dvert[i].dw[j]; break; } } /* if this vert isn't in the vgroup, don't deform it */ if(!def_weight) continue; } if(wmd->texture) { texres.nor = NULL; get_texture_value(wmd->texture, tex_co[i], &texres); } /*get dist*/ if(wmd->flag & MOD_WAVE_X) { if(wmd->flag & MOD_WAVE_Y){ dist = (float)sqrt(x*x + y*y); } else{ dist = fabs(x); } } else if(wmd->flag & MOD_WAVE_Y) { dist = fabs(y); } falloff_fac = (1.0f - (dist * falloff_inv)); if(wmd->flag & MOD_WAVE_X) { if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y); else amplit = x; } else if(wmd->flag & MOD_WAVE_Y) amplit= y; /* this way it makes nice circles */ amplit -= (ctime - wmd->timeoffs) * wmd->speed; if(wmd->flag & MOD_WAVE_CYCL) { amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width) + wmd->width; } /* GAUSSIAN */ if(amplit > -wmd->width && amplit < wmd->width) { amplit = amplit * wmd->narrow; amplit = (float)(1.0 / exp(amplit * amplit) - minfac); /*apply texture*/ if(wmd->texture) amplit = amplit * texres.tin; /*apply weight*/ if(def_weight) amplit = amplit * def_weight->weight; /*apply falloff*/ if (wmd->falloff > 0) amplit = amplit * falloff_fac; if(mvert) { /* move along normals */ if(wmd->flag & MOD_WAVE_NORM_X) { co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f; } if(wmd->flag & MOD_WAVE_NORM_Y) { co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f; } if(wmd->flag & MOD_WAVE_NORM_Z) { co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f; } } else { /* move along local z axis */ co[2] += lifefac * amplit; } } } } if(wmd->texture) MEM_freeN(tex_co); }
static void waveModifier_do(WaveModifierData *md, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { WaveModifierData *wmd = (WaveModifierData*) md; MVert *mvert = NULL; MDeformVert *dvert; int defgrp_index; float ctime = BKE_curframe(scene); float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow)); float lifefac = wmd->height; float (*tex_co)[3] = NULL; const int wmd_axis= wmd->flag & (MOD_WAVE_X|MOD_WAVE_Y); const float falloff= wmd->falloff; float falloff_fac= 1.0f; /* when falloff == 0.0f this stays at 1.0f */ if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH) mvert = dm->getVertArray(dm); if(wmd->objectcenter){ float mat[4][4]; /* get the control object's location in local coordinates */ invert_m4_m4(ob->imat, ob->obmat); mul_m4_m4m4(mat, wmd->objectcenter->obmat, ob->imat); wmd->startx = mat[3][0]; wmd->starty = mat[3][1]; } /* get the index of the deform group */ modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index); if(wmd->damp == 0) wmd->damp = 10.0f; if(wmd->lifetime != 0.0f) { float x = ctime - wmd->timeoffs; if(x > wmd->lifetime) { lifefac = x - wmd->lifetime; if(lifefac > wmd->damp) lifefac = 0.0; else lifefac = (float)(wmd->height * (1.0f - sqrtf(lifefac / wmd->damp))); } } if(wmd->texture) { tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "waveModifier_do tex_co"); wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts); } if(lifefac != 0.0f) { /* avoid divide by zero checks within the loop */ float falloff_inv= falloff ? 1.0f / falloff : 1.0f; int i; for(i = 0; i < numVerts; i++) { float *co = vertexCos[i]; float x = co[0] - wmd->startx; float y = co[1] - wmd->starty; float amplit= 0.0f; float def_weight= 1.0f; /* get weights */ if(dvert) { def_weight= defvert_find_weight(&dvert[i], defgrp_index); /* if this vert isn't in the vgroup, don't deform it */ if(def_weight == 0.0f) { continue; } } switch(wmd_axis) { case MOD_WAVE_X|MOD_WAVE_Y: amplit = sqrtf(x*x + y*y); break; case MOD_WAVE_X: amplit = x; break; case MOD_WAVE_Y: amplit = y; break; } /* this way it makes nice circles */ amplit -= (ctime - wmd->timeoffs) * wmd->speed; if(wmd->flag & MOD_WAVE_CYCL) { amplit = (float)fmodf(amplit - wmd->width, 2.0f * wmd->width) + wmd->width; } if(falloff != 0.0f) { float dist = 0.0f; switch(wmd_axis) { case MOD_WAVE_X|MOD_WAVE_Y: dist = sqrtf(x*x + y*y); break; case MOD_WAVE_X: dist = fabsf(x); break; case MOD_WAVE_Y: dist = fabsf(y); break; } falloff_fac = (1.0f - (dist * falloff_inv)); CLAMP(falloff_fac, 0.0f, 1.0f); } /* GAUSSIAN */ if((falloff_fac != 0.0f) && (amplit > -wmd->width) && (amplit < wmd->width)) { amplit = amplit * wmd->narrow; amplit = (float)(1.0f / expf(amplit * amplit) - minfac); /*apply texture*/ if(wmd->texture) { TexResult texres; texres.nor = NULL; get_texture_value(wmd->texture, tex_co[i], &texres); amplit *= texres.tin; } /*apply weight & falloff */ amplit *= def_weight * falloff_fac; if(mvert) { /* move along normals */ if(wmd->flag & MOD_WAVE_NORM_X) { co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f; } if(wmd->flag & MOD_WAVE_NORM_Y) { co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f; } if(wmd->flag & MOD_WAVE_NORM_Z) { co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f; } } else { /* move along local z axis */ co[2] += lifefac * amplit; } } } } if(wmd->texture) MEM_freeN(tex_co); }
static void warpModifier_do(WarpModifierData *wmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { float obinv[4][4]; float mat_from[4][4]; float mat_from_inv[4][4]; float mat_to[4][4]; float mat_unit[4][4]; float mat_final[4][4]; float tmat[4][4]; float strength = wmd->strength; float fac = 1.0f, weight; int i; int defgrp_index; MDeformVert *dvert, *dv = NULL; float (*tex_co)[3] = NULL; if (!(wmd->object_from && wmd->object_to)) return; modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index); if (wmd->curfalloff == NULL) /* should never happen, but bad lib linking could cause it */ wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); if (wmd->curfalloff) { curvemapping_initialize(wmd->curfalloff); } invert_m4_m4(obinv, ob->obmat); mul_m4_m4m4(mat_from, obinv, wmd->object_from->obmat); mul_m4_m4m4(mat_to, obinv, wmd->object_to->obmat); invert_m4_m4(tmat, mat_from); // swap? mul_m4_m4m4(mat_final, tmat, mat_to); invert_m4_m4(mat_from_inv, mat_from); unit_m4(mat_unit); if (strength < 0.0f) { float loc[3]; strength = -strength; /* inverted location is not useful, just use the negative */ copy_v3_v3(loc, mat_final[3]); invert_m4(mat_final); negate_v3_v3(mat_final[3], loc); } weight = strength; if (wmd->texture) { tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "warpModifier_do tex_co"); get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts); modifier_init_texture(wmd->modifier.scene, wmd->texture); } for (i = 0; i < numVerts; i++) { float *co = vertexCos[i]; if (wmd->falloff_type == eWarp_Falloff_None || ((fac = len_v3v3(co, mat_from[3])) < wmd->falloff_radius && (fac = (wmd->falloff_radius - fac) / wmd->falloff_radius))) { /* skip if no vert group found */ if (dvert && defgrp_index != -1) { dv = &dvert[i]; if (dv) { weight = defvert_find_weight(dv, defgrp_index) * strength; if (weight <= 0.0f) /* Should never occure... */ continue; } } /* closely match PROP_SMOOTH and similar */ switch (wmd->falloff_type) { case eWarp_Falloff_None: fac = 1.0f; break; case eWarp_Falloff_Curve: fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac); break; case eWarp_Falloff_Sharp: fac = fac * fac; break; case eWarp_Falloff_Smooth: fac = 3.0f * fac * fac - 2.0f * fac * fac * fac; break; case eWarp_Falloff_Root: fac = (float)sqrt(fac); break; case eWarp_Falloff_Linear: /* pass */ break; case eWarp_Falloff_Const: fac = 1.0f; break; case eWarp_Falloff_Sphere: fac = (float)sqrt(2 * fac - fac * fac); break; } fac *= weight; if (tex_co) { TexResult texres; texres.nor = NULL; get_texture_value(wmd->modifier.scene, wmd->texture, tex_co[i], &texres, false); fac *= texres.tin; } /* into the 'from' objects space */ mul_m4_v3(mat_from_inv, co); if (fac >= 1.0f) { mul_m4_v3(mat_final, co); } else if (fac > 0.0f) { if (wmd->flag & MOD_WARP_VOLUME_PRESERVE) { /* interpolate the matrix for nicer locations */ blend_m4_m4m4(tmat, mat_unit, mat_final, fac); mul_m4_v3(tmat, co); } else { float tvec[3]; mul_v3_m4v3(tvec, mat_final, co); interp_v3_v3v3(co, co, tvec, fac); } } /* out of the 'from' objects space */ mul_m4_v3(mat_from, co); } } if (tex_co) MEM_freeN(tex_co); }
/* Applies new_w weights to org_w ones, using either a texture, vgroup or constant value as factor. * Return values are in org_w. * If indices is not NULL, it must be a table of same length as org_w and new_w, mapping to the real * vertex index (in case the weight tables do not cover the whole vertices...). * XXX The standard “factor” value is assumed in [0.0, 1.0] range. Else, weird results might appear. */ void weightvg_do_mask(int num, const int *indices, float *org_w, const float *new_w, Object *ob, DerivedMesh *dm, float fact, const char defgrp_name[32], Tex *texture, int tex_use_channel, int tex_mapping, Object *tex_map_object, const char *tex_uvlayer_name) { int ref_didx; int i; /* If influence factor is null, nothing to do! */ if (fact == 0.0f) return; /* If we want to mask vgroup weights from a texture. */ if (texture) { /* The texture coordinates. */ float (*tex_co)[3]; /* See mapping note below... */ MappingInfoModifierData t_map; float (*v_co)[3]; /* Use new generic get_texture_coords, but do not modify our DNA struct for it... * XXX Why use a ModifierData stuff here ? Why not a simple, generic struct for parameters ? * What e.g. if a modifier wants to use several textures ? * Why use only v_co, and not MVert (or both) ? */ t_map.texture = texture; t_map.map_object = tex_map_object; BLI_strncpy(t_map.uvlayer_name, tex_uvlayer_name, sizeof(t_map.uvlayer_name)); t_map.texmapping = tex_mapping; v_co = MEM_mallocN(sizeof(*v_co) * num, "WeightVG Modifier, TEX mode, v_co"); dm->getVertCos(dm, v_co); tex_co = MEM_callocN(sizeof(*tex_co) * num, "WeightVG Modifier, TEX mode, tex_co"); get_texture_coords(&t_map, ob, dm, v_co, tex_co, num); MEM_freeN(v_co); /* For each weight (vertex), make the mix between org and new weights. */ for(i = 0; i < num; ++i) { int idx = indices ? indices[i] : i; TexResult texres; float h, s, v; /* For HSV color space. */ texres.nor = NULL; get_texture_value(texture, tex_co[idx], &texres); /* Get the good channel value... */ switch(tex_use_channel) { case MOD_WVG_MASK_TEX_USE_INT: org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin*fact))); break; case MOD_WVG_MASK_TEX_USE_RED: org_w[i] = (new_w[i] * texres.tr * fact) + (org_w[i] * (1.0f - (texres.tr*fact))); break; case MOD_WVG_MASK_TEX_USE_GREEN: org_w[i] = (new_w[i] * texres.tg * fact) + (org_w[i] * (1.0f - (texres.tg*fact))); break; case MOD_WVG_MASK_TEX_USE_BLUE: org_w[i] = (new_w[i] * texres.tb * fact) + (org_w[i] * (1.0f - (texres.tb*fact))); break; case MOD_WVG_MASK_TEX_USE_HUE: rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v); org_w[i] = (new_w[i] * h * fact) + (org_w[i] * (1.0f - (h*fact))); break; case MOD_WVG_MASK_TEX_USE_SAT: rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v); org_w[i] = (new_w[i] * s * fact) + (org_w[i] * (1.0f - (s*fact))); break; case MOD_WVG_MASK_TEX_USE_VAL: rgb_to_hsv(texres.tr, texres.tg, texres.tb, &h, &s, &v); org_w[i] = (new_w[i] * v * fact) + (org_w[i] * (1.0f - (v*fact))); break; case MOD_WVG_MASK_TEX_USE_ALPHA: org_w[i] = (new_w[i] * texres.ta * fact) + (org_w[i] * (1.0f - (texres.ta*fact))); break; default: org_w[i] = (new_w[i] * texres.tin * fact) + (org_w[i] * (1.0f - (texres.tin*fact))); break; } } MEM_freeN(tex_co); } else if ((ref_didx = defgroup_name_index(ob, defgrp_name)) != -1) { MDeformVert *dvert = NULL; /* Check whether we want to set vgroup weights from a constant weight factor or a vertex * group. */ /* Get vgroup idx from its name. */ /* Proceed only if vgroup is valid, else use constant factor. */ /* Get actual dverts (ie vertex group data). */ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* Proceed only if vgroup is valid, else assume factor = O. */ if (dvert == NULL) return; /* For each weight (vertex), make the mix between org and new weights. */ for (i = 0; i < num; i++) { int idx = indices ? indices[i] : i; const float f = defvert_find_weight(&dvert[idx], ref_didx) * fact; org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f-f)); /* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */ } } else { /* Default "influence" behavior. */ /* For each weight (vertex), make the mix between org and new weights. */ const float ifact = 1.0f - fact; for (i = 0; i < num; i++) { org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact); } } }
/* dm must be a CDDerivedMesh */ static void displaceModifier_do( DisplaceModifierData *dmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { int i; MVert *mvert; MDeformVert *dvert; int defgrp_index; float (*tex_co)[3]; float weight = 1.0f; /* init value unused but some compilers may complain */ const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */ if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return; if (dmd->strength == 0.0f) return; mvert = CDDM_get_verts(dm); modifier_get_vgroup(ob, dm, dmd->defgrp_name, &dvert, &defgrp_index); if (dmd->texture) { tex_co = MEM_callocN(sizeof(*tex_co) * numVerts, "displaceModifier_do tex_co"); get_texture_coords((MappingInfoModifierData *)dmd, ob, dm, vertexCos, tex_co, numVerts); modifier_init_texture(dmd->modifier.scene, dmd->texture); } else { tex_co = NULL; } for (i = 0; i < numVerts; i++) { TexResult texres; float strength = dmd->strength; float delta; if (dvert) { weight = defvert_find_weight(dvert + i, defgrp_index); if (weight == 0.0f) continue; } if (dmd->texture) { texres.nor = NULL; get_texture_value(dmd->modifier.scene, dmd->texture, tex_co[i], &texres, false); delta = texres.tin - dmd->midlevel; } else { delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */ } if (dvert) strength *= weight; delta *= strength; CLAMP(delta, -10000, 10000); switch (dmd->direction) { case MOD_DISP_DIR_X: vertexCos[i][0] += delta; break; case MOD_DISP_DIR_Y: vertexCos[i][1] += delta; break; case MOD_DISP_DIR_Z: vertexCos[i][2] += delta; break; case MOD_DISP_DIR_RGB_XYZ: vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength; vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength; vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength; break; case MOD_DISP_DIR_NOR: vertexCos[i][0] += delta * (mvert[i].no[0] / 32767.0f); vertexCos[i][1] += delta * (mvert[i].no[1] / 32767.0f); vertexCos[i][2] += delta * (mvert[i].no[2] / 32767.0f); break; } } if (tex_co) { MEM_freeN(tex_co); } }