[Bf-blender-cvs] [dd44754] master: Data Transfer: Add an option to 'auto-transform' destination mesh so that it matches best the source one.

Bastien Montagne noreply at git.blender.org
Mon Jul 13 18:11:02 CEST 2015


Commit: dd44754c5ff3b2f200f5bb256ac9868eb43a65f6
Author: Bastien Montagne
Date:   Mon Jul 13 18:00:08 2015 +0200
Branches: master
https://developer.blender.org/rBdd44754c5ff3b2f200f5bb256ac9868eb43a65f6

Data Transfer: Add an option to 'auto-transform' destination mesh so that it matches best the source one.

This allows to match and transfer data between two meshes with similar shape but complete arbitrary different transform.

Note that the result will be best if the meshes (more precisely, their vertices) are exact copies of each other.
Otherwise, method used can only perform an approximated best match, which means you'll likely get better
results if you 'visually' make them match in 3D space (and use 'Object Transform') instead.

===================================================================

M	source/blender/blenkernel/BKE_data_transfer.h
M	source/blender/blenkernel/BKE_mesh_remap.h
M	source/blender/blenkernel/intern/data_transfer.c
M	source/blender/blenkernel/intern/mesh_remap.c
M	source/blender/editors/object/object_data_transfer.c
M	source/blender/modifiers/intern/MOD_datatransfer.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index cea093a..7c64d52 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 c6d8da1..5c77ab8 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 da00aec..53b6f4a 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 08823c1..c818c6b 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 eig

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list