forked from bartvdbraak/blender
WeightVG utils, weightvg_update_vg func updates.
* Added an optional array of MDeformModifier pointers, to avoid another search based on defgrp_idx. * Split out "add/remove verts from vgroup" functions, preparing their move to deform.c (if their current form is validated!).
This commit is contained in:
parent
41e5040e2f
commit
2f50579d9a
@ -212,7 +212,7 @@ void weightvg_do_mask(int num, const int *indices, float *org_w, const float *ne
|
|||||||
/* For each weight (vertex), make the mix between org and new weights. */
|
/* For each weight (vertex), make the mix between org and new weights. */
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
int idx = indices ? indices[i] : i;
|
int idx = indices ? indices[i] : i;
|
||||||
const float f= defvert_find_weight(&dvert[idx], ref_didx) * fact;
|
const float f = defvert_find_weight(&dvert[idx], ref_didx) * fact;
|
||||||
org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f-f));
|
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! */
|
/* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */
|
||||||
}
|
}
|
||||||
@ -220,87 +220,107 @@ void weightvg_do_mask(int num, const int *indices, float *org_w, const float *ne
|
|||||||
else {
|
else {
|
||||||
/* Default "influence" behavior. */
|
/* Default "influence" behavior. */
|
||||||
/* For each weight (vertex), make the mix between org and new weights. */
|
/* For each weight (vertex), make the mix between org and new weights. */
|
||||||
const float ifact= 1.0f - fact;
|
const float ifact = 1.0f - fact;
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact);
|
org_w[i] = (new_w[i] * fact) + (org_w[i] * ifact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Adds the given vertex to the specified vertex group, with given weight. */
|
||||||
|
void defvert_add_to_group(MDeformVert *dv, int defgrp_idx, const float weight) {
|
||||||
|
/* TODO, move into deform.c as a generic function. This assumes the vertex
|
||||||
|
* groups have already been checked, so this has to remain low level. */
|
||||||
|
MDeformWeight *newdw;
|
||||||
|
|
||||||
|
newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "defvert_add_to group, new deformWeight");
|
||||||
|
if(dv->dw) {
|
||||||
|
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
|
||||||
|
MEM_freeN(dv->dw);
|
||||||
|
}
|
||||||
|
dv->dw = newdw;
|
||||||
|
dv->dw[dv->totweight].weight = weight;
|
||||||
|
dv->dw[dv->totweight].def_nr = defgrp_idx;
|
||||||
|
dv->totweight++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Removes the given vertex from the vertex group, specified either by its defgrp_idx,
|
||||||
|
* or directly by its MDeformWeight pointer, if dw is not NULL.
|
||||||
|
* WARNING: This function frees the given MDeformWeight, do not use it afterward! */
|
||||||
|
void defvert_remove_from_group(MDeformVert *dv, int defgrp_idx, MDeformWeight *dw) {
|
||||||
|
/* TODO, move this into deform.c as a generic function. */
|
||||||
|
MDeformWeight *newdw;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Get index of removed MDeformWeight. */
|
||||||
|
if(dw == NULL) {
|
||||||
|
dw = dv->dw;
|
||||||
|
for (i = dv->totweight; i > 0; i--, dw++) {
|
||||||
|
if (dw->def_nr == defgrp_idx)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i = dw - dv->dw;
|
||||||
|
/* Security check! */
|
||||||
|
if(i < 0 || i >= dv->totweight)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv->totweight--;
|
||||||
|
/* If there are still other deform weights attached to this vert then remove
|
||||||
|
* this deform weight, and reshuffle the others.
|
||||||
|
*/
|
||||||
|
if(dv->totweight) {
|
||||||
|
newdw = MEM_mallocN(sizeof(MDeformWeight)*(dv->totweight), "defvert_remove_from_group, new deformWeight");
|
||||||
|
if(dv->dw){
|
||||||
|
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*i);
|
||||||
|
memcpy(newdw+i, dv->dw+i+1, sizeof(MDeformWeight)*(dv->totweight-i));
|
||||||
|
MEM_freeN(dv->dw);
|
||||||
|
}
|
||||||
|
dv->dw = newdw;
|
||||||
|
}
|
||||||
|
/* If there are no other deform weights left then just remove this one. */
|
||||||
|
else {
|
||||||
|
MEM_freeN(dv->dw);
|
||||||
|
dv->dw = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Applies weights to given vgroup (defgroup), and optionnaly add/remove vertices from the group.
|
/* Applies weights to given vgroup (defgroup), and optionnaly add/remove vertices from the group.
|
||||||
* If indices is not NULL, it must be a table of same length as weights, mapping to the real
|
* If dws is not NULL, it must be an array of MDeformWeight pointers of same length as weights (and
|
||||||
* vertex index (in case the weight table does not cover the whole vertices...).
|
* defgrp_idx can then have any value).
|
||||||
|
* If indices is not NULL, it must be an array of same length as weights, mapping to the real
|
||||||
|
* vertex index (in case the weight array does not cover the whole vertices...).
|
||||||
*/
|
*/
|
||||||
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, int num,
|
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, MDeformWeight **dws, int num,
|
||||||
const int *indices, const float *weights, int do_add,
|
const int *indices, const float *weights, int do_add,
|
||||||
float add_thresh, int do_rem, float rem_thresh)
|
float add_thresh, int do_rem, float rem_thresh)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
for(i = 0; i < num; i++) {
|
||||||
int j;
|
|
||||||
int add2vg = do_add;
|
|
||||||
float w = weights[i];
|
float w = weights[i];
|
||||||
MDeformVert *dv = &dvert[indices ? indices[i] : i];
|
MDeformVert *dv = &dvert[indices ? indices[i] : i];
|
||||||
MDeformWeight *newdw;
|
MDeformWeight *dw = dws ? dws[i] : defvert_find_index(dv, defgrp_idx);
|
||||||
|
|
||||||
/* Never allow weights out of [0.0, 1.0] range. */
|
/* Never allow weights out of [0.0, 1.0] range. */
|
||||||
CLAMP(w, 0.0f, 1.0f);
|
CLAMP(w, 0.0f, 1.0f);
|
||||||
|
|
||||||
/* Let's first check to see if this vert is already in the weight group – if so
|
/* If the vertex is in this vgroup, remove it if needed, or just update it. */
|
||||||
* let's update it, or remove it if needed.
|
if(dw != NULL) {
|
||||||
*/
|
if(do_rem && w < rem_thresh) {
|
||||||
for (j = 0; j < dv->totweight; j++) {
|
defvert_remove_from_group(dv, defgrp_idx, dw);
|
||||||
/* If this weight corresponds to the deform group, update the value or,
|
}
|
||||||
* if lower than rem_threshold, remove the vertex from the vgroup.
|
else {
|
||||||
*/
|
dw->weight = w;
|
||||||
if (dv->dw[j].def_nr == defgrp_idx) {
|
|
||||||
/* Remove the vertex from this vgroup if needed. */
|
|
||||||
if (do_rem && w < rem_thresh) {
|
|
||||||
/* TODO, move this into deform.c to make into a generic function */
|
|
||||||
|
|
||||||
dv->totweight--;
|
|
||||||
/* If there are still other deform weights attached to this vert then remove
|
|
||||||
* this deform weight, and reshuffle the others.
|
|
||||||
*/
|
|
||||||
if(dv->totweight) {
|
|
||||||
newdw = MEM_mallocN(sizeof(MDeformWeight)*(dv->totweight), "deformWeight");
|
|
||||||
if(dv->dw){
|
|
||||||
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*j);
|
|
||||||
memcpy(newdw+j, dv->dw+j+1, sizeof(MDeformWeight)*(dv->totweight-j));
|
|
||||||
MEM_freeN(dv->dw);
|
|
||||||
}
|
|
||||||
dv->dw = newdw;
|
|
||||||
}
|
|
||||||
/* If there are no other deform weights left then just remove this one. */
|
|
||||||
else {
|
|
||||||
MEM_freeN(dv->dw);
|
|
||||||
dv->dw = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Else, just set the new computed weight. */
|
|
||||||
else {
|
|
||||||
dv->dw[j].weight = w;
|
|
||||||
}
|
|
||||||
add2vg = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Else, add it if needed! */
|
||||||
/* If the vert wasn't in the deform group, add it if needed!
|
else if(do_add && w > add_thresh) {
|
||||||
*/
|
defvert_add_to_group(dv, defgrp_idx, w);
|
||||||
if ((add2vg == TRUE) && w > add_thresh) {
|
|
||||||
/* TODO, mvoe into deform.c and make into a generic function, this assumes the vertex
|
|
||||||
* groups have already been checked, so this has to remain low level */
|
|
||||||
newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "WeightVGEdit Modifier, deformWeight");
|
|
||||||
if(dv->dw) {
|
|
||||||
memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
|
|
||||||
MEM_freeN(dv->dw);
|
|
||||||
}
|
|
||||||
dv->dw = newdw;
|
|
||||||
dv->dw[dv->totweight].weight = w;
|
|
||||||
dv->dw[dv->totweight].def_nr = defgrp_idx;
|
|
||||||
dv->totweight++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ void weightvg_do_mask(int num, const int *indices, float *org_w, const float *ne
|
|||||||
* If indices is not NULL, it must be a table of same length as weights, mapping to the real
|
* If indices is not NULL, it must be a table of same length as weights, mapping to the real
|
||||||
* vertex index (in case the weight table does not cover the whole vertices...).
|
* vertex index (in case the weight table does not cover the whole vertices...).
|
||||||
*/
|
*/
|
||||||
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, int num,
|
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, MDeformWeight **dws, int num,
|
||||||
const int *indices, const float *weights, int do_add,
|
const int *indices, const float *weights, int do_add,
|
||||||
float add_thresh, int do_rem, float rem_thresh);
|
float add_thresh, int do_rem, float rem_thresh);
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
|
|||||||
wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
|
wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
|
||||||
|
|
||||||
/* Update/add/remove from vgroup. */
|
/* Update/add/remove from vgroup. */
|
||||||
weightvg_update_vg(dvert, defgrp_idx, numVerts, NULL, org_w, do_add, wmd->add_threshold,
|
weightvg_update_vg(dvert, defgrp_idx, NULL, numVerts, NULL, org_w, do_add, wmd->add_threshold,
|
||||||
do_rem, wmd->rem_threshold);
|
do_rem, wmd->rem_threshold);
|
||||||
|
|
||||||
/* Freeing stuff. */
|
/* Freeing stuff. */
|
||||||
|
@ -412,7 +412,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
|
|||||||
/* Update (add to) vgroup.
|
/* Update (add to) vgroup.
|
||||||
* XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup.
|
* XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup.
|
||||||
*/
|
*/
|
||||||
weightvg_update_vg(dvert, defgrp_idx, numIdx, indices, org_w, TRUE, -FLT_MAX, 0, 0.0f);
|
weightvg_update_vg(dvert, defgrp_idx, dw1, numIdx, indices, org_w, TRUE, -FLT_MAX, 0, 0.0f);
|
||||||
|
|
||||||
/* Freeing stuff. */
|
/* Freeing stuff. */
|
||||||
MEM_freeN(org_w);
|
MEM_freeN(org_w);
|
||||||
|
@ -508,7 +508,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
|
|||||||
wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
|
wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name);
|
||||||
|
|
||||||
/* Update vgroup. Note we never add nor remove vertices from vgroup here. */
|
/* Update vgroup. Note we never add nor remove vertices from vgroup here. */
|
||||||
weightvg_update_vg(dvert, defgrp_idx, numIdx, indices, org_w, 0, 0.0f, 0, 0.0f);
|
weightvg_update_vg(dvert, defgrp_idx, NULL, numIdx, indices, org_w, 0, 0.0f, 0, 0.0f);
|
||||||
|
|
||||||
/* Freeing stuff. */
|
/* Freeing stuff. */
|
||||||
MEM_freeN(org_w);
|
MEM_freeN(org_w);
|
||||||
|
Loading…
Reference in New Issue
Block a user