Exemple #1
0
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);
		}
	}
}
Exemple #2
0
/* 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;
}
Exemple #3
0
/* 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);
	}
}
Exemple #4
0
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);
}
Exemple #5
0
/* 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;
}
Exemple #8
0
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;
}