Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:48:54

0001 #pragma once
0002 
0003 /**
0004 distance_leaf_box3
0005 --------------------
0006 
0007 https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
0008 
0009 https://www.youtube.com/watch?v=62-pRVZuS5c
0010 
0011 float sdBox( vec3 p, vec3 b )
0012 {
0013   vec3 q = abs(p) - b;
0014   return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);
0015 }
0016 
0017 **/
0018 
0019 LEAF_FUNC
0020 float distance_leaf_box3(const float3& pos, const quad& q0 )
0021 {
0022     float3 q = make_float3( fabs(pos.x) - q0.f.x/2.f, fabs(pos.y) - q0.f.y/2.f , fabs(pos.z) - q0.f.z/2.f ) ;    
0023     float3 z = make_float3( 0.f ); 
0024     float sd = length(fmaxf(q, z)) + fminf(fmaxf(q.x, fmaxf(q.y, q.z)), 0.f ) ;   
0025 
0026 #ifdef DEBUG
0027     printf("//distance_leaf_box3 sd %10.4f \n", sd ); 
0028 #endif
0029     return sd ; 
0030 }
0031 
0032 
0033 /**
0034 intersect_leaf_box3
0035 -----------------------
0036 
0037 "Fast, Branchless Ray/Bounding Box Intersections"
0038 
0039 * https://tavianator.com/2011/ray_box.html
0040 
0041 ..
0042 
0043     The fastest method for performing ray/AABB intersections is the slab method.
0044     The idea is to treat the box as the space inside of three pairs of parallel
0045     planes. The ray is clipped by each pair of parallel planes, and if any portion
0046     of the ray remains, it intersected the box.
0047 
0048 
0049 * https://tavianator.com/2015/ray_box_nan.html
0050 
0051 
0052 Just because the ray intersects the box doesnt 
0053 mean its a usable intersect, there are 3 possibilities::
0054 
0055               t_near       t_far   
0056 
0057                 |           |
0058       -----1----|----2------|------3---------->
0059                 |           |
0060 
0061 **/
0062 
0063 LEAF_FUNC
0064 void intersect_leaf_box3(bool& valid_isect, float4& isect, const quad& q0, const float t_min, const float3& ray_origin, const float3& ray_direction )
0065 {
0066    const float3 bmin = make_float3(-q0.f.x/2.f, -q0.f.y/2.f, -q0.f.z/2.f );   // fullside 
0067    const float3 bmax = make_float3( q0.f.x/2.f,  q0.f.y/2.f,  q0.f.z/2.f ); 
0068    const float3 bcen = make_float3( 0.f, 0.f, 0.f ) ;    
0069 
0070 #ifdef DEBUG_BOX3
0071     printf("//intersect_leaf_box3  bmin (%10.4f,%10.4f,%10.4f) bmax (%10.4f,%10.4f,%10.4f)  \n", bmin.x, bmin.y, bmin.z, bmax.x, bmax.y, bmax.z );  
0072 #endif
0073 
0074    float3 idir = make_float3(1.f)/ray_direction ; 
0075 
0076    // the below t-parameter float3 are intersects with the x, y and z planes of
0077    // the three axis slab planes through the box bmin and bmax  
0078 
0079    float3 t0 = (bmin - ray_origin)*idir;      //  intersects with bmin x,y,z slab planes
0080    float3 t1 = (bmax - ray_origin)*idir;      //  intersects with bmax x,y,z slab planes 
0081 
0082    float3 near = fminf(t0, t1);               //  bmin or bmax intersects closest to origin  
0083    float3 far  = fmaxf(t0, t1);               //  bmin or bmax intersects farthest from origin 
0084 
0085    float t_near = fmaxf( near );              //  furthest near intersect              
0086    float t_far  = fminf( far );               //  closest far intersect 
0087 
0088    bool along_x = ray_direction.x != 0.f && ray_direction.y == 0.f && ray_direction.z == 0.f ;
0089    bool along_y = ray_direction.x == 0.f && ray_direction.y != 0.f && ray_direction.z == 0.f ;
0090    bool along_z = ray_direction.x == 0.f && ray_direction.y == 0.f && ray_direction.z != 0.f ;
0091 
0092    bool in_x = ray_origin.x > bmin.x && ray_origin.x < bmax.x  ;
0093    bool in_y = ray_origin.y > bmin.y && ray_origin.y < bmax.y  ;
0094    bool in_z = ray_origin.z > bmin.z && ray_origin.z < bmax.z  ;
0095 
0096 
0097    bool has_intersect = false ;
0098    if(     along_x) has_intersect = in_y && in_z ;
0099    else if(along_y) has_intersect = in_x && in_z ; 
0100    else if(along_z) has_intersect = in_x && in_y ; 
0101    else             has_intersect = ( t_far > t_near && t_far > 0.f ) ;  // segment of ray intersects box, at least one is ahead
0102 
0103 
0104 #ifdef DEBUG_BOX3
0105     printf("//intersect_leaf_box3  along_xyz (%d,%d,%d) in_xyz (%d,%d,%d)   has_intersect %d  \n", along_x, along_y, along_z, in_x, in_y, in_z, has_intersect  );  
0106     //printf("//intersect_leaf_box3 t_min %10.4f t_near %10.4f t_far %10.4f \n", t_min, t_near, t_far ); 
0107 #endif
0108 
0109 
0110    valid_isect = false ; 
0111    if( has_intersect ) 
0112    {
0113        float t_cand = t_min < t_near ?  t_near : ( t_min < t_far ? t_far : t_min ) ; 
0114 #ifdef DEBUG_BOX3
0115        printf("//intersect_leaf_box3 t_min %10.4f t_near %10.4f t_far %10.4f t_cand %10.4f \n", t_min, t_near, t_far, t_cand ); 
0116 #endif
0117 
0118        float3 p = ray_origin + t_cand*ray_direction - bcen ; 
0119 
0120        float3 pa = make_float3(fabs(p.x)/(bmax.x - bmin.x), 
0121                                fabs(p.y)/(bmax.y - bmin.y), 
0122                                fabs(p.z)/(bmax.z - bmin.z)) ;
0123 
0124        // discern which face is intersected from the largest absolute coordinate 
0125        // hmm this implicitly assumes a "box" of equal sides, not a "box3"
0126        // nope, no problem as the above pa already scales by the fullside so effectivey get a symmetric box 
0127        // about the origin for the purpose of the comparison
0128        //
0129        //
0130        // Think about intersects onto the unit cube
0131        // clearly the coordinate with the largest absolute value
0132        // identifies the x,y or z pair of axes and then 
0133        // the sign of that gives which face and the outwards normal.
0134        // Hmm : what about the corner case ?
0135 
0136        float3 n = make_float3(0.f) ;
0137        if(      pa.x >= pa.y && pa.x >= pa.z ) n.x = copysignf( 1.f , p.x ) ;              
0138        else if( pa.y >= pa.x && pa.y >= pa.z ) n.y = copysignf( 1.f , p.y ) ;              
0139        else if( pa.z >= pa.x && pa.z >= pa.y ) n.z = copysignf( 1.f , p.z ) ;              
0140 
0141        if(t_cand > t_min)
0142        {
0143            valid_isect = true ; 
0144 
0145            isect.x = n.x ;
0146            isect.y = n.y ;
0147            isect.z = n.z ;
0148            isect.w = t_cand ; 
0149        }
0150    }
0151 
0152 #ifdef DEBUG_BOX3
0153    printf("//intersect_leaf_box3 valid_isect %d  isect ( %10.4f %10.4f %10.4f %10.4f)  \n", valid_isect, isect.x, isect.y, isect.z, isect.w ); 
0154 #endif
0155 }
0156 
0157