예제 #1
0
static PyObject *bpy_bmdeformvert_subscript(BPy_BMDeformVert *self, PyObject *key)
{
	if (PyIndex_Check(key)) {
		int i;
		i = PyNumber_AsSsize_t(key, PyExc_IndexError);
		if (i == -1 && PyErr_Occurred()) {
			return NULL;
		}
		else {
			MDeformWeight *dw = defvert_find_index(self->data, i);

			if (dw == NULL) {
				PyErr_SetString(PyExc_KeyError, "BMDeformVert[key] = x: "
				                "key not found");
				return NULL;
			}
			else {
				return PyFloat_FromDouble(dw->weight);
			}
		}
	}
	else {
		PyErr_Format(PyExc_TypeError,
		             "BMDeformVert keys must be integers, not %.200s",
		             Py_TYPE(key)->tp_name);
		return NULL;
	}
}
예제 #2
0
파일: deform.c 프로젝트: Brachi/blender
/* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
MDeformWeight *defvert_verify_index(MDeformVert *dvert, const int defgroup)
{
	MDeformWeight *dw_new;

	/* do this check always, this function is used to check for it */
	if (!dvert || defgroup < 0) {
		BLI_assert(0);
		return NULL;
	}

	dw_new = defvert_find_index(dvert, defgroup);
	if (dw_new)
		return dw_new;

	dw_new = MEM_mallocN(sizeof(MDeformWeight) * (dvert->totweight + 1), "deformWeight");
	if (dvert->dw) {
		memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
		MEM_freeN(dvert->dw);
	}
	dvert->dw = dw_new;
	dw_new += dvert->totweight;
	dw_new->weight = 0.0f;
	dw_new->def_nr = defgroup;
	/* Group index */

	dvert->totweight++;

	return dw_new;
}
예제 #3
0
/* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup)
{
	MDeformWeight *newdw;

	/* do this check always, this function is used to check for it */
	if(!dv || defgroup<0)
		return NULL;

	newdw = defvert_find_index(dv, defgroup);
	if(newdw)
		return newdw;

	newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
	if(dv->dw) {
		memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
		MEM_freeN(dv->dw);
	}
	dv->dw=newdw;

	dv->dw[dv->totweight].weight=0.0f;
	dv->dw[dv->totweight].def_nr=defgroup;
	/* Group index */

	dv->totweight++;

	return dv->dw+(dv->totweight-1);
}
예제 #4
0
/* Applies weights to given vgroup (defgroup), and optionnaly add/remove vertices from the group.
 * If dws is not NULL, it must be an array of MDeformWeight pointers of same length as weights (and
 * defgrp_idx can then have any value).
 * If indices is not NULL, it must be an array of same length as weights, mapping to the real
 * vertex index (in case the weight array does not cover the whole vertices...).
 */
void weightvg_update_vg(MDeformVert *dvert, int defgrp_idx, MDeformWeight **dws, int num,
                        const int *indices, const float *weights, int do_add,
                        float add_thresh, int do_rem, float rem_thresh)
{
	int i;

	for(i = 0; i < num; i++) {
		float w = weights[i];
		MDeformVert *dv = &dvert[indices ? indices[i] : i];
		MDeformWeight *dw = dws ? dws[i] : defvert_find_index(dv, defgrp_idx);

		/* Never allow weights out of [0.0, 1.0] range. */
		CLAMP(w, 0.0f, 1.0f);

		/* If the vertex is in this vgroup, remove it if needed, or just update it. */
		if(dw != NULL) {
			if(do_rem && w < rem_thresh) {
				defvert_remove_from_group(dv, defgrp_idx, dw);
			}
			else {
				dw->weight = w;
			}
		}
		/* Else, add it if needed! */
		else if(do_add && w > add_thresh) {
			defvert_add_to_group(dv, defgrp_idx, w);
		}
	}
}
예제 #5
0
파일: deform.c 프로젝트: Brachi/blender
/* copy an index from one dvert to another
 * - do nothing if neither are set.
 * - add destination weight if needed.
 */
void defvert_copy_index(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const int defgroup)
{
	MDeformWeight *dw_src, *dw_dst;

	dw_src = defvert_find_index(dvert_src, defgroup);

	if (dw_src) {
		/* source is valid, verify destination */
		dw_dst = defvert_verify_index(dvert_dst, defgroup);
		dw_dst->weight = dw_src->weight;
	}
	else {
		/* source was NULL, assign zero, could also remove */
		dw_dst = defvert_find_index(dvert_dst, defgroup);

		if (dw_dst) {
			dw_dst->weight = 0.0f;
		}
	}
}
예제 #6
0
static int bpy_bmdeformvert_contains(BPy_BMDeformVert *self, PyObject *value)
{
	const int key = PyLong_AsSsize_t(value);

	if (key == -1 && PyErr_Occurred()) {
		PyErr_SetString(PyExc_TypeError,
		                "BMDeformVert.__contains__: expected an int");
		return -1;
	}

	return (defvert_find_index(self->data, key) != NULL) ? 1 : 0;
}
예제 #7
0
static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, PyObject *value)
{
	if (PyIndex_Check(key)) {
		int i;

		i = PyNumber_AsSsize_t(key, PyExc_IndexError);
		if (i == -1 && PyErr_Occurred()) {
			return -1;
		}

		if (value) {
			/* dvert[group_index] = 0.5 */
			if (i < 0) {
				PyErr_SetString(PyExc_KeyError, "BMDeformVert[key] = x: "
				                "weight keys can't be negative");
				return -1;
			}
			else {
				MDeformWeight *dw = defvert_verify_index(self->data, i);
				const float f = PyFloat_AsDouble(value);
				if (f == -1 && PyErr_Occurred()) { // parsed key not a number
					PyErr_SetString(PyExc_TypeError,
					                "BMDeformVert[key] = x: "
					                "assigned value not a number");
					return -1;
				}

				dw->weight = clamp_f(f, 0.0f, 1.0f);
			}
		}
		else {
			/* del dvert[group_index] */
			MDeformWeight *dw = defvert_find_index(self->data, i);

			if (dw == NULL) {
				PyErr_SetString(PyExc_KeyError, "del BMDeformVert[key]: "
				                "key not found");
			}
			defvert_remove_group(self->data, dw);
		}

		return 0;

	}
	else {
		PyErr_Format(PyExc_TypeError,
		             "BMDeformVert keys must be integers, not %.200s",
		             Py_TYPE(key)->tp_name);
		return -1;
	}
}
예제 #8
0
/* be sure all flip_map values are valid */
void defvert_sync_mapped (MDeformVert *dvert_r, const MDeformVert *dvert, const int *flip_map, int use_verify)
{
	if(dvert->totweight && dvert_r->totweight) {
		int i;
		MDeformWeight *dw;
		for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
			MDeformWeight *dw_r;
			if(use_verify)	dw_r= defvert_find_index(dvert_r, flip_map[dw->def_nr]);
			else			dw_r= defvert_verify_index(dvert_r, flip_map[dw->def_nr]);

			if(dw_r) {
				dw_r->weight= dw->weight;
			}
		}
	}
}
예제 #9
0
파일: deform.c 프로젝트: Brachi/blender
/* only sync over matching weights, don't add or remove groups
 * warning, loop within loop.
 */
void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool use_verify)
{
	if (dvert_src->totweight && dvert_dst->totweight) {
		int i;
		MDeformWeight *dw_src;
		for (i = 0, dw_src = dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
			MDeformWeight *dw_dst;
			if (use_verify) dw_dst = defvert_verify_index(dvert_dst, dw_src->def_nr);
			else            dw_dst = defvert_find_index(dvert_dst, dw_src->def_nr);

			if (dw_dst) {
				dw_dst->weight = dw_src->weight;
			}
		}
	}
}
예제 #10
0
파일: deform.c 프로젝트: Brachi/blender
static void vgroups_datatransfer_interp(
        const CustomDataTransferLayerMap *laymap, void *dest,
        const void **sources, const float *weights, const int count, const float mix_factor)
{
	MDeformVert **data_src = (MDeformVert **)sources;
	MDeformVert *data_dst = (MDeformVert *)dest;
	const int idx_src = laymap->data_src_n;
	const int idx_dst = laymap->data_dst_n;

	const int mix_mode = laymap->mix_mode;

	int i, j;

	MDeformWeight *dw_src;
	MDeformWeight *dw_dst = defvert_find_index(data_dst, idx_dst);
	float weight_src = 0.0f, weight_dst = 0.0f;

	if (sources) {
		for (i = count; i--;) {
			for (j = data_src[i]->totweight; j--;) {
				if ((dw_src = &data_src[i]->dw[j])->def_nr == idx_src) {
					weight_src += dw_src->weight * weights[i];
					break;
				}
			}
		}
	}

	if (dw_dst) {
		weight_dst = dw_dst->weight;
	}
	else if (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD) {
		return;  /* Do not affect destination. */
	}

	weight_src = data_transfer_interp_float_do(mix_mode, weight_dst, weight_src, mix_factor);

	CLAMP(weight_src, 0.0f, 1.0f);

	if (!dw_dst) {
		defvert_add_index_notest(data_dst, idx_dst, weight_src);
	}
	else {
		dw_dst->weight = weight_src;
	}
}
예제 #11
0
파일: deform.c 프로젝트: Brachi/blender
/* be sure all flip_map values are valid */
void defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src,
                         const int *flip_map, const int flip_map_len, const bool use_verify)
{
	if (dvert_src->totweight && dvert_dst->totweight) {
		int i;
		MDeformWeight *dw_src;
		for (i = 0, dw_src = dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
			if (dw_src->def_nr < flip_map_len) {
				MDeformWeight *dw_dst;
				if (use_verify) dw_dst = defvert_verify_index(dvert_dst, flip_map[dw_src->def_nr]);
				else            dw_dst = defvert_find_index(dvert_dst, flip_map[dw_src->def_nr]);

				if (dw_dst) {
					dw_dst->weight = dw_src->weight;
				}
			}
		}
	}
}
예제 #12
0
static PyObject *bpy_bmdeformvert_get(BPy_BMDeformVert *self, PyObject *args)
{
	int key;
	PyObject *def = Py_None;

	if (!PyArg_ParseTuple(args, "i|O:get", &key, &def)) {
		return NULL;
	}
	else {
		MDeformWeight *dw = defvert_find_index(self->data, key);

		if (dw) {
			return PyFloat_FromDouble(dw->weight);
		}
		else {
			return Py_INCREF_RET(def);
		}
	}
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
파일: deform.c 프로젝트: Brachi/blender
float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
{
	MDeformWeight *dw = defvert_find_index(dvert, defgroup);
	return dw ? dw->weight : 0.0f;
}
예제 #16
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;
}
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;
}