X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=bvh.h;h=21bfb39c3b162ceca22d22a207b3021f6931747a;hb=2b7784846e2f2ee57ba336a2aa040adb2d0ca461;hp=94ea69bdf91d95c8ea86b0f79a44c3a33b940848;hpb=000297f007a08b25f458656bfb8dfe4345f2ec32;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/bvh.h b/bvh.h index 94ea69b..21bfb39 100644 --- a/bvh.h +++ b/bvh.h @@ -26,6 +26,13 @@ typedef struct bh_node bh_node; typedef struct bh_tree bh_tree; typedef struct bh_system bh_system; +typedef struct ray_hit ray_hit; +struct ray_hit{ + float dist; + u32 *tri; + v3f pos, normal; +}; + struct bh_tree { u32 node_count; @@ -68,8 +75,7 @@ VG_STATIC void bh_update_bounds( bh_tree *bh, u32 inode ) bh_node *node = &bh->nodes[ inode ]; box_init_inf( node->bbx ); - for( u32 i=0; icount; i++ ) - { + for( u32 i=0; icount; i++ ){ u32 idx = node->start+i; bh->system->expand_bound( bh->user, node->bbx, idx ); } @@ -103,12 +109,10 @@ VG_STATIC void bh_subdivide( bh_tree *bh, u32 inode ) i32 i = node->start, j = i + node->count-1; - while( i <= j ) - { + while( i <= j ){ if( bh->system->item_centroid( bh->user, i, axis ) < split ) i ++; - else - { + else{ bh->system->item_swap( bh->user, i, j ); j --; } @@ -164,10 +168,10 @@ VG_STATIC bh_tree *bh_create( void *lin_alloc, bh_system *system, if( item_count > 2 ) bh_subdivide( bh, 0 ); - totsize = sizeof(bh_tree) + sizeof(bh_node) * bh->node_count; + totsize = vg_align8(sizeof(bh_tree) + sizeof(bh_node) * bh->node_count); bh = vg_linear_resize( lin_alloc, bh, totsize ); - vg_success( "BVH done, size: %u/%u\n", bh->node_count, (item_count*2-1) ); + vg_success( "BVH done, size: %u/%u\n", bh->node_count, (alloc_count*2-1) ); return bh; } @@ -179,10 +183,8 @@ VG_STATIC void bh_debug_leaf( bh_tree *bh, bh_node *node ) { vg_line_boxf( node->bbx, 0xff00ff00 ); - if( bh->system->item_debug ) - { - for( u32 i=0; icount; i++ ) - { + if( bh->system->item_debug ){ + for( u32 i=0; icount; i++ ){ u32 idx = node->start+i; bh->system->item_debug( bh->user, idx ); } @@ -199,15 +201,13 @@ VG_STATIC void bh_debug_trace( bh_tree *bh, u32 inode, v3f pos, u32 colour ) if( (pos[0] >= node->bbx[0][0] && pos[0] <= node->bbx[1][0]) && (pos[2] >= node->bbx[0][2] && pos[2] <= node->bbx[1][2]) ) { - if( !node->count ) - { + if( !node->count ){ vg_line_boxf( node->bbx, colour ); bh_debug_trace( bh, node->il, pos, colour ); bh_debug_trace( bh, node->ir, pos, colour ); } - else - { + else{ if( bh->system->item_debug ) bh_debug_leaf( bh, node ); } @@ -228,19 +228,13 @@ VG_STATIC int bh_ray( bh_tree *bh, v3f co, v3f dir, ray_hit *hit ) stack[2] = bh->nodes[0].ir; v3f dir_inv; - dir_inv[0] = 1.0f/dir[0]; - dir_inv[1] = 1.0f/dir[1]; - dir_inv[2] = 1.0f/dir[2]; + v3_div( (v3f){1.0f,1.0f,1.0f}, dir, dir_inv ); - while(depth) - { + while(depth){ bh_node *inode = &bh->nodes[ stack[depth] ]; - if( ray_aabb1( inode->bbx, co, dir_inv, hit->dist ) ) - { - if( inode->count ) - { - for( u32 i=0; icount; i++ ) - { + if( ray_aabb1( inode->bbx, co, dir_inv, hit->dist ) ){ + if( inode->count ){ + for( u32 i=0; icount; i++ ){ u32 idx = inode->start+i; if( bh->system->cast_ray ) @@ -251,10 +245,8 @@ VG_STATIC int bh_ray( bh_tree *bh, v3f co, v3f dir, ray_hit *hit ) depth --; } - else - { - if( depth+1 >= vg_list_size(stack) ) - { + else{ + if( depth+1 >= vg_list_size(stack) ){ vg_error( "Maximum stack reached!\n" ); return count; } @@ -264,8 +256,7 @@ VG_STATIC int bh_ray( bh_tree *bh, v3f co, v3f dir, ray_hit *hit ) depth ++; } } - else - { + else{ depth --; } } @@ -276,54 +267,90 @@ VG_STATIC int bh_ray( bh_tree *bh, v3f co, v3f dir, ray_hit *hit ) typedef struct bh_iter bh_iter; struct bh_iter { - struct - { - int id, depth; + struct { + i32 id, depth; } stack[64]; - int depth, i; + enum bh_query_type{ + k_bh_query_box, + k_bh_query_ray + } + query; + + union{ + struct{ + boxf box; + } + box; + + struct{ + v3f co, inv_dir; + f32 max_dist; + } + ray; + }; + + i32 depth, i; }; -VG_STATIC void bh_iter_init( int root, bh_iter *it ) +VG_STATIC void bh_iter_init_box( i32 root, bh_iter *it, boxf box ) { + it->query = k_bh_query_box; it->stack[0].id = root; it->stack[0].depth = 0; it->depth = 0; it->i = 0; + + box_copy( box, it->box.box ); } -VG_STATIC int bh_next( bh_tree *bh, bh_iter *it, boxf box, int *em ) +VG_STATIC void bh_iter_init_ray( i32 root, bh_iter *it, v3f co, + v3f dir, f32 max_dist ) { - while( it->depth >= 0 ) - { + it->query = k_bh_query_ray; + it->stack[0].id = root; + it->stack[0].depth = 0; + it->depth = 0; + it->i = 0; + + v3_div( (v3f){1.0f,1.0f,1.0f}, dir, it->ray.inv_dir ); + v3_copy( co, it->ray.co ); + it->ray.max_dist = max_dist; +} + +VG_STATIC i32 bh_next( bh_tree *bh, bh_iter *it, i32 *em ) +{ + while( it->depth >= 0 ){ bh_node *inode = &bh->nodes[ it->stack[it->depth].id ]; /* Only process overlapping nodes */ - if( !box_overlap( inode->bbx, box ) ) - { + i32 q = 0; + + if( it->query == k_bh_query_box ) + q = box_overlap( inode->bbx, it->box.box ); + else + q = ray_aabb1( inode->bbx, it->ray.co, + it->ray.inv_dir, it->ray.max_dist ); + + if( !q ){ it->depth --; continue; } - if( inode->count ) - { - if( it->i < inode->count ) - { + if( inode->count ){ + if( it->i < inode->count ){ *em = inode->start+it->i; it->i ++; return 1; } - else - { + else{ it->depth --; it->i = 0; } } - else - { - if( it->depth+1 >= vg_list_size(it->stack) ) - { + else{ + if( it->depth+1 >= vg_list_size(it->stack) ){ vg_error( "Maximum stack reached!\n" ); return 0; } @@ -352,8 +379,7 @@ VG_STATIC int bh_closest_point( bh_tree *bh, v3f pos, queue[0] = 0; - while( depth >= 0 ) - { + while( depth >= 0 ){ bh_node *inode = &bh->nodes[ queue[depth] ]; v3f p1; @@ -361,18 +387,14 @@ VG_STATIC int bh_closest_point( bh_tree *bh, v3f pos, /* branch into node if its closer than current best */ float node_dist = v3_dist2( pos, p1 ); - if( node_dist < max_dist ) - { - if( inode->count ) - { - for( int i=0; icount; i++ ) - { + if( node_dist < max_dist ){ + if( inode->count ){ + for( int i=0; icount; i++ ){ v3f p2; bh->system->item_closest( bh->user, inode->start+i, pos, p2 ); float item_dist = v3_dist2( pos, p2 ); - if( item_dist < max_dist ) - { + if( item_dist < max_dist ){ max_dist = item_dist; v3_copy( p2, closest ); best_item = inode->start+i; @@ -381,8 +403,7 @@ VG_STATIC int bh_closest_point( bh_tree *bh, v3f pos, depth --; } - else - { + else{ queue[depth] = inode->il; queue[depth+1] = inode->ir;