Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #pragma once
0002 /**
0003 intersect_leaf_cylinder : a much simpler approach than intersect_leaf_oldcylinder
0004 -------------------------------------------------------------------------------------------
0005 
0006 The two cylinder imps were compared with tests/CSGIntersectComparisonTest.cc.
0007 Surface distance comparisons show the new imp is more precise and does
0008 not suffer from near-axial spurious intersects beyond the ends.  
0009 
0010 intersect_leaf_cylinder
0011 
0012    * simple as possible approach, minimize the flops
0013    * axial special case removed, might need to put back if find some motivation to do that
0014 
0015 intersect_leaf_oldcylinder
0016 
0017    * pseudo-general approach, based on implementation from book RTCD  
0018    * had axial special case bolted on for unrecorded reason, some glitch presumably 
0019 
0020 
0021 There are four possible t
0022 
0023 * 2 from curved sheet, obtained from solving quadratic, that must be within z1 z2 range
0024 * 2 from endcaps that must be within r2 range  
0025 
0026 Finding the intersect means finding the smallest t from the four that exceeds t_min  
0027 
0028 Current approach keeps changing t_cand, could instead collect all four potential t 
0029 into a float4 and then pick from that ? 
0030 
0031 **/
0032 
0033 LEAF_FUNC
0034 void intersect_leaf_cylinder( bool& valid_isect, float4& isect, const quad& q0, const quad& q1, const float t_min, const float3& ray_origin, const float3& ray_direction )
0035 {
0036     const float& r  = q0.f.w ; 
0037     const float& z1 = q1.f.x  ; 
0038     const float& z2 = q1.f.y  ; 
0039     const float& ox = ray_origin.x ; 
0040     const float& oy = ray_origin.y ; 
0041     const float& oz = ray_origin.z ; 
0042     const float& vx = ray_direction.x ; 
0043     const float& vy = ray_direction.y ; 
0044     const float& vz = ray_direction.z ; 
0045 
0046     const float r2 = r*r ; 
0047     const float a = vx*vx + vy*vy ;     // see CSG/sympy_cylinder.py 
0048     const float b = ox*vx + oy*vy ; 
0049     const float c = ox*ox + oy*oy - r2 ; 
0050 
0051     float t_near, t_far, disc, sdisc ;   
0052     robust_quadratic_roots_disqualifying(t_min, t_near, t_far, disc, sdisc, a, b, c); //  Solving:  a t^2 + 2 b t +  c = 0 
0053     float z_near = oz+t_near*vz ; 
0054     float z_far  = oz+t_far*vz ; 
0055 
0056     const float t_z1cap = (z1 - oz)/vz ; 
0057     const float r2_z1cap = (ox+t_z1cap*vx)*(ox+t_z1cap*vx) + (oy+t_z1cap*vy)*(oy+t_z1cap*vy) ;  
0058 
0059     const float t_z2cap = (z2 - oz)/vz ;  
0060     const float r2_z2cap = (ox+t_z2cap*vx)*(ox+t_z2cap*vx) + (oy+t_z2cap*vy)*(oy+t_z2cap*vy) ;  
0061 
0062 #ifdef DEBUG
0063     //printf("// t_z1cap %10.4f r2_z1cap %10.4f \n", t_z1cap, r2_z1cap ); 
0064     //printf("// t_z2cap %10.4f r2_z2cap %10.4f \n", t_z2cap, r2_z2cap ); 
0065 #endif
0066 
0067     float t_cand = CUDART_INF_F ;
0068     if( t_near  > t_min && z_near   > z1 && z_near < z2 && t_near  < t_cand ) t_cand = t_near ; 
0069     if( t_far   > t_min && z_far    > z1 && z_far  < z2 && t_far   < t_cand ) t_cand = t_far ; 
0070     if( t_z1cap > t_min && r2_z1cap <= r2               && t_z1cap < t_cand ) t_cand = t_z1cap ; 
0071     if( t_z2cap > t_min && r2_z2cap <= r2               && t_z2cap < t_cand ) t_cand = t_z2cap ; 
0072 
0073     valid_isect = t_cand > t_min && t_cand < CUDART_INF_F ; 
0074     if(valid_isect)
0075     {
0076         bool sheet = ( t_cand == t_near || t_cand == t_far ) ; 
0077         isect.x = sheet ? (ox + t_cand*vx)/r : 0.f ; 
0078         isect.y = sheet ? (oy + t_cand*vy)/r : 0.f ; 
0079         isect.z = sheet ? 0.f : ( t_cand == t_z1cap ? -1.f : 1.f) ; 
0080         isect.w = t_cand ;      
0081     }
0082 }
0083 
0084 
0085 
0086 
0087 
0088 /**
0089 distance_leaf_cylinder
0090 ------------------------
0091 
0092 * https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
0093 
0094 Capped Cylinder - exact
0095 
0096 float sdCappedCylinder( vec3 p, float h, float r )
0097 {
0098   vec2 d = abs(vec2(length(p.xz),p.y)) - vec2(h,r); 
0099   // dont follow  would expect h <-> r with radius to be on the first dimension and height on second
0100      
0101   return min(max(d.x,d.y),0.0) + length(max(d,0.0));
0102 }
0103 
0104 
0105                       p
0106                       +
0107                       | 
0108                       |
0109                       | 
0110   - - - +---r----+----+---+ - - - - - -
0111         |        :        |
0112         h        :        +------+ p    
0113         |        :        |
0114         |        :        |
0115         +--------+--------+
0116         |        :        |
0117         |        :        |
0118         |        :        |
0119         |        :        |
0120   - - - +--------+--------+ - - - - - - - 
0121 
0122 
0123 
0124 
0125 
0126 The SDF rules for CSG combinations::
0127 
0128     CSG union(l,r)     ->  min(l,r)
0129     CSG intersect(l,r) ->  max(l,r)
0130     CSG difference(l,r) -> max(l,-r)    [aka subtraction, corresponds to intersecting with a complemented rhs]
0131 
0132 
0133 **/
0134 
0135 
0136 LEAF_FUNC
0137 float distance_leaf_cylinder( const float3& pos, const quad& q0, const quad& q1 )
0138 {
0139     const float   radius = q0.f.w ; 
0140     const float       z1 = q1.f.x  ; 
0141     const float       z2 = q1.f.y  ;   // z2 > z1 
0142 
0143     float sd_capslab = fmaxf( pos.z - z2 , z1 - pos.z ); 
0144     float sd_infcyl = sqrtf( pos.x*pos.x + pos.y*pos.y ) - radius ;  
0145     float sd = fmaxf( sd_capslab, sd_infcyl ); 
0146 
0147 #ifdef DEBUG
0148     printf("//distance_leaf_cylinder sd %10.4f \n", sd ); 
0149 #endif
0150     return sd ; 
0151 }
0152 
0153