static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source) { BVHTreeRayHit hit; BVHCallbackUserData data; const MLoopTri *lt; float end[3]; int visible; lt = sys->heat.vltree[vertex]; if (lt == NULL) return 1; data.sys = sys; copy_v3_v3(data.start, sys->heat.verts[vertex]); closest_to_line_segment_v3(end, data.start, sys->heat.root[source], sys->heat.tip[source]); sub_v3_v3v3(data.vec, end, data.start); madd_v3_v3v3fl(data.start, data.start, data.vec, 1e-5); mul_v3_fl(data.vec, 1.0f - 2e-5f); /* pass normalized vec + distance to bvh */ hit.index = -1; hit.dist = normalize_v3(data.vec); visible = BLI_bvhtree_ray_cast(sys->heat.bvhtree, data.start, data.vec, 0.0f, &hit, bvh_callback, (void *)&data) == -1; return visible; }
static float heat_source_distance(LaplacianSystem *sys, int vertex, int source) { float closest[3], d[3], dist, cosine; /* compute euclidian distance */ closest_to_line_segment_v3(closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]); sub_v3_v3v3(d, sys->heat.verts[vertex], closest); dist = normalize_v3(d); /* if the vertex normal does not point along the bone, increase distance */ cosine = dot_v3v3(d, sys->heat.vnors[vertex]); return dist / (0.5f * (cosine + 1.001f)); }
/* Helper, does all the point-spherecast work actually. */ static void mesh_verts_spherecast_do( const BVHTreeFromMesh *UNUSED(data), int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit) { float dist; const float *r1; float r2[3], i1[3]; r1 = ray->origin; add_v3_v3v3(r2, r1, ray->direction); closest_to_line_segment_v3(i1, v, r1, r2); /* No hit if closest point is 'behind' the origin of the ray, or too far away from it. */ if ((dot_v3v3v3(r1, i1, r2) >= 0.0f) && ((dist = len_v3v3(r1, i1)) < hit->dist)) { hit->index = index; hit->dist = dist; copy_v3_v3(hit->co, i1); } }
/* 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) { const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata; const MVert *vert = data->vert; const MEdge *edge = data->edge + index; float nearest_tmp[3], dist_sq; const float *t0, *t1; t0 = vert[edge->v1].co; t1 = vert[edge->v2].co; closest_to_line_segment_v3(nearest_tmp, co, t0, t1); dist_sq = len_squared_v3v3(nearest_tmp, co); if (dist_sq < nearest->dist_sq) { nearest->index = index; nearest->dist_sq = dist_sq; copy_v3_v3(nearest->co, nearest_tmp); sub_v3_v3v3(nearest->no, t0, t1); normalize_v3(nearest->no); } }
// Callback to bvh tree nearest point. The tree must bust 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, BVHTreeNearest *nearest) { const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata; MVert *vert = data->vert; MEdge *edge = data->edge + index; float nearest_tmp[3], dist; float *t0, *t1; t0 = vert[ edge->v1 ].co; t1 = vert[ edge->v2 ].co; // NOTE: casts to "float*" here are due to co being "const float*" closest_to_line_segment_v3(nearest_tmp, (float*)co, t0, t1); dist = len_squared_v3v3(nearest_tmp, (float*)co); if(dist < nearest->dist) { nearest->index = index; nearest->dist = dist; VECCOPY(nearest->co, nearest_tmp); sub_v3_v3v3(nearest->no, t0, t1); normalize_v3(nearest->no); } }