Skip to content

Commit

Permalink
Improved instance bounding box computation
Browse files Browse the repository at this point in the history
  • Loading branch information
madmann91 committed Apr 5, 2024
1 parent 0448117 commit d52f728
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 2 deletions.
38 changes: 38 additions & 0 deletions src/lib/accelerators/bvh.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,44 @@ struct boundingBox get_root_bbox(const struct bvh *bvh) {
return load_bbox_from_node(&bvh->nodes[0]);
}

struct boundingBox get_transformed_root_bbox(const struct bvh *bvh, const struct matrix4x4 *mat) {
// This algorithm recursively traverses the BVH in order to get a better approximation of the
// bounding box of the transformed BVH. An area threshold, expressed as a fraction of the area
// of the root node, is used to stop recursion early: For nodes that have a smaller area, the
// bounding box of the node is used as a proxy for the bounding box of the elements contained
// in the subtree. Thus, the smaller the threshold, the more precise the algorithm is, at the
// cost of more iterations.
const float area_threshold = 0.1f * bboxHalfArea((struct boundingBox[]) { get_root_bbox(bvh) });

index_t stack[MAX_BVH_DEPTH + 1];
index_t top = 0;
size_t stack_size = 0;
struct boundingBox bbox = emptyBBox;

while (true) {
struct bvh_node* node = &bvh->nodes[top];
struct boundingBox node_bbox = load_bbox_from_node(node);

// Stop recursing at a fixed depth, when we hit a leaf, or when the surface area of the bounding
// box is lower than the given threshold.
if (stack_size >= MAX_BVH_DEPTH + 1 ||
node->index.prim_count > 0 ||
bboxHalfArea(&node_bbox) < area_threshold)
{
tform_bbox(&node_bbox, *mat);
extendBBox(&bbox, &node_bbox);
if (stack_size <= 0)
break;
top = stack[--stack_size];
} else {
stack[stack_size++] = node->index.first_child_or_prim + 0;
top = node->index.first_child_or_prim + 1;
}
}

return bbox;
}

struct bvh *build_mesh_bvh(const struct mesh *mesh) {
return build_bvh_generic(mesh, get_poly_bbox_and_center, mesh->polygons.count);
}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/accelerators/bvh.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ struct bvh;
/// Returns the bounding box of the root of the given BVH
struct boundingBox get_root_bbox(const struct bvh *bvh);

/// Returns the transformed bounding box of the BVH, using a better approximation than transforming
/// the root bounding box.
struct boundingBox get_transformed_root_bbox(const struct bvh *bvh, const struct matrix4x4 *);

/// Builds a BVH for a given mesh
/// @param mesh Mesh containing polygons to process
/// @param count Amount of polygons given
Expand Down
3 changes: 1 addition & 2 deletions src/lib/renderer/instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,7 @@ static void getMeshBBoxAndCenter(const struct instance *instance, struct boundin
mesh->rayOffset = 0.0f;
return;
}
*bbox = get_root_bbox(mesh->bvh);
tform_bbox(bbox, instance->composite.A);
*bbox = get_transformed_root_bbox(mesh->bvh, &instance->composite.A);
*center = bboxCenter(bbox);
mesh->rayOffset = rayOffset(*bbox);
}
Expand Down

0 comments on commit d52f728

Please sign in to comment.