void rna_Object_dm_info(struct Object *ob, int type, char *result) { DerivedMesh *dm = NULL; bool dm_release = false; char *ret = NULL; result[0] = '\0'; switch (type) { case 0: if (ob->type == OB_MESH) { dm = CDDM_from_mesh(ob->data); ret = DM_debug_info(dm); dm_release = true; } break; case 1: dm = ob->derivedDeform; break; case 2: dm = ob->derivedFinal; break; } if (dm) { ret = DM_debug_info(dm); if (dm_release) { dm->release(dm); } if (ret) { strcpy(result, ret); MEM_freeN(ret); } } }
/* 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; }
/* get the appropriate DerivedMesh based on rigid body mesh source */ static DerivedMesh *rigidbody_get_mesh(Object *ob) { if (ob->rigidbody_object->mesh_source == RBO_MESH_DEFORM) { return ob->derivedDeform; } else if (ob->rigidbody_object->mesh_source == RBO_MESH_FINAL) { return ob->derivedFinal; } else { return CDDM_from_mesh(ob->data); } }
static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData *) md; DerivedMesh *dm = derivedData; if (!derivedData) dm = CDDM_from_mesh((Mesh *)ob->data, ob); armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts, amd->deformflag, NULL, amd->defgrp_name); 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; }
/** * This function converts an object space normal map to a tangent space normal map for a given low poly mesh */ void RE_bake_normal_world_to_tangent( const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[], Mesh *me, const BakeNormalSwizzle normal_swizzle[3], float mat[4][4]) { size_t i; TriTessFace *triangles; DerivedMesh *dm = CDDM_from_mesh(me); triangles = MEM_mallocN(sizeof(TriTessFace) * (me->totface * 2), "MVerts Mesh"); mesh_calc_tri_tessface(triangles, me, true, dm); BLI_assert(num_pixels >= 3); for (i = 0; i < num_pixels; i++) { TriTessFace *triangle; float tangents[3][3]; float normals[3][3]; float signs[3]; int j; float tangent[3]; float normal[3]; float binormal[3]; float sign; float u, v, w; float tsm[3][3]; /* tangent space matrix */ float itsm[3][3]; size_t offset; float nor[3]; /* texture normal */ bool is_smooth; int primitive_id = pixel_array[i].primitive_id; offset = i * depth; if (primitive_id == -1) { copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f); continue; } triangle = &triangles[primitive_id]; is_smooth = triangle->is_smooth; for (j = 0; j < 3; j++) { const TSpace *ts; if (is_smooth) normal_short_to_float_v3(normals[j], triangle->mverts[j]->no); else normal[j] = triangle->normal[j]; ts = triangle->tspace[j]; copy_v3_v3(tangents[j], ts->tangent); signs[j] = ts->sign; } u = pixel_array[i].uv[0]; v = pixel_array[i].uv[1]; w = 1.0f - u - v; /* normal */ if (is_smooth) interp_barycentric_tri_v3(normals, u, v, normal); /* tangent */ interp_barycentric_tri_v3(tangents, u, v, tangent); /* sign */ /* The sign is the same at all face vertices for any non degenerate face. * Just in case we clamp the interpolated value though. */ sign = (signs[0] * u + signs[1] * v + signs[2] * w) < 0 ? (-1.0f) : 1.0f; /* binormal */ /* B = sign * cross(N, T) */ cross_v3_v3v3(binormal, normal, tangent); mul_v3_fl(binormal, sign); /* populate tangent space matrix */ copy_v3_v3(tsm[0], tangent); copy_v3_v3(tsm[1], binormal); copy_v3_v3(tsm[2], normal); /* texture values */ normal_uncompress(nor, &result[offset]); /* converts from world space to local space */ mul_transposed_mat3_m4_v3(mat, nor); invert_m3_m3(itsm, tsm); mul_m3_v3(itsm, nor); normalize_v3(nor); /* save back the values */ normal_compress(&result[offset], nor, normal_swizzle); } /* garbage collection */ MEM_freeN(triangles); if (dm) dm->release(dm); }
bool RE_bake_pixels_populate_from_objects( struct Mesh *me_low, BakePixel pixel_array_from[], BakePixel pixel_array_to[], BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage, const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage) { size_t i; int primitive_id; float u, v; float imat_low[4][4]; bool is_cage = me_cage != NULL; bool result = true; DerivedMesh *dm_low = NULL; DerivedMesh **dm_highpoly; BVHTreeFromMesh *treeData; /* Note: all coordinates are in local space */ TriTessFace *tris_low = NULL; TriTessFace *tris_cage = NULL; TriTessFace **tris_high; /* assume all lowpoly tessfaces can be quads */ tris_high = MEM_callocN(sizeof(TriTessFace *) * tot_highpoly, "MVerts Highpoly Mesh Array"); /* assume all highpoly tessfaces are triangles */ dm_highpoly = MEM_mallocN(sizeof(DerivedMesh *) * tot_highpoly, "Highpoly Derived Meshes"); treeData = MEM_callocN(sizeof(BVHTreeFromMesh) * tot_highpoly, "Highpoly BVH Trees"); if (!is_cage) { dm_low = CDDM_from_mesh(me_low); tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); mesh_calc_tri_tessface(tris_low, me_low, true, dm_low); } else if (is_custom_cage) { tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh"); mesh_calc_tri_tessface(tris_low, me_low, false, NULL); tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL); } else { tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh"); mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL); } invert_m4_m4(imat_low, mat_low); for (i = 0; i < tot_highpoly; i++) { tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly[i].me->totface, "MVerts Highpoly Mesh"); mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL); dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me); DM_ensure_tessface(dm_highpoly[i]); if (dm_highpoly[i]->getNumTessFaces(dm_highpoly[i]) != 0) { /* Create a bvh-tree for each highpoly object */ bvhtree_from_mesh_faces(&treeData[i], dm_highpoly[i], 0.0, 2, 6); if (treeData[i].tree == NULL) { printf("Baking: out of memory while creating BHVTree for object \"%s\"\n", highpoly[i].ob->id.name + 2); result = false; goto cleanup; } } } for (i = 0; i < num_pixels; i++) { float co[3]; float dir[3]; primitive_id = pixel_array_from[i].primitive_id; if (primitive_id == -1) { pixel_array_to[i].primitive_id = -1; continue; } u = pixel_array_from[i].uv[0]; v = pixel_array_from[i].uv[1]; /* calculate from low poly mesh cage */ if (is_custom_cage) { calc_point_from_barycentric_cage(tris_low, tris_cage, mat_low, mat_cage, primitive_id, u, v, co, dir); } else if (is_cage) { calc_point_from_barycentric_extrusion(tris_cage, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, true); } else { calc_point_from_barycentric_extrusion(tris_low, mat_low, imat_low, primitive_id, u, v, cage_extrusion, co, dir, false); } /* cast ray */ if (!cast_ray_highpoly(treeData, tris_high, pixel_array_to, highpoly, co, dir, i, tot_highpoly, pixel_array_from[i].du_dx, pixel_array_from[i].du_dy, pixel_array_from[i].dv_dx, pixel_array_from[i].dv_dy)) { /* if it fails mask out the original pixel array */ pixel_array_from[i].primitive_id = -1; } } /* garbage collection */ cleanup: for (i = 0; i < tot_highpoly; i++) { free_bvhtree_from_mesh(&treeData[i]); if (dm_highpoly[i]) { dm_highpoly[i]->release(dm_highpoly[i]); } if (tris_high[i]) { MEM_freeN(tris_high[i]); } } MEM_freeN(tris_high); MEM_freeN(treeData); MEM_freeN(dm_highpoly); if (dm_low) { dm_low->release(dm_low); } if (tris_low) { MEM_freeN(tris_low); } if (tris_cage) { MEM_freeN(tris_cage); } return result; }
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int UNUSED(numVerts), ModifierApplyFlag UNUSED(flag)) { CollisionModifierData *collmd = (CollisionModifierData *) md; DerivedMesh *dm = NULL; MVert *tempVert = NULL; /* if possible use/create DerivedMesh */ if (derivedData) dm = CDDM_copy(derivedData); else if (ob->type == OB_MESH) dm = CDDM_from_mesh(ob->data, ob); if (!ob->pd) { printf("CollisionModifier deformVerts: Should not happen!\n"); return; } if (dm) { float current_time = 0; unsigned int numverts = 0; CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); current_time = BKE_scene_frame_get(md->scene); if (G.debug_value > 0) printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew); numverts = dm->getNumVerts(dm); if (current_time > collmd->time_xnew) { unsigned int i; /* check if mesh has changed */ if (collmd->x && (numverts != collmd->numverts)) freeData((ModifierData *)collmd); if (collmd->time_xnew == -1000) { /* first time */ collmd->x = dm->dupVertArray(dm); /* frame start position */ for (i = 0; i < numverts; i++) { /* we save global positions */ mul_m4_v3(ob->obmat, collmd->x[i].co); } collmd->xnew = MEM_dupallocN(collmd->x); // frame end position collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame collmd->numverts = numverts; DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ collmd->mfaces = dm->dupTessFaceArray(dm); collmd->numfaces = dm->getNumTessFaces(dm); /* create bounding box hierarchy */ collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft); collmd->time_x = collmd->time_xnew = current_time; } else if (numverts == collmd->numverts) { /* put positions to old positions */ tempVert = collmd->x; collmd->x = collmd->xnew; collmd->xnew = tempVert; collmd->time_x = collmd->time_xnew; memcpy(collmd->xnew, dm->getVertArray(dm), numverts * sizeof(MVert)); for (i = 0; i < numverts; i++) { /* we save global positions */ mul_m4_v3(ob->obmat, collmd->xnew[i].co); } memcpy(collmd->current_xnew, collmd->x, numverts * sizeof(MVert)); memcpy(collmd->current_x, collmd->x, numverts * sizeof(MVert)); /* check if GUI setting has changed for bvh */ if (collmd->bvhtree) { if (ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree)) { BLI_bvhtree_free(collmd->bvhtree); collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); } } /* happens on file load (ONLY when i decomment changes in readfile.c) */ if (!collmd->bvhtree) { collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); } else { /* recalc static bounding boxes */ bvhtree_update_from_mvert(collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1); } collmd->time_xnew = current_time; } else if (numverts != collmd->numverts) { freeData((ModifierData *)collmd); } } else if (current_time < collmd->time_xnew) { freeData((ModifierData *)collmd); } else { if (numverts != collmd->numverts) { freeData((ModifierData *)collmd); } } } if (dm) dm->release(dm); }
/* saves the current emitter state for a particle system and calculates particles */ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int UNUSED(numVerts), ModifierApplyFlag flag) { DerivedMesh *dm = derivedData; ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; ParticleSystem *psys = NULL; bool needsFree = false; /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */ if (ob->particlesystem.first) psys = psmd->psys; else return; if (!psys_check_enabled(ob, psys, (flag & MOD_APPLY_RENDER) != 0)) return; if (dm == NULL) { dm = get_dm(ob, NULL, NULL, vertexCos, false, true); if (!dm) return; needsFree = true; } /* clear old dm */ if (psmd->dm_final) { psmd->dm_final->needsFree = true; psmd->dm_final->release(psmd->dm_final); if (psmd->dm_deformed) { psmd->dm_deformed->needsFree = 1; psmd->dm_deformed->release(psmd->dm_deformed); psmd->dm_deformed = NULL; } } else if (psmd->flag & eParticleSystemFlag_file_loaded) { /* in file read dm just wasn't saved in file so no need to reset everything */ psmd->flag &= ~eParticleSystemFlag_file_loaded; } else { /* no dm before, so recalc particles fully */ psys->recalc |= PSYS_RECALC_RESET; } /* make new dm */ psmd->dm_final = CDDM_copy(dm); CDDM_apply_vert_coords(psmd->dm_final, vertexCos); CDDM_calc_normals(psmd->dm_final); if (needsFree) { dm->needsFree = true; dm->release(dm); } /* protect dm */ psmd->dm_final->needsFree = false; DM_ensure_tessface(psmd->dm_final); if (!psmd->dm_final->deformedOnly) { /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set. * This is awfully weak though. :| */ if (ob->derivedDeform) { psmd->dm_deformed = CDDM_copy(ob->derivedDeform); } else { /* Can happen in some cases, e.g. when rendering from Edit mode... */ psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data); } DM_ensure_tessface(psmd->dm_deformed); } /* report change in mesh structure */ if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert || psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge || psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface) { psys->recalc |= PSYS_RECALC_RESET; psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final); psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final); psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final); } if (!(ob->transflag & OB_NO_PSYS_UPDATE)) { psmd->flag &= ~eParticleSystemFlag_psys_updated; particle_system_update(md->scene, ob, psys, (flag & MOD_APPLY_RENDER) != 0); psmd->flag |= eParticleSystemFlag_psys_updated; } }
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_idx; float *tw = NULL; float *org_w = NULL; float *new_w = NULL; int *tidx, *indices = NULL; int numIdx = 0; int i; /* Flags. */ #if 0 int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); #endif #if DO_PROFILE 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) || (ob->defbase.first == NULL)) return dm; /* Get our target object. */ obr = wmd->proximity_ob_target; if (obr == NULL) return dm; /* Get vgroup idx from its name. */ defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name); if (defgrp_idx < 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. * 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_idx); 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; short free_target_dm = FALSE; if (!target_dm) { if (ELEM3(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_BMEditMesh(me->edit_btmesh, me, FALSE, FALSE); else target_dm = CDDM_from_mesh(me, obr); } 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; 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] = minf(dists_e[i], new_w[i]); if (dists_f) new_w[i] = minf(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(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_idx, 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); #if DO_PROFILE TIMEIT_END(perf) #endif /* Return the vgroup-modified mesh. */ return dm; }