fix long standing grind bug
[carveJwlIkooP6JGAAIwe30JlM.git] / bvh.h
diff --git a/bvh.h b/bvh.h
index b054741facdcfbac6d80ee5f6d36dfaac24a5e09..21bfb39c3b162ceca22d22a207b3021f6931747a 100644 (file)
--- 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;
@@ -221,9 +228,7 @@ 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){
       bh_node *inode = &bh->nodes[ stack[depth] ];
@@ -262,30 +267,73 @@ 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 )
+{
+   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;
       }