Split ray_face_intersection into quad/tri versions

Since many callers only need a single triangle
This commit is contained in:
2015-07-17 04:15:24 +10:00
parent 595a491e63
commit 9d090c4717
5 changed files with 91 additions and 63 deletions

View File

@@ -97,14 +97,15 @@ void BKE_pbvh_raycast(
const float ray_start[3], const float ray_normal[3],
bool original);
bool BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
const float ray_start[3], const float ray_normal[3],
float *dist);
bool BKE_pbvh_node_raycast(
PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
const float ray_start[3], const float ray_normal[3],
float *dist);
bool BKE_pbvh_bmesh_node_raycast_detail(
PBVHNode *node,
const float ray_start[3], const float ray_normal[3],
float *detail, float *dist);
float *dist, float *r_detail);
/* for orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision. */

View File

@@ -1503,18 +1503,17 @@ void BKE_pbvh_raycast(
BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
}
bool ray_face_intersection(const float ray_start[3],
const float ray_normal[3],
const float t0[3], const float t1[3],
const float t2[3], const float t3[3],
float *fdist)
bool ray_face_intersection_quad(
const float ray_start[3], const float ray_normal[3],
const float t0[3], const float t1[3], const float t2[3], const float t3[3],
float *dist)
{
float dist;
float dist_test;
if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist, NULL, 0.1f) && dist < *fdist) ||
(t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist))
if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist_test, NULL, 0.1f) && (dist_test < *dist)) ||
(isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist_test, NULL, 0.1f) && (dist_test < *dist)))
{
*fdist = dist;
*dist = dist_test;
return true;
}
else {
@@ -1522,10 +1521,27 @@ bool ray_face_intersection(const float ray_start[3],
}
}
static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
const float ray_normal[3], float *dist)
bool ray_face_intersection_tri(
const float ray_start[3], const float ray_normal[3],
const float t0[3], const float t1[3], const float t2[3],
float *dist)
{
float dist_test;
if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist_test, NULL, 0.1f) && (dist_test < *dist))) {
*dist = dist_test;
return true;
}
else {
return false;
}
}
static bool pbvh_faces_node_raycast(
PBVH *bvh, const PBVHNode *node,
float (*origco)[3],
const float ray_start[3], const float ray_normal[3],
float *dist)
{
const MVert *vert = bvh->verts;
const MLoop *mloop = bvh->mloop;
@@ -1542,21 +1558,21 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
if (origco) {
/* intersect with backuped original coordinates */
hit |= ray_face_intersection(ray_start, ray_normal,
origco[face_verts[0]],
origco[face_verts[1]],
origco[face_verts[2]],
NULL,
dist);
hit |= ray_face_intersection_tri(
ray_start, ray_normal,
origco[face_verts[0]],
origco[face_verts[1]],
origco[face_verts[2]],
dist);
}
else {
/* intersect with current coordinates */
hit |= ray_face_intersection(ray_start, ray_normal,
vert[mloop[lt->tri[0]].v].co,
vert[mloop[lt->tri[1]].v].co,
vert[mloop[lt->tri[2]].v].co,
NULL,
dist);
hit |= ray_face_intersection_tri(
ray_start, ray_normal,
vert[mloop[lt->tri[0]].v].co,
vert[mloop[lt->tri[1]].v].co,
vert[mloop[lt->tri[2]].v].co,
dist);
}
}
@@ -1592,20 +1608,22 @@ static bool pbvh_grids_node_raycast(
}
if (origco) {
hit |= ray_face_intersection(ray_start, ray_normal,
origco[y * gridsize + x],
origco[y * gridsize + x + 1],
origco[(y + 1) * gridsize + x + 1],
origco[(y + 1) * gridsize + x],
dist);
hit |= ray_face_intersection_quad(
ray_start, ray_normal,
origco[y * gridsize + x],
origco[y * gridsize + x + 1],
origco[(y + 1) * gridsize + x + 1],
origco[(y + 1) * gridsize + x],
dist);
}
else {
hit |= ray_face_intersection(ray_start, ray_normal,
CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
dist);
hit |= ray_face_intersection_quad(
ray_start, ray_normal,
CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
dist);
}
}
}
@@ -1629,15 +1647,18 @@ bool BKE_pbvh_node_raycast(
switch (bvh->type) {
case PBVH_FACES:
hit |= pbvh_faces_node_raycast(bvh, node, origco,
ray_start, ray_normal, dist);
hit |= pbvh_faces_node_raycast(
bvh, node, origco,
ray_start, ray_normal, dist);
break;
case PBVH_GRIDS:
hit |= pbvh_grids_node_raycast(bvh, node, origco,
ray_start, ray_normal, dist);
hit |= pbvh_grids_node_raycast(
bvh, node, origco,
ray_start, ray_normal, dist);
break;
case PBVH_BMESH:
hit = pbvh_bmesh_node_raycast(node, ray_start, ray_normal, dist, use_origco);
hit = pbvh_bmesh_node_raycast(
node, ray_start, ray_normal, dist, use_origco);
break;
}

View File

@@ -1358,11 +1358,12 @@ bool pbvh_bmesh_node_raycast(
int i;
for (i = 0; i < node->bm_tot_ortri; i++) {
const int *t = node->bm_ortri[i];
hit |= ray_face_intersection(ray_start, ray_normal,
node->bm_orco[t[0]],
node->bm_orco[t[1]],
node->bm_orco[t[2]],
NULL, dist);
hit |= ray_face_intersection_tri(
ray_start, ray_normal,
node->bm_orco[t[0]],
node->bm_orco[t[1]],
node->bm_orco[t[2]],
dist);
}
}
else {
@@ -1376,11 +1377,12 @@ bool pbvh_bmesh_node_raycast(
BMVert *v_tri[3];
BM_face_as_array_vert_tri(f, v_tri);
hit |= ray_face_intersection(ray_start, ray_normal,
v_tri[0]->co,
v_tri[1]->co,
v_tri[2]->co,
NULL, dist);
hit |= ray_face_intersection_tri(
ray_start, ray_normal,
v_tri[0]->co,
v_tri[1]->co,
v_tri[2]->co,
dist);
}
}
}
@@ -1391,7 +1393,7 @@ bool pbvh_bmesh_node_raycast(
bool BKE_pbvh_bmesh_node_raycast_detail(
PBVHNode *node,
const float ray_start[3], const float ray_normal[3],
float *detail, float *dist)
float *dist, float *r_detail)
{
GSetIterator gs_iter;
bool hit = false;
@@ -1408,12 +1410,12 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
BMVert *v_tri[3];
bool hit_local;
BM_face_as_array_vert_tri(f, v_tri);
hit_local = ray_face_intersection(
hit_local = ray_face_intersection_tri(
ray_start, ray_normal,
v_tri[0]->co,
v_tri[1]->co,
v_tri[2]->co,
NULL, dist);
dist);
if (hit_local) {
f_hit = f;
@@ -1431,7 +1433,7 @@ bool BKE_pbvh_bmesh_node_raycast_detail(
len3 = len_squared_v3v3(v_tri[2]->co, v_tri[0]->co);
/* detail returned will be set to the maximum allowed size, so take max here */
*detail = sqrtf(max_fff(len1, len2, len3));
*r_detail = sqrtf(max_fff(len1, len2, len3));
}
return hit;

View File

@@ -176,10 +176,14 @@ void BB_expand_with_bb(BB *bb, BB *bb2);
void BBC_update_centroid(BBC *bbc);
int BB_widest_axis(const BB *bb);
void pbvh_grow_nodes(PBVH *bvh, int totnode);
bool ray_face_intersection(
bool ray_face_intersection_quad(
const float ray_start[3], const float ray_normal[3],
const float *t0, const float *t1, const float *t2, const float *t3,
float *r_dist);
bool ray_face_intersection_tri(
const float ray_start[3], const float ray_normal[3],
const float *t0, const float *t1, const float *t2,
const float *t3, float *fdist);
float *r_dist);
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
/* pbvh_bmesh.c */

View File

@@ -4132,7 +4132,7 @@ static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
SculptDetailRaycastData *srd = data_v;
if (BKE_pbvh_bmesh_node_raycast_detail(node, srd->ray_start, srd->ray_normal,
&srd->detail, &srd->dist))
&srd->dist, &srd->detail))
{
srd->hit = 1;
*tmin = srd->dist;