[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