Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h8
-rw-r--r--source/blender/blenkernel/BKE_mesh_remap.h8
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c27
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c295
-rw-r--r--source/blender/editors/object/object_data_transfer.c16
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c2
6 files changed, 292 insertions, 64 deletions
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index cea093adca4..7c64d525575 100644
--- a/source/blender/blenkernel/BKE_data_transfer.h
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -136,8 +136,8 @@ bool BKE_object_data_transfer_mesh(
struct Scene *scene,
struct Object *ob_src, struct Object *ob_dst, const int data_types, bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- struct SpaceTransform *space_transform, const float max_distance, const float ray_radius,
- const float islands_handling_precision,
+ struct SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
struct ReportList *reports);
@@ -146,8 +146,8 @@ bool BKE_object_data_transfer_dm(
struct Object *ob_src, struct Object *ob_dst, struct DerivedMesh *dm_dst,
const int data_types, bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- struct SpaceTransform *space_transform, const float max_distance, const float ray_radius,
- const float islands_handling_precision,
+ struct SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
struct ReportList *reports);
diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h
index c6d8da16565..5c77ab8a94e 100644
--- a/source/blender/blenkernel/BKE_mesh_remap.h
+++ b/source/blender/blenkernel/BKE_mesh_remap.h
@@ -140,6 +140,14 @@ enum {
MREMAP_MODE_TOPOLOGY = MREMAP_MODE_VERT | MREMAP_MODE_EDGE | MREMAP_MODE_LOOP | MREMAP_MODE_POLY,
};
+float BKE_mesh_remap_calc_difference_from_dm(
+ const struct SpaceTransform *space_transform,
+ const struct MVert *verts_dst, const int numverts_dst, struct DerivedMesh *dm_src);
+
+void BKE_mesh_remap_find_best_match_from_dm(
+ const struct MVert *verts_dst, const int numverts_dst, struct DerivedMesh *dm_src,
+ struct SpaceTransform *r_space_transform);
+
/* TODO add mesh2mesh versions (we'll need mesh versions of bvhtree funcs too, though!). */
void BKE_mesh_remap_calc_verts_from_dm(
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index da00aecf9c0..53b6f4a1019 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -1064,8 +1064,8 @@ void BKE_object_data_transfer_layout(
bool BKE_object_data_transfer_dm(
Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, const int data_types, bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- SpaceTransform *space_transform, const float max_distance, const float ray_radius,
- const float islands_handling_precision,
+ SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
ReportList *reports)
@@ -1076,6 +1076,8 @@ bool BKE_object_data_transfer_dm(
#define PDATA 3
#define DATAMAX 4
+ SpaceTransform auto_space_transform;
+
DerivedMesh *dm_src;
Mesh *me_dst, *me_src;
bool dirty_nors_dst = true; /* Assumed always true if not using a dm as destination. */
@@ -1126,6 +1128,17 @@ bool BKE_object_data_transfer_dm(
return changed;
}
+ if (auto_transform) {
+ MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
+ const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
+
+ if (space_transform == NULL) {
+ space_transform = &auto_space_transform;
+ }
+
+ BKE_mesh_remap_find_best_match_from_dm(verts_dst, num_verts_dst, dm_src, space_transform);
+ }
+
/* Check all possible data types.
* Note item mappings and dest mix weights are cached. */
for (i = 0; i < DT_TYPE_MAX; i++) {
@@ -1388,15 +1401,17 @@ bool BKE_object_data_transfer_dm(
bool BKE_object_data_transfer_mesh(
Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- SpaceTransform *space_transform, const float max_distance, const float ray_radius,
- const float islands_handling_precision,
+ SpaceTransform *space_transform, const bool auto_transform,
+ const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
ReportList *reports)
{
return BKE_object_data_transfer_dm(
scene, ob_src, ob_dst, NULL, data_types, use_create,
- map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, space_transform,
- max_distance, ray_radius, islands_handling_precision, fromlayers_select, tolayers_select,
+ map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
+ space_transform, auto_transform,
+ max_distance, ray_radius, islands_handling_precision,
+ fromlayers_select, tolayers_select,
mix_mode, mix_factor, vgroup_name, invert_vgroup, reports);
}
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index 08823c1c4a1..c818c6b9f19 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -51,6 +51,250 @@
/* -------------------------------------------------------------------- */
+/** \name Some generic helpers.
+ * \{ */
+
+static bool mesh_remap_bvhtree_query_nearest(
+ BVHTreeFromMesh *treedata, BVHTreeNearest *nearest,
+ const float co[3], const float max_dist_sq, float *r_hit_dist)
+{
+ /* Use local proximity heuristics (to reduce the nearest search). */
+ if (nearest->index != -1) {
+ nearest->dist_sq = min_ff(len_squared_v3v3(co, nearest->co), max_dist_sq);
+ }
+ else {
+ nearest->dist_sq = max_dist_sq;
+ }
+ /* Compute and store result. If invalid (-1 index), keep FLT_MAX dist. */
+ BLI_bvhtree_find_nearest(treedata->tree, co, nearest, treedata->nearest_callback, treedata);
+
+ if ((nearest->index != -1) && (nearest->dist_sq <= max_dist_sq)) {
+ *r_hit_dist = sqrtf(nearest->dist_sq);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static bool mesh_remap_bvhtree_query_raycast(
+ BVHTreeFromMesh *treedata, BVHTreeRayHit *rayhit,
+ const float co[3], const float no[3], const float radius, const float max_dist, float *r_hit_dist)
+{
+ BVHTreeRayHit rayhit_tmp;
+ float inv_no[3];
+
+ rayhit->index = -1;
+ rayhit->dist = max_dist;
+ BLI_bvhtree_ray_cast(treedata->tree, co, no, radius, rayhit, treedata->raycast_callback, treedata);
+
+ /* Also cast in the other direction! */
+ rayhit_tmp = *rayhit;
+ negate_v3_v3(inv_no, no);
+ BLI_bvhtree_ray_cast(treedata->tree, co, inv_no, radius, &rayhit_tmp, treedata->raycast_callback, treedata);
+ if (rayhit_tmp.dist < rayhit->dist) {
+ *rayhit = rayhit_tmp;
+ }
+
+ if ((rayhit->index != -1) && (rayhit->dist <= max_dist)) {
+ *r_hit_dist = rayhit->dist;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/** \} */
+
+/**
+ * \name Auto-match.
+ *
+ * Find transform of a mesh to get best match with another.
+ * \{ */
+
+/**
+ * Compute a value of the difference between both given meshes.
+ * The smaller the result, the better the match.
+ *
+ * We return the inverse of the average of the inversed shortest distance from each dst vertex to src ones.
+ * In other words, beyond a certain (relatively small) distance, all differences have more or less the same weight
+ * in final result, which allows to reduce influence of a few high differences, in favor of a global good matching.
+ */
+float BKE_mesh_remap_calc_difference_from_dm(
+ const SpaceTransform *space_transform, const MVert *verts_dst, const int numverts_dst, DerivedMesh *dm_src)
+{
+ BVHTreeFromMesh treedata = {NULL};
+ BVHTreeNearest nearest = {0};
+ float hit_dist;
+
+ float result = 0.0f;
+ int i;
+
+ bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
+ nearest.index = -1;
+
+ for (i = 0; i < numverts_dst; i++) {
+ float tmp_co[3];
+
+ copy_v3_v3(tmp_co, verts_dst[i].co);
+
+ /* Convert the vertex to tree coordinates, if needed. */
+ if (space_transform) {
+ BLI_space_transform_apply(space_transform, tmp_co);
+ }
+
+ if (mesh_remap_bvhtree_query_nearest(&treedata, &nearest, tmp_co, FLT_MAX, &hit_dist)) {
+ result += 1.0f / (hit_dist + 1.0f);
+ }
+ else {
+ /* No source for this dest vertex! */
+ result += 1e-18f;
+ }
+ }
+
+ result = ((float)numverts_dst / result) - 1.0f;
+
+// printf("%s: Computed difference between meshes (the lower the better): %f\n", __func__, result);
+
+ return result;
+}
+
+/* This helper computes the eigen values & vectors for covariance matrix of all given vertices coordinates.
+ *
+ * Those vectors define the 'average ellipsoid' of the mesh (i.e. the 'best fitting' ellipsoid
+ * containing 50% of the vertices).
+ *
+ * Note that it will not perform fantastic in case two or more eigen values are equal (e.g. a cylinder or
+ * parallelepiped with a square section give two identical eigenvalues, a sphere or tetrahedron give
+ * three identical ones, etc.), since you cannot really define all axes in those cases. We default to dummy
+ * generated orthogonal vectors in this case, instead of using eigen vectors.
+ */
+static void mesh_calc_eigen_matrix(
+ const MVert *verts, const float (*vcos)[3], const int numverts, float r_mat[4][4])
+{
+ float center[3], covmat[3][3];
+ float eigen_val[3], eigen_vec[3][3];
+ float (*cos)[3] = (float (*)[3])vcos;
+
+ bool eigen_success;
+ int i;
+
+ if (verts) {
+ const MVert *mv;
+ float (*co)[3];
+
+ cos = MEM_mallocN(sizeof(*cos) * (size_t)numverts, __func__);
+ for (i = 0, co = cos, mv = verts; i < numverts; i++, co++, mv++) {
+ copy_v3_v3(*co, mv->co);
+ }
+ }
+ unit_m4(r_mat);
+
+ /* Note: here we apply sample correction to covariance matrix, since we consider the vertices as a sample
+ * of the whole 'surface' population of our mesh... */
+ BLI_covariance_m3_v3n(cos, numverts, true, covmat, center);
+
+ eigen_success = BLI_eigen_solve_selfadjoint_m3(covmat, eigen_val, eigen_vec);
+ BLI_assert(eigen_success);
+ UNUSED_VARS_NDEBUG(eigen_success);
+
+ /* Special handling of cases where some eigen values are (nearly) identical. */
+ if (compare_ff_relative(eigen_val[0], eigen_val[1], FLT_EPSILON, 64)) {
+ if (compare_ff_relative(eigen_val[0], eigen_val[2], FLT_EPSILON, 64)) {
+ /* No preferred direction, that set of vertices has a spherical average,
+ * so we simply returned scaled/translated identity matrix (with no rotation). */
+ unit_m3(eigen_vec);
+ }
+ else {
+ /* Ellipsoid defined by eigen values/vectors has a spherical section,
+ * we can only define one axis from eigen_vec[2] (two others computed eigen vecs
+ * are not so nice for us here, they tend to 'randomly' rotate around valid one).
+ * Note that eigen vectors as returned by BLI_eigen_solve_selfadjoint_m3() are normalized. */
+ ortho_basis_v3v3_v3(eigen_vec[0], eigen_vec[1], eigen_vec[2]);
+ }
+ }
+ else if (compare_ff_relative(eigen_val[0], eigen_val[2], FLT_EPSILON, 64)) {
+ /* Same as above, but with eigen_vec[1] as valid axis. */
+ ortho_basis_v3v3_v3(eigen_vec[2], eigen_vec[0], eigen_vec[1]);
+ }
+ else if (compare_ff_relative(eigen_val[1], eigen_val[2], FLT_EPSILON, 64)) {
+ /* Same as above, but with eigen_vec[0] as valid axis. */
+ ortho_basis_v3v3_v3(eigen_vec[1], eigen_vec[2], eigen_vec[0]);
+ }
+
+ for (i = 0; i < 3; i++) {
+ float evi = eigen_val[i];
+
+ /* Protect against 1D/2D degenerated cases! */
+ /* Note: not sure why we need square root of eigen values here (which are equivalent to singular values,
+ * as far as I have understood), but it seems to heavily reduce (if not completly nullify)
+ * the error due to non-uniform scalings... */
+ evi = (evi < 1e-6f && evi > -1e-6f) ? ((evi < 0.0f) ? -1e-3f : 1e-3f) : sqrtf_signed(evi);
+ mul_v3_fl(eigen_vec[i], evi);
+ }
+
+ copy_m4_m3(r_mat, eigen_vec);
+ copy_v3_v3(r_mat[3], center);
+
+ if (verts) {
+ MEM_freeN(cos);
+ }
+}
+
+/**
+ * Set r_space_transform so that best bbox of dst matches best bbox of src.
+ */
+void BKE_mesh_remap_find_best_match_from_dm(
+ const MVert *verts_dst, const int numverts_dst, DerivedMesh *dm_src, SpaceTransform *r_space_transform)
+{
+ /* Note that those are done so that we successively get actual mirror matrix (by multiplication of columns)... */
+ const float mirrors[][3] = {
+ {-1.0f, 1.0f, 1.0f}, /* -> -1, 1, 1 */
+ { 1.0f, -1.0f, 1.0f}, /* -> -1, -1, 1 */
+ { 1.0f, 1.0f, -1.0f}, /* -> -1, -1, -1 */
+ { 1.0f, -1.0f, 1.0f}, /* -> -1, 1, -1 */
+ {-1.0f, 1.0f, 1.0f}, /* -> 1, 1, -1 */
+ { 1.0f, -1.0f, 1.0f}, /* -> 1, -1, -1 */
+ { 1.0f, 1.0f, -1.0f}, /* -> 1, -1, 1 */
+ {0.0f, 0.0f, 0.0f},
+ };
+ const float (*mirr)[3];
+
+ float mat_src[4][4], mat_dst[4][4], best_mat_dst[4][4];
+ float best_match = FLT_MAX, match;
+
+ const int numverts_src = dm_src->getNumVerts(dm_src);
+ float (*vcos_src)[3] = MEM_mallocN(sizeof(*vcos_src) * (size_t)numverts_src, __func__);
+ dm_src->getVertCos(dm_src, vcos_src);
+
+ mesh_calc_eigen_matrix(NULL, vcos_src, numverts_src, mat_src);
+ mesh_calc_eigen_matrix(verts_dst, NULL, numverts_dst, mat_dst);
+
+ BLI_space_transform_global_from_matrices(r_space_transform, mat_dst, mat_src);
+ match = BKE_mesh_remap_calc_difference_from_dm(r_space_transform, verts_dst, numverts_dst, dm_src);
+ best_match = match;
+ copy_m4_m4(best_mat_dst, mat_dst);
+
+ /* And now, we have to check the otehr sixth possible mirrored versions... */
+ for (mirr = mirrors; (*mirr)[0]; mirr++) {
+ mul_v3_fl(mat_dst[0], (*mirr)[0]);
+ mul_v3_fl(mat_dst[1], (*mirr)[1]);
+ mul_v3_fl(mat_dst[2], (*mirr)[2]);
+
+ BLI_space_transform_global_from_matrices(r_space_transform, mat_dst, mat_src);
+ match = BKE_mesh_remap_calc_difference_from_dm(r_space_transform, verts_dst, numverts_dst, dm_src);
+ if (match < best_match) {
+ best_match = match;
+ copy_m4_m4(best_mat_dst, mat_dst);
+ }
+ }
+
+ BLI_space_transform_global_from_matrices(r_space_transform, best_mat_dst, mat_src);
+}
+
+/** \} */
+
/** \name Mesh to mesh mapping
* \{ */
@@ -147,57 +391,6 @@ static int mesh_remap_interp_poly_data_get(
return sources_num;
}
-static bool mesh_remap_bvhtree_query_nearest(
- BVHTreeFromMesh *treedata, BVHTreeNearest *nearest,
- float co[3], const float max_dist_sq, float *r_hit_dist)
-{
- /* Use local proximity heuristics (to reduce the nearest search). */
- if (nearest->index != -1) {
- nearest->dist_sq = min_ff(len_squared_v3v3(co, nearest->co), max_dist_sq);
- }
- else {
- nearest->dist_sq = max_dist_sq;
- }
- /* Compute and store result. If invalid (-1 index), keep FLT_MAX dist. */
- BLI_bvhtree_find_nearest(treedata->tree, co, nearest, treedata->nearest_callback, treedata);
-
- if ((nearest->index != -1) && (nearest->dist_sq <= max_dist_sq)) {
- *r_hit_dist = sqrtf(nearest->dist_sq);
- return true;
- }
- else {
- return false;
- }
-}
-
-static bool mesh_remap_bvhtree_query_raycast(
- BVHTreeFromMesh *treedata, BVHTreeRayHit *rayhit,
- const float co[3], const float no[3], const float radius, const float max_dist, float *r_hit_dist)
-{
- BVHTreeRayHit rayhit_tmp;
- float inv_no[3];
-
- rayhit->index = -1;
- rayhit->dist = max_dist;
- BLI_bvhtree_ray_cast(treedata->tree, co, no, radius, rayhit, treedata->raycast_callback, treedata);
-
- /* Also cast in the other direction! */
- rayhit_tmp = *rayhit;
- negate_v3_v3(inv_no, no);
- BLI_bvhtree_ray_cast(treedata->tree, co, inv_no, radius, &rayhit_tmp, treedata->raycast_callback, treedata);
- if (rayhit_tmp.dist < rayhit->dist) {
- *rayhit = rayhit_tmp;
- }
-
- if ((rayhit->index != -1) && (rayhit->dist <= max_dist)) {
- *r_hit_dist = rayhit->dist;
- return true;
- }
- else {
- return false;
- }
-}
-
/* Little helper when dealing with source islands */
typedef struct IslandResult {
float factor; /* A factor, based on which best island for a given set of elements will be selected. */
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index d6a1694b4b0..0b604a73977 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -339,6 +339,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
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;
@@ -355,7 +356,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
SpaceTransform space_transform_data;
- SpaceTransform *space_transform = use_object_transform ? &space_transform_data : NULL;
+ SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ? &space_transform_data : NULL;
if (reverse_transfer && ((ID *)(ob_src->data))->lib) {
/* Do not transfer to linked data, not supported. */
@@ -384,7 +385,8 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
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, max_distance, ray_radius, islands_precision,
+ 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))
{
@@ -428,9 +430,13 @@ static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
const char *prop_id = RNA_property_identifier(prop);
const int data_type = RNA_enum_get(ptr, "data_type");
+ bool use_auto_transform = false;
bool use_max_distance = false;
bool use_modifier = false;
+ if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
+ use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
+ }
if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
use_max_distance = RNA_property_boolean_get(ptr, prop_other);
}
@@ -447,6 +453,9 @@ static bool data_transfer_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
return false;
}
+ if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
+ return false;
+ }
if (STREQ(prop_id, "max_distance") && !use_max_distance) {
return false;
}
@@ -530,6 +539,9 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
"Method used to map source faces to destination ones");
/* Mapping options and filtering. */
+ RNA_def_boolean(ot->srna, "use_auto_transform", false, "Auto Transform",
+ "Automatically compute transformation to get the best possible match between source and "
+ "destination meshes (WARNING: results will never be as good as manual matching of objects)");
RNA_def_boolean(ot->srna, "use_object_transform", true, "Object Transform",
"Evaluate source and destination meshes in global space");
RNA_def_boolean(ot->srna, "use_max_distance", false, "Only Neighbor Geometry",
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index e133c4785b7..85e9b4ee185 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -208,7 +208,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
/* 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,
+ space_transform, false, 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);