/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], bool use_normals, bool use_orco) { if (dm) { /* pass */ } else if (ob->type == OB_MESH) { if (em) dm = CDDM_from_editbmesh(em, false, false); else dm = CDDM_from_mesh((struct Mesh *)(ob->data)); if (vertexCos) { CDDM_apply_vert_coords(dm, vertexCos); dm->dirty |= DM_DIRTY_NORMALS; } if (use_orco) { DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob)); } } else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { dm = CDDM_from_curve(ob); } if (use_normals) { if (LIKELY(dm)) { DM_ensure_normals(dm); } } return dm; }
static void deformVertsEM( ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; if (!derivedData) dm = CDDM_from_editbmesh(em, FALSE, FALSE); deformVerts(md, ob, dm, vertexCos, numVerts, 0); if (!derivedData) dm->release(dm); }
static void deformMatricesEM( ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData *) md; DerivedMesh *dm = derivedData; if (!derivedData) dm = CDDM_from_editbmesh(em, FALSE, FALSE); armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts, amd->deformflag, NULL, amd->defgrp_name); if (!derivedData) dm->release(dm); }
static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; int use_dm = warp_needs_dm((WarpModifierData *)md); if (use_dm) { if (!derivedData) dm = CDDM_from_editbmesh(em, false, false); } deformVerts(md, ob, dm, vertexCos, numVerts, 0); if (use_dm) { if (!derivedData) dm->release(dm); } }
static void deformVertsEM( ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData *) md; DerivedMesh *dm = derivedData; if (!derivedData) dm = CDDM_from_editbmesh(em, FALSE, FALSE); modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts, amd->deformflag, (float(*)[3])amd->prevCos, amd->defgrp_name); /* free cache */ if (amd->prevCos) { MEM_freeN(amd->prevCos); amd->prevCos = NULL; } if (!derivedData) dm->release(dm); }
/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco) { if (dm) return dm; if (ob->type == OB_MESH) { if (em) dm = CDDM_from_editbmesh(em, FALSE, FALSE); else dm = CDDM_from_mesh((struct Mesh *)(ob->data), ob); if (vertexCos) { CDDM_apply_vert_coords(dm, vertexCos); //CDDM_calc_normals(dm); } if (orco) DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob)); } else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { dm = CDDM_from_curve(ob); } return dm; }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md; DerivedMesh *dm = derivedData; MDeformVert *dvert = NULL; MDeformWeight **dw, **tdw; int numVerts; float (*v_cos)[3] = NULL; /* The vertices coordinates. */ Object *obr = NULL; /* Our target object. */ int defgrp_index; float *tw = NULL; float *org_w = NULL; float *new_w = NULL; int *tidx, *indices = NULL; int numIdx = 0; int i; /* Flags. */ #if 0 const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; #endif #ifdef USE_TIMEIT TIMEIT_START(perf); #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) || BLI_listbase_is_empty(&ob->defbase)) return dm; /* Get our target object. */ obr = wmd->proximity_ob_target; if (obr == NULL) return dm; /* Get vgroup idx from its name. */ defgrp_index = defgroup_name_index(ob, wmd->defgrp_name); if (defgrp_index == -1) 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. * As this modifier never add vertices to vgroup, just return. */ if (!dvert) return dm; /* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. */ tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGProximity Modifier, tidx"); tw = MEM_mallocN(sizeof(float) * numVerts, "WeightVGProximity Modifier, tw"); tdw = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGProximity Modifier, tdw"); for (i = 0; i < numVerts; i++) { MDeformWeight *_dw = defvert_find_index(&dvert[i], defgrp_index); if (_dw) { tidx[numIdx] = i; tw[numIdx] = _dw->weight; tdw[numIdx++] = _dw; } } /* If no vertices found, return org data! */ if (numIdx == 0) { MEM_freeN(tidx); MEM_freeN(tw); MEM_freeN(tdw); return dm; } if (numIdx != numVerts) { indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGProximity Modifier, indices"); memcpy(indices, tidx, sizeof(int) * numIdx); org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, org_w"); memcpy(org_w, tw, sizeof(float) * numIdx); dw = MEM_mallocN(sizeof(MDeformWeight *) * numIdx, "WeightVGProximity Modifier, dw"); memcpy(dw, tdw, sizeof(MDeformWeight *) * numIdx); MEM_freeN(tw); MEM_freeN(tdw); } else { org_w = tw; dw = tdw; } new_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, new_w"); MEM_freeN(tidx); /* Get our vertex coordinates. */ v_cos = MEM_mallocN(sizeof(float[3]) * numIdx, "WeightVGProximity Modifier, v_cos"); if (numIdx != numVerts) { /* XXX In some situations, this code can be up to about 50 times more performant * than simply using getVertCo for each affected vertex... */ float (*tv_cos)[3] = MEM_mallocN(sizeof(float[3]) * numVerts, "WeightVGProximity Modifier, tv_cos"); dm->getVertCos(dm, tv_cos); for (i = 0; i < numIdx; i++) copy_v3_v3(v_cos[i], tv_cos[indices[i]]); MEM_freeN(tv_cos); } else dm->getVertCos(dm, v_cos); /* Compute wanted distances. */ if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) { const float dist = get_ob2ob_distance(ob, obr); for (i = 0; i < numIdx; i++) new_w[i] = dist; } else if (wmd->proximity_mode == MOD_WVG_PROXIMITY_GEOMETRY) { const short use_trgt_verts = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_VERTS); const short use_trgt_edges = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_EDGES); const short use_trgt_faces = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_FACES); if (use_trgt_verts || use_trgt_edges || use_trgt_faces) { DerivedMesh *target_dm = obr->derivedFinal; bool free_target_dm = false; if (!target_dm) { if (ELEM(obr->type, OB_CURVE, OB_SURF, OB_FONT)) target_dm = CDDM_from_curve(obr); else if (obr->type == OB_MESH) { Mesh *me = (Mesh *)obr->data; if (me->edit_btmesh) target_dm = CDDM_from_editbmesh(me->edit_btmesh, false, false); else target_dm = CDDM_from_mesh(me); } free_target_dm = true; } /* We must check that we do have a valid target_dm! */ if (target_dm) { SpaceTransform loc2trgt; float *dists_v = use_trgt_verts ? MEM_mallocN(sizeof(float) * numIdx, "dists_v") : NULL; float *dists_e = use_trgt_edges ? MEM_mallocN(sizeof(float) * numIdx, "dists_e") : NULL; float *dists_f = use_trgt_faces ? MEM_mallocN(sizeof(float) * numIdx, "dists_f") : NULL; BLI_SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr); get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f, target_dm, &loc2trgt); for (i = 0; i < numIdx; i++) { new_w[i] = dists_v ? dists_v[i] : FLT_MAX; if (dists_e) new_w[i] = min_ff(dists_e[i], new_w[i]); if (dists_f) new_w[i] = min_ff(dists_f[i], new_w[i]); } if (free_target_dm) target_dm->release(target_dm); if (dists_v) MEM_freeN(dists_v); if (dists_e) MEM_freeN(dists_e); if (dists_f) MEM_freeN(dists_f); } /* Else, fall back to default obj2vert behavior. */ else { get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr); } } else { get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr); } } /* Map distances to weights. */ do_map(ob, new_w, numIdx, wmd->min_dist, wmd->max_dist, wmd->falloff_type); /* 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 vgroup. Note we never add nor remove vertices from vgroup here. */ weightvg_update_vg(dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, 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(dw); if (indices) MEM_freeN(indices); MEM_freeN(v_cos); #ifdef USE_TIMEIT TIMEIT_END(perf); #endif /* Return the vgroup-modified mesh. */ return dm; }