Ejemplo n.º 1
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
	DerivedMesh *dm = derivedData;
	ReportList reports;

	/* Only used to check wehther we are operating on org data or not... */
	Mesh *me = ob->data;
	MVert *mvert;

	const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;

	const float max_dist = (dtmd->flags & MOD_DATATRANSFER_MAP_MAXDIST) ? dtmd->map_max_distance : FLT_MAX;

	SpaceTransform space_transform_data;
	SpaceTransform *space_transform = (dtmd->flags & MOD_DATATRANSFER_OBSRC_TRANSFORM) ? &space_transform_data : NULL;

	if (space_transform) {
		BLI_SPACE_TRANSFORM_SETUP(space_transform, ob, dtmd->ob_source);
	}

	mvert = dm->getVertArray(dm);
	if ((me->mvert == mvert) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) {
		/* We need to duplicate data here, otherwise setting custom normals, edges' shaprness, etc., could
		 * modify org mesh, see T43671. */
		dm = CDDM_copy(dm);
	}

	BKE_reports_init(&reports, RPT_STORE);

	/* Note: no islands precision for now here. */
	BKE_object_data_transfer_dm(md->scene, dtmd->ob_source, ob, dm, dtmd->data_types, false,
	                     dtmd->vmap_mode, dtmd->emap_mode, dtmd->lmap_mode, dtmd->pmap_mode,
	                     space_transform, max_dist, dtmd->map_ray_radius, 0.0f,
	                     dtmd->layers_select_src, dtmd->layers_select_dst,
	                     dtmd->mix_mode, dtmd->mix_factor, dtmd->defgrp_name, invert_vgroup, &reports);

	if (BKE_reports_contain(&reports, RPT_ERROR)) {
		modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR));
	}
	else if (dm->getNumVerts(dm) > HIGH_POLY_WARNING || ((Mesh *)(dtmd->ob_source->data))->totvert > HIGH_POLY_WARNING) {
		modifier_setError(md, "You are using a rather high poly as source or destination, computation might be slow");
	}

	return dm;
}
Ejemplo n.º 2
0
/* simple deform modifier */
static void SimpleDeformModifier_do(
        SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm,
        float (*vertexCos)[3], int numVerts)
{
	const float base_limit[2] = {0.0f, 0.0f};

	int i;
	float smd_limit[2], smd_factor;
	SpaceTransform *transf = NULL, tmp_transf;
	void (*simpleDeform_callback)(const float factor, const int axis, const float dcut[3], float co[3]) = NULL;  /* Mode callback */
	int vgroup;
	MDeformVert *dvert;

	/* This is historically the lock axis, _not_ the deform axis as the name would imply */
	const int deform_axis = smd->deform_axis;
	int lock_axis = smd->axis;
	if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) { /* Bend mode shouldn't have any lock axis */
		lock_axis = 0;
	}
	else {
		/* Don't lock axis if it is the chosen deform axis, as this flattens
		 * the geometry */
		if (deform_axis == 0) {
			lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_X;
		}
		if (deform_axis == 1) {
			lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_Y;
		}
		if (deform_axis == 2) {
			lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_Z;
		}
	}


	/* Safe-check */
	if (smd->origin == ob) smd->origin = NULL;  /* No self references */

	if (smd->limit[0] < 0.0f) smd->limit[0] = 0.0f;
	if (smd->limit[0] > 1.0f) smd->limit[0] = 1.0f;

	smd->limit[0] = min_ff(smd->limit[0], smd->limit[1]);  /* Upper limit >= than lower limit */

	/* Calculate matrixs do convert between coordinate spaces */
	if (smd->origin) {
		transf = &tmp_transf;
		BLI_SPACE_TRANSFORM_SETUP(transf, ob, smd->origin);
	}

	/* Update limits if needed */
	int limit_axis = deform_axis;
	if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) {
		/* Bend is a special case. */
		switch (deform_axis) {
			case 0:
				ATTR_FALLTHROUGH;
			case 1:
				limit_axis = 2;
				break;
			default:
				limit_axis = 0;
		}
	}

	{
		float lower =  FLT_MAX;
		float upper = -FLT_MAX;

		for (i = 0; i < numVerts; i++) {
			float tmp[3];
			copy_v3_v3(tmp, vertexCos[i]);

			if (transf) {
				BLI_space_transform_apply(transf, tmp);
			}

			lower = min_ff(lower, tmp[limit_axis]);
			upper = max_ff(upper, tmp[limit_axis]);
		}


		/* SMD values are normalized to the BV, calculate the absolute values */
		smd_limit[1] = lower + (upper - lower) * smd->limit[1];
		smd_limit[0] = lower + (upper - lower) * smd->limit[0];

		smd_factor   = smd->factor / max_ff(FLT_EPSILON, smd_limit[1] - smd_limit[0]);
	}

	switch (smd->mode) {
		case MOD_SIMPLEDEFORM_MODE_TWIST:   simpleDeform_callback = simpleDeform_twist;     break;
		case MOD_SIMPLEDEFORM_MODE_BEND:    simpleDeform_callback = simpleDeform_bend;      break;
		case MOD_SIMPLEDEFORM_MODE_TAPER:   simpleDeform_callback = simpleDeform_taper;     break;
		case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch;   break;
		default:
			return; /* No simpledeform mode? */
	}

	if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) {
		if (fabsf(smd_factor) < BEND_EPS) {
			return;
		}
	}

	modifier_get_vgroup(ob, dm, smd->vgroup_name, &dvert, &vgroup);
	const bool invert_vgroup = (smd->flag & MOD_SIMPLEDEFORM_FLAG_INVERT_VGROUP) != 0;
	const uint *axis_map = axis_map_table[(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) ? deform_axis : 2];

	for (i = 0; i < numVerts; i++) {
		float weight = defvert_array_find_weight_safe(dvert, i, vgroup);

		if (invert_vgroup) {
			weight = 1.0f - weight;
		}

		if (weight != 0.0f) {
			float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};

			if (transf) {
				BLI_space_transform_apply(transf, vertexCos[i]);
			}

			copy_v3_v3(co, vertexCos[i]);

			/* Apply axis limits, and axis mappings */
			if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) {
				axis_limit(0, base_limit, co, dcut);
			}
			if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) {
				axis_limit(1, base_limit, co, dcut);
			}
			if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Z) {
				axis_limit(2, base_limit, co, dcut);
			}
			axis_limit(limit_axis, smd_limit, co, dcut);

			/* apply the deform to a mapped copy of the vertex, and then re-map it back. */
			float co_remap[3];
			float dcut_remap[3];
			copy_v3_v3_map(co_remap, co, axis_map);
			copy_v3_v3_map(dcut_remap, dcut, axis_map);
			simpleDeform_callback(smd_factor, deform_axis, dcut_remap, co_remap);  /* apply deform */
			copy_v3_v3_unmap(co, co_remap, axis_map);

			interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight);  /* Use vertex weight has coef of linear interpolation */

			if (transf) {
				BLI_space_transform_invert(transf, vertexCos[i]);
			}
		}
	}
}
static int data_transfer_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob_src = ED_object_active_context(C);

	ListBase ctx_objects;
	CollectionPointerLink *ctx_ob_dst;

	bool changed = false;

	const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");

	const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");

	const int data_type = RNA_enum_get(op->ptr, "data_type");
	const bool use_create = RNA_boolean_get(op->ptr, "use_create");

	const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
	const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
	const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
	const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");

	const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
	const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
	const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
	const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
	const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
	const float islands_precision = RNA_float_get(op->ptr, "islands_precision");

	const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
	const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
	int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
	int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
	const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);

	const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
	const float mix_factor = RNA_float_get(op->ptr, "mix_factor");

	SpaceTransform space_transform_data;
	SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ? &space_transform_data : NULL;

	if (is_frozen) {
		BKE_report(op->reports, RPT_INFO,
		           "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
		return OPERATOR_FINISHED;
	}

	if (reverse_transfer && ((ID *)(ob_src->data))->lib) {
		/* Do not transfer to linked data, not supported. */
		return OPERATOR_CANCELLED;
	}

	if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
		layers_select_src[fromto_idx] = layers_src;
		layers_select_dst[fromto_idx] = layers_dst;
	}

	data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);

	for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
		Object *ob_dst = ctx_ob_dst->ptr.data;

		if (reverse_transfer) {
			SWAP(Object *, ob_src, ob_dst);
		}

		if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
			if (space_transform) {
				BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst, ob_src);
			}

			if (BKE_object_data_transfer_mesh(
			        scene, ob_src, ob_dst, data_type, use_create,
			        map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
			        space_transform, use_auto_transform,
			        max_distance, ray_radius, islands_precision,
			        layers_select_src, layers_select_dst,
			        mix_mode, mix_factor, NULL, false, op->reports))
			{
				changed = true;
			}
		}

		DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);

		if (reverse_transfer) {
			SWAP(Object *, ob_src, ob_dst);
		}
	}

	BLI_freelistN(&ctx_objects);

	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);

#if 0  /* TODO */
	/* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
	return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
#else
	(void)changed;
	return OPERATOR_FINISHED;
#endif
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
/* simple deform modifier */
static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm,
                                    float (*vertexCos)[3], int numVerts)
{
	static const float lock_axis[2] = {0.0f, 0.0f};

	int i;
	int limit_axis = 0;
	float smd_limit[2], smd_factor;
	SpaceTransform *transf = NULL, tmp_transf;
	void (*simpleDeform_callback)(const float factor, const float dcut[3], float co[3]) = NULL;  /* Mode callback */
	int vgroup;
	MDeformVert *dvert;

	/* Safe-check */
	if (smd->origin == ob) smd->origin = NULL;  /* No self references */

	if (smd->limit[0] < 0.0f) smd->limit[0] = 0.0f;
	if (smd->limit[0] > 1.0f) smd->limit[0] = 1.0f;

	smd->limit[0] = min_ff(smd->limit[0], smd->limit[1]);  /* Upper limit >= than lower limit */

	/* Calculate matrixs do convert between coordinate spaces */
	if (smd->origin) {
		transf = &tmp_transf;
		BLI_SPACE_TRANSFORM_SETUP(transf, ob, smd->origin);
	}

	/* Setup vars,
	 * Bend limits on X.. all other modes limit on Z */
	limit_axis  = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2;

	/* Update limits if needed */
	{
		float lower =  FLT_MAX;
		float upper = -FLT_MAX;

		for (i = 0; i < numVerts; i++) {
			float tmp[3];
			copy_v3_v3(tmp, vertexCos[i]);

			if (transf) {
				BLI_space_transform_apply(transf, tmp);
			}

			lower = min_ff(lower, tmp[limit_axis]);
			upper = max_ff(upper, tmp[limit_axis]);
		}


		/* SMD values are normalized to the BV, calculate the absolut values */
		smd_limit[1] = lower + (upper - lower) * smd->limit[1];
		smd_limit[0] = lower + (upper - lower) * smd->limit[0];

		smd_factor   = smd->factor / max_ff(FLT_EPSILON, smd_limit[1] - smd_limit[0]);
	}

	switch (smd->mode) {
		case MOD_SIMPLEDEFORM_MODE_TWIST:   simpleDeform_callback = simpleDeform_twist;     break;
		case MOD_SIMPLEDEFORM_MODE_BEND:    simpleDeform_callback = simpleDeform_bend;      break;
		case MOD_SIMPLEDEFORM_MODE_TAPER:   simpleDeform_callback = simpleDeform_taper;     break;
		case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch;   break;
		default:
			return; /* No simpledeform mode? */
	}

	if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) {
		if (fabsf(smd_factor) < BEND_EPS) {
			return;
		}
	}

	modifier_get_vgroup(ob, dm, smd->vgroup_name, &dvert, &vgroup);

	for (i = 0; i < numVerts; i++) {
		float weight = defvert_array_find_weight_safe(dvert, i, vgroup);

		if (weight != 0.0f) {
			float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};

			if (transf) {
				BLI_space_transform_apply(transf, vertexCos[i]);
			}

			copy_v3_v3(co, vertexCos[i]);

			/* Apply axis limits */
			if (smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) { /* Bend mode shoulnt have any lock axis */
				if (smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut);
				if (smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut);
			}
			axis_limit(limit_axis, smd_limit, co, dcut);

			simpleDeform_callback(smd_factor, dcut, co);  /* apply deform */
			interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight);  /* Use vertex weight has coef of linear interpolation */

			if (transf) {
				BLI_space_transform_invert(transf, vertexCos[i]);
			}
		}
	}
}