[Bf-blender-cvs] [dc162aa] mesh-transfer-data: More fixes and refinements:

Bastien Montagne noreply at git.blender.org
Wed Oct 15 21:37:23 CEST 2014


Commit: dc162aa815e7b20b66ba6d0fae94587c0d2ebbe2
Author: Bastien Montagne
Date:   Wed Oct 15 21:32:14 2014 +0200
Branches: mesh-transfer-data
https://developer.blender.org/rBdc162aa815e7b20b66ba6d0fae94587c0d2ebbe2

More fixes and refinements:

* Now edge projection starts to show some results (quite useful for things like edge seam transfer).
* Better handling of bitflags default 'interpolation' (binary-choose value representing the highest sum of weights).

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

M	source/blender/blenkernel/intern/bvhutils.c
M	source/blender/blenkernel/intern/customdata.c
M	source/blender/blenkernel/intern/mesh_mapping.c
M	source/blender/editors/object/object_transfer_data.c

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

diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index db2ef85..b8b39b2 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -81,7 +81,7 @@ static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, con
  * BVH from meshes callbacks
  */
 
-/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_faces.
  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
 static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
 {
@@ -145,7 +145,7 @@ static void editmesh_faces_nearest_point(void *userdata, int index, const float
 	}
 }
 
-/* Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces.
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_faces.
  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
 static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
 {
@@ -214,7 +214,7 @@ static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRa
 	}
 }
 
-/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges.
+/* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_edges.
  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
 static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
 {
@@ -272,7 +272,7 @@ static void mesh_verts_spherecast_do(
 	}
 }
 
-/* Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_verts.
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_verts.
  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
 static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
 {
@@ -282,7 +282,7 @@ static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *r
 	mesh_verts_spherecast_do(data, index, v, ray, hit);
 }
 
-/* Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_edges.
+/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_edges.
  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
 static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
 {
@@ -290,6 +290,7 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r
 	MVert *vert = data->vert;
 	MEdge *edge = &data->edge[index];
 
+	const float radius_sq = SQUARE(data->sphere_radius);
 	float dist;
 	const float *v1, *v2, *r1;
 	float r2[3], i1[3], i2[3];
@@ -308,9 +309,19 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r
 	if (isect_line_line_v3(v1, v2, r1, r2, i1, i2)) {
 		/* No hit if intersection point is 'behind' the origin of the ray, or too far away from it. */
 		if ((dot_v3v3v3(r1, i2, r2) >= 0.0f) && ((dist = len_v3v3(r1, i2)) < hit->dist)) {
-			hit->index = index;
-			hit->dist = dist;
-			copy_v3_v3(hit->co, i2);
+			const float e_fac = line_point_factor_v3(i1, v1, v2);
+			if (e_fac < 0.0f) {
+				copy_v3_v3(i1, v1);
+			}
+			else if (e_fac > 1.0f) {
+				copy_v3_v3(i1, v2);
+			}
+			/* Ensure ray is really close enough from edge! */
+			if (len_squared_v3v3(i1, i2) <= radius_sq) {
+				hit->index = index;
+				hit->dist = dist;
+				copy_v3_v3(hit->co, i2);
+			}
 		}
 	}
 }
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 0914a92..be3a523 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -3480,51 +3480,120 @@ void CustomData_external_remove_object(CustomData *data, ID *id)
 static void customdata_data_transfer_interp_generic(const DataTransferLayerMapping *laymap, void **sources,
                                                     const float *weights, int count, void *data_dst)
 {
+#define COPY_BIT_FLAG(_type, _dst, _src, _f)                    \
+{                                                               \
+	const _type _flag = *((_type *)(_src)) & ((_type)(_f));     \
+	*((_type *)(_dst)) &= ~(_f);                                \
+	*((_type *)(_dst)) |= _flag;                                \
+} (void) 0
+#define CHECK_BIT_FLAG(_type, _item, _f) ((*((_type *)(_item)) & ((_type)(_f))) != 0)
+
 	/* Fake interpolation, we actually copy highest weighted source to dest.
-	 * Note we also handle bitflags here. */
+	 * Note we also handle bitflags here, in which case we rather choose to transfer value of elements totalizing
+	 * more than 0.5 of weight. */
 
-	int max_weight_idx = 0;
+	int best_src_idx = 0;
 
 	const size_t data_size = laymap->data_size;
 	const uint64_t data_flag = laymap->data_flag;
 
 	if (count > 1) {
-		float max_weight = 0.0f;
 		int i;
 
-		for (i = 0; i < count; i++) {
-			if (weights[i] > max_weight) {
-				max_weight = weights[i];
-				max_weight_idx = i;
+		if (data_flag) {
+			/* Boolean case, we can 'interpolate' in two groups, and choose value from highest weighted group. */
+			float tot_weight_true = 0.0f, tot_weight_false = 0.0f;
+			int item_true_idx = -1, item_false_idx = -1;
+
+			for (i = 0; i < count; i++) {
+				switch (data_size) {
+					case 1:
+						if (CHECK_BIT_FLAG(uint8_t, sources[i], data_flag)) {
+							tot_weight_true += weights[i];
+							item_true_idx = i;
+						}
+						else {
+							tot_weight_false += weights[i];
+							item_false_idx = i;
+						}
+						break;
+					case 2:
+						if (CHECK_BIT_FLAG(uint32_t, sources[i], data_flag)) {
+							tot_weight_true += weights[i];
+							item_true_idx = i;
+						}
+						else {
+							tot_weight_false += weights[i];
+							item_false_idx = i;
+						}
+						break;
+					case 4:
+						if (CHECK_BIT_FLAG(uint32_t, sources[i], data_flag)) {
+							tot_weight_true += weights[i];
+							item_true_idx = i;
+						}
+						else {
+							tot_weight_false += weights[i];
+							item_false_idx = i;
+						}
+						break;
+					case 8:
+						if (CHECK_BIT_FLAG(uint64_t, sources[i], data_flag)) {
+							tot_weight_true += weights[i];
+							item_true_idx = i;
+						}
+						else {
+							tot_weight_false += weights[i];
+							item_false_idx = i;
+						}
+						break;
+					default:
+						//printf("ERROR %s: Unknown flags-container size (%zu)\n", __func__, datasize);
+						break;
+				}
+			}
+			best_src_idx = (tot_weight_true >= 0.5f) ? item_true_idx : item_false_idx;
+		}
+		else {
+			/* We just choose highest weighted source. */
+			float max_weight = 0.0f;
+
+			for (i = 0; i < count; i++) {
+				if (weights[i] > max_weight) {
+					max_weight = weights[i];
+					best_src_idx = i;
+				}
 			}
 		}
 	}
 
+	BLI_assert(best_src_idx >= 0);
+
 	if (data_flag) {
-#define COPY_BIT_FLAG(_type, _dst, _src, _f)                    \
-{                                                               \
-	const _type _flag = *((_type *)(_src)) & ((_type)(_f));     \
-	*((_type *)(_dst)) &= ~(_f);                                \
-	*((_type *)(_dst)) |= _flag;                                \
-} (void) 0
 		switch (data_size) {
 			case 1:
-				COPY_BIT_FLAG(uint8_t, data_dst, sources[max_weight_idx], data_flag);
+				COPY_BIT_FLAG(uint8_t, data_dst, sources[best_src_idx], data_flag);
+				break;
 			case 2:
-				COPY_BIT_FLAG(uint16_t, data_dst, sources[max_weight_idx], data_flag);
+				COPY_BIT_FLAG(uint16_t, data_dst, sources[best_src_idx], data_flag);
+				break;
 			case 4:
-				COPY_BIT_FLAG(uint32_t, data_dst, sources[max_weight_idx], data_flag);
+				COPY_BIT_FLAG(uint32_t, data_dst, sources[best_src_idx], data_flag);
+				break;
 			case 8:
-				COPY_BIT_FLAG(uint64_t, data_dst, sources[max_weight_idx], data_flag);
+				COPY_BIT_FLAG(uint64_t, data_dst, sources[best_src_idx], data_flag);
+				break;
 			default:
 				//printf("ERROR %s: Unknown flags-container size (%zu)\n", __func__, datasize);
 				break;
 		}
-#undef COPY_BIT_FLAG
 	}
 	else {
-		memcpy(data_dst, sources[max_weight_idx], data_size);
+		memcpy(data_dst, sources[best_src_idx], data_size);
 	}
+
+#undef COPY_BIT_FLAG
+#undef CHECK_BIT_FLAG
 }
 
 void CustomData_data_transfer(const Mesh2MeshMapping *m2mmap, const DataTransferLayerMapping *laymap)
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 6ecb0dc..f2fe8b1 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -1255,13 +1255,15 @@ void BKE_dm2mesh_mapping_edges_compute(
 			MEM_freeN(vcos_src);
 		}
 		else if (mode == M2MMAP_MODE_EDGE_EDGEINTERP_VNORPROJ) {
+			const int num_rays_min = 5, num_rays_max = 100;
 			const int numedges_src = dm_src->getNumEdges(dm_src);
 
+			/* Subtleness - this one we can allocate only max number of cast rays per edges! */
+			int *indices = MEM_mallocN(sizeof(*indices) * (size_t)min_ii(numedges_src, num_rays_max), __func__);
 			/* Here it's simpler to just allocate for all edges :/ */
-			int *indices = MEM_mallocN(sizeof(*indices) * (size_t)numedges_src, __func__);
 			float *weights = MEM_mallocN(sizeof(*weights) * (size_t)numedges_src, __func__);
 
-			bvhtree_from_mesh_edges(&treedata, dm_src, 0.0f, 2, 6);
+			bvhtree_from_mesh_edges(&treedata, dm_src, ray_radius, 2, 6);
 
 			for (i = 0; i < numedges_dst; i++) {
 				/* For each dst edge, we sample some rays from it (interpolated from its vertices)
@@ -1300,9 +1302,9 @@ void BKE_dm2mesh_mapping_edges_compute(
 				edge_dst_len = len_v3v3(v1_co, v2_co);
 
 				grid_size = (int)((edge_dst_len / ray_radius) + 0.5f);
-				CLAMP(grid_size, 5, 100);  /* min 5 rays/edge, max 100. */
+				CLAMP(grid_size, num_rays_min, num_rays_max);  /* min 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list