static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; DerivedMesh *dm = derivedData; MDeformVert *dvert = NULL; MDeformWeight **dw1, **tdw1, **dw2, **tdw2; int numVerts; int defgrp_idx, defgrp_idx2 = -1; float *org_w; float *new_w; int *tidx, *indices = NULL; int numIdx = 0; int i; /* Flags. */ #if 0 int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); #endif /* Get number of verts. */ numVerts = dm->getNumVerts(dm); /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ if ((numVerts == 0) || (ob->defbase.first == NULL)) return dm; /* Get vgroup idx from its name. */ defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name_a); if (defgrp_idx < 0) return dm; /* Get seconf vgroup idx from its name, if given. */ if (wmd->defgrp_name_b[0] != (char)0) { defgrp_idx2 = defgroup_name_index(ob, wmd->defgrp_name_b); if (defgrp_idx2 < 0) return dm; } dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts); /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ if (!dvert) { /* If not affecting all vertices, just return. */ if (wmd->mix_set != MOD_WVG_SET_ALL) return dm; /* Else, add a valid data layer! */ dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts, wmd->defgrp_name_a); /* Ultimate security check. */ if (!dvert) return dm; } /* Find out which vertices to work on. */ tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGMix Modifier, tidx"); tdw1 = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGMix Modifier, tdw1"); tdw2 = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGMix Modifier, tdw2"); switch (wmd->mix_set) { case MOD_WVG_SET_A: /* All vertices in first vgroup. */ for (i = 0; i < numVerts; i++) { MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx); if (dw) { tdw1[numIdx] = dw; tdw2[numIdx] = defvert_find_index(&dvert[i], defgrp_idx2); tidx[numIdx++] = i; } } break; case MOD_WVG_SET_B: /* All vertices in second vgroup. */ for (i = 0; i < numVerts; i++) { MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx2); if (dw) { tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_idx); tdw2[numIdx] = dw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_OR: /* All vertices in one vgroup or the other. */ for (i = 0; i < numVerts; i++) { MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); if (adw || bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_AND: /* All vertices in both vgroups. */ for (i = 0; i < numVerts; i++) { MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); if (adw && bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_ALL: default: /* Use all vertices. */ for (i = 0; i < numVerts; i++) { tdw1[i] = defvert_find_index(&dvert[i], defgrp_idx); tdw2[i] = defvert_find_index(&dvert[i], defgrp_idx2); } numIdx = -1; break; } if (numIdx == 0) { /* Use no vertices! Hence, return org data. */ MEM_freeN(tdw1); MEM_freeN(tdw2); MEM_freeN(tidx); return dm; } if (numIdx != -1) { indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGMix Modifier, indices"); memcpy(indices, tidx, sizeof(int) * numIdx); dw1 = MEM_mallocN(sizeof(MDeformWeight *) * numIdx, "WeightVGMix Modifier, dw1"); memcpy(dw1, tdw1, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tdw1); dw2 = MEM_mallocN(sizeof(MDeformWeight *) * numIdx, "WeightVGMix Modifier, dw2"); memcpy(dw2, tdw2, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tdw2); } else { /* Use all vertices. */ numIdx = numVerts; /* Just copy MDeformWeight pointers arrays, they will be freed at the end. */ dw1 = tdw1; dw2 = tdw2; } MEM_freeN(tidx); org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, org_w"); new_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, new_w"); /* Mix weights. */ for (i = 0; i < numIdx; i++) { float weight2 = 0.0; org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a; weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b; new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode); } /* Do masking. */ weightvg_do_mask(numIdx, indices, org_w, new_w, ob, dm, wmd->mask_constant, wmd->mask_defgrp_name, wmd->modifier.scene, wmd->mask_texture, wmd->mask_tex_use_channel, wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); /* Update (add 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, dw1, numIdx, indices, org_w, TRUE, -FLT_MAX, FALSE, 0.0f); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ if (do_prev) DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices); #endif /* Freeing stuff. */ MEM_freeN(org_w); MEM_freeN(new_w); MEM_freeN(dw1); MEM_freeN(dw2); if (indices) MEM_freeN(indices); /* Return the vgroup-modified mesh. */ return dm; }
static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; MDeformVert *dvert = NULL; MDeformWeight **dw1, **tdw1, **dw2, **tdw2; float *org_w; float *new_w; int *tidx, *indices = NULL; int numIdx = 0; int i; /* Flags. */ #if 0 const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; #endif /* Get number of verts. */ const int numVerts = mesh->totvert; /* Check if we can just return the original mesh. * Must have verts and therefore verts assigned to vgroups to do anything useful! */ if ((numVerts == 0) || BLI_listbase_is_empty(&ctx->object->defbase)) { return mesh; } /* Get vgroup idx from its name. */ const int defgrp_index = defgroup_name_index(ctx->object, wmd->defgrp_name_a); if (defgrp_index == -1) { return mesh; } /* Get second vgroup idx from its name, if given. */ int defgrp_index_other = -1; if (wmd->defgrp_name_b[0] != '\0') { defgrp_index_other = defgroup_name_index(ctx->object, wmd->defgrp_name_b); if (defgrp_index_other == -1) { return mesh; } } const bool has_mdef = CustomData_has_layer(&mesh->vdata, CD_MDEFORMVERT); /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ if (!has_mdef) { /* If not affecting all vertices, just return. */ if (wmd->mix_set != MOD_WVG_SET_ALL) { return mesh; } } if (has_mdef) { dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, numVerts); } else { /* Add a valid data layer! */ dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts); } /* Ultimate security check. */ if (!dvert) { return mesh; } mesh->dvert = dvert; /* Find out which vertices to work on. */ tidx = MEM_malloc_arrayN(numVerts, sizeof(int), "WeightVGMix Modifier, tidx"); tdw1 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw1"); tdw2 = MEM_malloc_arrayN(numVerts, sizeof(MDeformWeight *), "WeightVGMix Modifier, tdw2"); switch (wmd->mix_set) { case MOD_WVG_SET_A: /* All vertices in first vgroup. */ for (i = 0; i < numVerts; i++) { MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_index); if (dw) { tdw1[numIdx] = dw; tdw2[numIdx] = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_B: /* All vertices in second vgroup. */ for (i = 0; i < numVerts; i++) { MDeformWeight *dw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; if (dw) { tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_index); tdw2[numIdx] = dw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_OR: /* All vertices in one vgroup or the other. */ for (i = 0; i < numVerts; i++) { MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_index); MDeformWeight *bdw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; if (adw || bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_AND: /* All vertices in both vgroups. */ for (i = 0; i < numVerts; i++) { MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_index); MDeformWeight *bdw = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; if (adw && bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; tidx[numIdx++] = i; } } break; case MOD_WVG_SET_ALL: default: /* Use all vertices. */ for (i = 0; i < numVerts; i++) { tdw1[i] = defvert_find_index(&dvert[i], defgrp_index); tdw2[i] = (defgrp_index_other >= 0) ? defvert_find_index(&dvert[i], defgrp_index_other) : NULL; } numIdx = -1; break; } if (numIdx == 0) { /* Use no vertices! Hence, return org data. */ MEM_freeN(tdw1); MEM_freeN(tdw2); MEM_freeN(tidx); return mesh; } if (numIdx != -1) { indices = MEM_malloc_arrayN(numIdx, sizeof(int), "WeightVGMix Modifier, indices"); memcpy(indices, tidx, sizeof(int) * numIdx); dw1 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw1"); memcpy(dw1, tdw1, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tdw1); dw2 = MEM_malloc_arrayN(numIdx, sizeof(MDeformWeight *), "WeightVGMix Modifier, dw2"); memcpy(dw2, tdw2, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tdw2); } else { /* Use all vertices. */ numIdx = numVerts; /* Just copy MDeformWeight pointers arrays, they will be freed at the end. */ dw1 = tdw1; dw2 = tdw2; } MEM_freeN(tidx); org_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, org_w"); new_w = MEM_malloc_arrayN(numIdx, sizeof(float), "WeightVGMix Modifier, new_w"); /* Mix weights. */ for (i = 0; i < numIdx; i++) { float weight2; org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a; weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b; new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode); } /* Do masking. */ struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); weightvg_do_mask(ctx, numIdx, indices, org_w, new_w, ctx->object, mesh, wmd->mask_constant, wmd->mask_defgrp_name, scene, wmd->mask_texture, wmd->mask_tex_use_channel, wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); /* Update (add 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_index, dw1, numIdx, indices, org_w, true, -FLT_MAX, false, 0.0f); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ if (do_prev) DM_update_weight_mcol(ob, dm, 0, org_w, numIdx, indices); #endif /* Freeing stuff. */ MEM_freeN(org_w); MEM_freeN(new_w); MEM_freeN(dw1); MEM_freeN(dw2); MEM_SAFE_FREE(indices); /* Return the vgroup-modified mesh. */ return mesh; }