rayt/src/old_cuda_c_src/old_rayt_bvh.cu
2025-05-06 21:39:21 +02:00

137 lines
3.7 KiB
Plaintext

__host__ function BVH
bvh_build()
{
U64 max_bvh_nodes = 2 * MAX_NUM_ENTITIES - 1;
BVH bvh = {0};
bvh.nodes = (BVHNode *)_aligned_malloc(sizeof(BVHNode)*max_bvh_nodes, 64);
bvh.max_num_nodes = max_bvh_nodes;
bvh.used_nodes = 2; // Skip by two, TODO(anton): Comment this.
bvh.minimum_entities_in_leaf = 2;
U32 root_index = 0;
BVHNode *root = &bvh.nodes[root_index];
root->left_first = 0;
root->tri_count = MAX_NUM_ENTITIES;
bvh_update_bounds(&bvh, 0);
bvh_subdivide(&bvh, 0);
return bvh;
}
__host__ function void
bvh_subdivide(BVH *bvh, U32 node_idx)
{
BVHNode *node = &bvh->nodes[node_idx];
if(node->tri_count <= bvh->minimum_entities_in_leaf)
{
return;
}
// Split box
Vec3F32 extent = sub_V3F32(node->aabb_max, node->aabb_min);
U32 axis = 0;
if(extent.y > extent.x) axis = 1;
if(extent.z > extent.v[axis]) axis = 2;
F32 split_pos = node->aabb_min.v[axis] + extent.v[axis] * 0.5f;
// Sorting into left and right partitions
U32 i = node->left_first;
U32 j = node->tri_count + i - 1;
while (i <= j)
{
U32 tri_idx = h_tri_indices[i];
if(h_entities[tri_idx].center.v[axis] < split_pos)
{
i += 1;
}
else
{
h_tri_indices[i] = h_tri_indices[j];
h_tri_indices[j] = tri_idx;
j -= 1;
}
}
U32 left_count = i - node->left_first;
if(left_count == 0 || left_count == node->tri_count)
{
// One of the partitions are empty, don't subdivide further.
return;
}
// Create child nodes and subdivide
U32 left_child_index = bvh->used_nodes++;
U32 right_child_index = bvh->used_nodes++;
bvh->nodes[left_child_index].left_first = node->left_first;
bvh->nodes[left_child_index].tri_count = left_count;
bvh->nodes[right_child_index].left_first = i;
bvh->nodes[right_child_index].tri_count = node->tri_count - left_count;
node->left_first = left_child_index;
node->tri_count = 0;
bvh_update_bounds(bvh, left_child_index);
bvh_update_bounds(bvh, right_child_index);
bvh_subdivide(bvh, left_child_index);
bvh_subdivide(bvh, right_child_index);
}
__host__ function void
bvh_update_bounds(BVH *bvh, U32 node_idx)
{
BVHNode *node = &bvh->nodes[node_idx];
node->aabb_min = vec3F32(F32_MAX, F32_MAX, F32_MAX);
node->aabb_max = vec3F32(F32_MIN, F32_MIN, F32_MIN);
U32 first_tri_idx = node->left_first;
for(U32 i = 0; i < node->tri_count; i += 1)
{
U32 leaf_tri_idx = h_tri_indices[first_tri_idx + i];
Entity *tri = &h_entities[leaf_tri_idx];
node->aabb_min = h_min_V3F32(node->aabb_min, tri->vertex0);
node->aabb_min = h_min_V3F32(node->aabb_min, tri->vertex1);
node->aabb_min = h_min_V3F32(node->aabb_min, tri->vertex2);
node->aabb_max = h_max_V3F32(node->aabb_max, tri->vertex0);
node->aabb_max = h_max_V3F32(node->aabb_max, tri->vertex1);
node->aabb_max = h_max_V3F32(node->aabb_max, tri->vertex2);
}
}
__host__ function void
bvh_host_intersect(BVH *bvh, RayF32 *ray, HitRecord *rec, U32 node_idx)
{
BVHNode *node = &bvh->nodes[node_idx];
U32 any_hit = 0;
if(h_intersect_aabb(ray, node->aabb_min, node->aabb_max, rec->t))
{
if(node->tri_count > 0)
{
//LOG("Hit a leaf node %i with tri count %i \n", node_idx, node->tri_count);
for(U32 i = 0; i < node->tri_count; i+=1)
{
U32 tri_index = h_tri_indices[node->left_first + i];
Entity *tri = &h_entities[tri_index];
hit_triangle_host(ray, rec, tri);
if(rec->hit)
{
any_hit = 1;
//LOG("got hit in bvh_host_intersect loop \n");
}
}
}
else
{
bvh_host_intersect(bvh, ray, rec, node->left_first);
bvh_host_intersect(bvh, ray, rec, node->left_first + 1);
}
}
if(!rec->hit)
{
rec->hit = any_hit;
}
}