/**
 * Maps distances to weights, with an optional "smoothing" mapping.
 */
void do_map(float *weights, const int nidx, const float min_d, const float max_d, short mode)
{
	const float range_inv = 1.0f / (max_d - min_d); /* invert since multiplication is faster */
	unsigned int i = nidx;
	if (max_d == min_d) {
		while (i-- > 0) {
			weights[i] = (weights[i] >= max_d) ? 1.0f : 0.0f; /* "Step" behavior... */
		}
	}
	else if (max_d > min_d) {
		while (i-- > 0) {
			if     (weights[i] >= max_d) weights[i] = 1.0f;  /* most likely case first */
			else if (weights[i] <= min_d) weights[i] = 0.0f;
			else weights[i] = (weights[i] - min_d) * range_inv;
		}
	}
	else {
		while (i-- > 0) {
			if     (weights[i] <= max_d) weights[i] = 1.0f;  /* most likely case first */
			else if (weights[i] >= min_d) weights[i] = 0.0f;
			else weights[i] = (weights[i] - min_d) * range_inv;
		}
	}

	if (!ELEM(mode, MOD_WVG_MAPPING_NONE, MOD_WVG_MAPPING_CURVE)) {
		weightvg_do_map(nidx, weights, mode, NULL);
	}
}
Exemplo n.º 2
0
/**
 * Maps distances to weights, with an optional "smoothing" mapping.
 */
static void do_map(Object *ob, float *weights, const int nidx, const float min_d, const float max_d, short mode)
{
	const float range_inv = 1.0f / (max_d - min_d); /* invert since multiplication is faster */
	unsigned int i = nidx;
	if (max_d == min_d) {
		while (i-- > 0) {
			weights[i] = (weights[i] >= max_d) ? 1.0f : 0.0f; /* "Step" behavior... */
		}
	}
	else if (max_d > min_d) {
		while (i-- > 0) {
			if     (weights[i] >= max_d) weights[i] = 1.0f;  /* most likely case first */
			else if (weights[i] <= min_d) weights[i] = 0.0f;
			else weights[i] = (weights[i] - min_d) * range_inv;
		}
	}
	else {
		while (i-- > 0) {
			if     (weights[i] <= max_d) weights[i] = 1.0f;  /* most likely case first */
			else if (weights[i] >= min_d) weights[i] = 0.0f;
			else weights[i] = (weights[i] - min_d) * range_inv;
		}
	}

	if (!ELEM(mode, MOD_WVG_MAPPING_NONE, MOD_WVG_MAPPING_CURVE)) {
		RNG *rng = NULL;

		if (mode == MOD_WVG_MAPPING_RANDOM)
			rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2));

		weightvg_do_map(nidx, weights, mode, NULL, rng);

		if (rng)
			BLI_rng_free(rng);
	}
}
Exemplo n.º 3
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
	DerivedMesh *dm = derivedData;
	MDeformVert *dvert = NULL;
	MDeformWeight **dw = NULL;
	float *org_w; /* Array original weights. */
	float *new_w; /* Array new weights. */
	int numVerts;
	int defgrp_index;
	int i;
	/* Flags. */
	int do_add  = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0;
	int do_rem  = (wmd->edit_flags & MOD_WVG_EDIT_REMFVG) != 0;
	/* Only do weight-preview in Object, Sculpt and Pose modes! */
#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_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. */
	if (!dvert) {
		/* If this modifier is not allowed to add vertices, just return. */
		if (!do_add)
			return dm;
		/* Else, add a valid data layer! */
		dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC,
		                                   NULL, numVerts, wmd->defgrp_name);
		/* Ultimate security check. */
		if (!dvert)
			return dm;
	}

	/* Get org weights, assuming 0.0 for vertices not in given vgroup. */
	org_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, org_w");
	new_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, new_w");
	dw = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGEdit Modifier, dw");
	for (i = 0; i < numVerts; i++) {
		dw[i] = defvert_find_index(&dvert[i], defgrp_index);
		if (dw[i]) {
			org_w[i] = new_w[i] = dw[i]->weight;
		}
		else {
			org_w[i] = new_w[i] = wmd->default_weight;
		}
	}

	/* Do mapping. */
	if (wmd->falloff_type != MOD_WVG_MAPPING_NONE) {
		RNG *rng = NULL;

		if (wmd->falloff_type == MOD_WVG_MAPPING_RANDOM)
			rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2));

		weightvg_do_map(numVerts, new_w, wmd->falloff_type, wmd->cmap_curve, rng);

		if (rng)
			BLI_rng_free(rng);
	}

	/* Do masking. */
	weightvg_do_mask(numVerts, NULL, 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/remove from vgroup. */
	weightvg_update_vg(dvert, defgrp_index, dw, numVerts, NULL, org_w, do_add, wmd->add_threshold,
	                   do_rem, wmd->rem_threshold);

	/* If weight preview enabled... */
#if 0 /* XXX Currently done in mod stack :/ */
	if (do_prev)
		DM_update_weight_mcol(ob, dm, 0, org_w, 0, NULL);
#endif

	/* Freeing stuff. */
	MEM_freeN(org_w);
	MEM_freeN(new_w);
	MEM_freeN(dw);

	/* Return the vgroup-modified mesh. */
	return dm;
}