Skip to content

Commit

Permalink
Cleanup intersection
Browse files Browse the repository at this point in the history
  • Loading branch information
xelatihy committed Jan 30, 2024
1 parent d523a61 commit 07c009a
Showing 1 changed file with 83 additions and 140 deletions.
223 changes: 83 additions & 140 deletions libs/yocto/yocto_raycasting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,67 @@ static intersection3f intersect_elements_bvh(const bvh_tree& bvh,
return intersection;
}

template <typename Intersect>
static intersection3f intersect_instances_bvh(const bvh_tree& bvh,
const ray3f& ray_, bool find_any, Intersect&& intersect_element) {
// check empty
if (bvh.nodes.empty()) return {};

// node stack
auto node_stack = array<int, 128>{};
auto node_cur = 0;
node_stack[node_cur++] = 0;

// intersection
auto intersection = intersection3f{};

// copy ray to modify it
auto ray = ray_;

// prepare ray for fast queries
auto ray_dinv = vec3f{1 / ray.d.x, 1 / ray.d.y, 1 / ray.d.z};
auto ray_dsign = vec3i{(ray_dinv.x < 0) ? 1 : 0, (ray_dinv.y < 0) ? 1 : 0,
(ray_dinv.z < 0) ? 1 : 0};

// walking stack
while (node_cur != 0) {
// grab node
auto& node = bvh.nodes[node_stack[--node_cur]];

// intersect bbox
// if (!intersect_bbox(ray, ray_dinv, ray_dsign, node.bbox)) continue;
if (!intersect_bbox(ray, ray_dinv, node.bbox)) continue;

// intersect node, switching based on node type
// for each type, iterate over the the primitive list
if (node.internal) {
// for internal nodes, attempts to proceed along the
// split axis from smallest to largest nodes
if (ray_dsign[node.axis] != 0) {
node_stack[node_cur++] = node.start + 0;
node_stack[node_cur++] = node.start + 1;
} else {
node_stack[node_cur++] = node.start + 1;
node_stack[node_cur++] = node.start + 0;
}
} else {
for (auto idx : range(node.num)) {
auto primitive = bvh.primitives[node.start + idx];
auto sintersection = intersect_element(primitive, ray);
if (!sintersection.hit) continue;
intersection = {primitive, sintersection.element, sintersection.uv,
sintersection.distance};
ray.tmax = sintersection.distance;
}
}

// check for early exit
if (find_any && intersection.hit) return intersection;
}

return intersection;
}

// Intersect ray with a bvh.
template <typename Overlap>
static intersection3f overlap_elements_bvh(const bvh_tree& bvh, vec3f pos,
Expand Down Expand Up @@ -730,68 +791,14 @@ intersection3f intersect_shape_bvh(const shape_bvh& sbvh,
}

intersection3f intersect_scene_bvh(const scene_bvh& sbvh,
const scene_data& scene, const ray3f& ray_, bool find_any) {
// get instances bvh
auto& bvh = sbvh.bvh;

// check empty
if (bvh.nodes.empty()) return {};

// node stack
auto node_stack = array<int, 128>{};
auto node_cur = 0;
node_stack[node_cur++] = 0;

// intersection
auto intersection = intersection3f{};

// copy ray to modify it
auto ray = ray_;

// prepare ray for fast queries
auto ray_dinv = vec3f{1 / ray.d.x, 1 / ray.d.y, 1 / ray.d.z};
auto ray_dsign = vec3i{(ray_dinv.x < 0) ? 1 : 0, (ray_dinv.y < 0) ? 1 : 0,
(ray_dinv.z < 0) ? 1 : 0};

// walking stack
while (node_cur != 0) {
// grab node
auto& node = bvh.nodes[node_stack[--node_cur]];

// intersect bbox
// if (!intersect_bbox(ray, ray_dinv, ray_dsign, node.bbox)) continue;
if (!intersect_bbox(ray, ray_dinv, node.bbox)) continue;

// intersect node, switching based on node type
// for each type, iterate over the the primitive list
if (node.internal) {
// for internal nodes, attempts to proceed along the
// split axis from smallest to largest nodes
if (ray_dsign[node.axis] != 0) {
node_stack[node_cur++] = node.start + 0;
node_stack[node_cur++] = node.start + 1;
} else {
node_stack[node_cur++] = node.start + 1;
node_stack[node_cur++] = node.start + 0;
}
} else {
for (auto idx = node.start; idx < node.start + node.num; idx++) {
auto& instance_ = scene.instances[bvh.primitives[idx]];
auto inv_ray = transform_ray(inverse(instance_.frame, true), ray);
auto sintersection = intersect_shape_bvh(sbvh.shapes[instance_.shape],
scene.shapes[instance_.shape], inv_ray, find_any);
if (!sintersection.hit) continue;
intersection = {bvh.primitives[idx], sintersection.element,
sintersection.uv, sintersection.distance};
ray.tmax = sintersection.distance;
}
}

// check for early exit
if (find_any && intersection.hit) return intersection;
}

return intersection;
const scene_data& scene, const ray3f& ray, bool find_any) {
return intersect_instances_bvh(
sbvh.bvh, ray, find_any, [&](int idx, const ray3f& ray) {
auto& instance = scene.instances[idx];
auto inv_ray = transform_ray(inverse(instance.frame, true), ray);
return intersect_shape_bvh(sbvh.shapes[instance.shape],
scene.shapes[instance.shape], inv_ray, find_any);
});
}

intersection3f intersect_instance_bvh(const scene_bvh& sbvh,
Expand All @@ -815,85 +822,21 @@ namespace yocto {
// Intersect ray with a bvh.
intersection3f overlap_shape_bvh(const shape_bvh& sbvh, const shape_data& shape,
vec3f pos, float max_distance, bool find_any) {
// get bvh tree
auto& bvh = sbvh.bvh;

// check if empty
if (bvh.nodes.empty()) return {};

// node stack
auto node_stack = array<int, 64>{};
auto node_cur = 0;
node_stack[node_cur++] = 0;

// intersection
auto intersection = intersection3f{};

// walking stack
while (node_cur != 0) {
// grab node
auto& node = bvh.nodes[node_stack[--node_cur]];

// intersect bbox
if (!overlap_bbox(pos, max_distance, node.bbox)) continue;

// intersect node, switching based on node type
// for each type, iterate over the the primitive list
if (node.internal) {
// internal node
node_stack[node_cur++] = node.start + 0;
node_stack[node_cur++] = node.start + 1;
} else if (!shape.points.empty()) {
for (auto idx : range(node.num)) {
auto primitive = bvh.primitives[node.start + idx];
auto& p = shape.points[primitive];
auto eintersection = overlap_point(
pos, max_distance, shape.positions[p], shape.radius[p]);
if (!eintersection.hit) continue;
intersection = {primitive, eintersection.uv, eintersection.distance};
max_distance = eintersection.distance;
}
} else if (!shape.lines.empty()) {
for (auto idx : range(node.num)) {
auto primitive = bvh.primitives[node.start + idx];
auto& l = shape.lines[primitive];
auto eintersection = overlap_line(pos, max_distance,
shape.positions[l.x], shape.positions[l.y], shape.radius[l.x],
shape.radius[l.y]);
if (!eintersection.hit) continue;
intersection = {primitive, eintersection.uv, eintersection.distance};
max_distance = eintersection.distance;
}
} else if (!shape.triangles.empty()) {
for (auto idx : range(node.num)) {
auto primitive = bvh.primitives[node.start + idx];
auto& t = shape.triangles[primitive];
auto eintersection = overlap_triangle(pos, max_distance,
shape.positions[t.x], shape.positions[t.y], shape.positions[t.z],
shape.radius[t.x], shape.radius[t.y], shape.radius[t.z]);
if (!eintersection.hit) continue;
intersection = {primitive, eintersection.uv, eintersection.distance};
max_distance = eintersection.distance;
}
} else if (!shape.quads.empty()) {
for (auto idx : range(node.num)) {
auto primitive = bvh.primitives[node.start + idx];
auto& q = shape.quads[primitive];
auto eintersection = overlap_quad(pos, max_distance,
shape.positions[q.x], shape.positions[q.y], shape.positions[q.z],
shape.positions[q.w], shape.radius[q.x], shape.radius[q.y],
shape.radius[q.z], shape.radius[q.w]);
if (!eintersection.hit) continue;
intersection = {primitive, eintersection.uv, eintersection.distance};
max_distance = eintersection.distance;
}
}

// check for early exit
if (find_any && intersection.hit) return intersection;
if (!shape.points.empty()) {
return overlap_points_bvh(sbvh.bvh, shape.points, shape.positions,
shape.radius, pos, max_distance, find_any);
} else if (!shape.lines.empty()) {
return overlap_lines_bvh(sbvh.bvh, shape.lines, shape.positions,
shape.radius, pos, max_distance, find_any);
} else if (!shape.triangles.empty()) {
return overlap_triangles_bvh(sbvh.bvh, shape.triangles, shape.positions,
shape.radius, pos, max_distance, find_any);
} else if (!shape.quads.empty()) {
return overlap_quads_bvh(sbvh.bvh, shape.quads, shape.positions,
shape.radius, pos, max_distance, find_any);
} else {
return {};
}

return intersection;
}

// Intersect ray with a bvh.
Expand Down

0 comments on commit 07c009a

Please sign in to comment.