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 intersect_leaf_oldcone
0005 ========================
0006 
0007 Suspect this cone implementation has issues with axial rays 
0008 and rays onto "corners" 
0009 
0010 Notice problems for rays along axis line thru apex 
0011 and for rays in -z direction onto the edge between the endcap 
0012 and quadratic sheet marked (*) on below::
0013 
0014 
0015                        *
0016                        |     [0,0,0]
0017        ----------------A------------------           
0018                       / \
0019                      /   \
0020                     /     \
0021                  * /       \ * 
0022                  |/         \|
0023                  +-----------+         z = z2
0024                 /     r2      \
0025                /               \
0026               /                 \
0027              /                   \
0028             +---------------------+   z = z1
0029       [-300,0,-300]    r1       [+300,0,-300]
0030 
0031 
0032 TODO: investigate and see if some special casing can avoid the issues.
0033 
0034 
0035 
0036     cone with apex at [0,0,z0]  and   r1/(z1-z0) = tanth  for any r1,z1 on the cone
0037     
0038         x^2 + y^2  - (z - z0)^2 tanth^2 = 0 
0039         x^2 + y^2  - (z^2 -2z0 z - z0^2) tanth^2 = 0 
0040     
0041       Gradient:    [2x, 2y, (-2z tanth^2) + 2z0 tanth^2 ] 
0042 
0043 
0044 
0045 To find ray intersect with infinite cone insert parametric ray
0046 into definining eqn of cone, giving a quadratic in t::
0047 
0048     (o.x+ t d.x)^2 + (o.y + t d.y)^2 - (o.z - z0 + t d.z)^2 tth2 = 0 
0049      
0050     c2 t^2 + 2 c1 t + c0 = 0 
0051 
0052 **/
0053 
0054 LEAF_FUNC
0055 void intersect_leaf_oldcone( bool& valid_isect, float4& isect, const quad& q0, const float t_min , const float3& ray_origin, const float3& ray_direction )
0056 {
0057     float r1 = q0.f.x ; 
0058     float z1 = q0.f.y ; 
0059     float r2 = q0.f.z ; 
0060     float z2 = q0.f.w ;   // z2 > z1
0061 
0062     float tth = (r2-r1)/(z2-z1) ;
0063     float tth2 = tth*tth ; 
0064     float z0 = (z2*r1-z1*r2)/(r1-r2) ;  // apex
0065 
0066 #ifdef DEBUG_CONE
0067     printf("//intersect_leaf_oldcone r1 %10.4f z1 %10.4f r2 %10.4f z2 %10.4f : z0 %10.4f \n", r1, z1, r2, z2, z0 );  
0068 #endif
0069  
0070     float r1r1 = r1*r1 ; 
0071     float r2r2 = r2*r2 ; 
0072 
0073     const float3& o = ray_origin ;
0074     const float3& d = ray_direction ;
0075 
0076     // collecting terms to form coefficients of the quadratic : c2 t^2 + 2 c1 t + c0 = 0 
0077 
0078     float c2 = d.x*d.x + d.y*d.y - d.z*d.z*tth2 ;
0079     float c1 = o.x*d.x + o.y*d.y - (o.z-z0)*d.z*tth2 ; 
0080     float c0 = o.x*o.x + o.y*o.y - (o.z-z0)*(o.z-z0)*tth2 ;
0081     float disc = c1*c1 - c0*c2 ; 
0082 
0083     // when c0 or c2 are small, sdisc will be very close to c1 
0084     // resulting in catastrophic precision loss for the root that 
0085     // is obtained by subtraction of two close values
0086     // => because of this need to use robust_quadratic_roots 
0087     // as done in csg_intersect_leaf_newcone.h 
0088 
0089 #ifdef DEBUG_CONE
0090     printf("//intersect_leaf_oldcone c2 %10.4f c1 %10.4f c0 %10.4f disc %10.4f disc > 0.f %d : tth %10.4f \n", c2, c1, c0, disc, disc>0.f, tth  );  
0091 #endif
0092  
0093     // * cap intersects (including axial ones) will always have potentially out of z-range cone intersects 
0094     // * cone intersects will have out of r-range plane intersects, other than rays within xy plane
0095 
0096     valid_isect = false ;
0097  
0098     if(disc > 0.f)  // has intersects with infinite cone
0099     {
0100         float sdisc = sqrtf(disc) ;   
0101         float root1 = (-c1 - sdisc)/c2 ;    
0102         float root2 = (-c1 + sdisc)/c2 ;  
0103 
0104         float root1p = root1 > t_min ? root1 : RT_DEFAULT_MAX ;  
0105         float root2p = root2 > t_min ? root2 : RT_DEFAULT_MAX ; 
0106         // disqualify -ve roots from mirror cone thats behind you immediately 
0107 
0108         // order the roots 
0109         float t_near = fminf( root1p, root2p );
0110         float t_far  = fmaxf( root1p, root2p );  
0111 
0112 
0113 #ifdef DEBUG_CONE
0114         printf("//intersect_leaf_oldcone c0 %10.4g c1 %10.4g c2 %10.4g t_near %10.4g t_far %10.4g sdisc %10.4f "
0115                 "(-c1-sdisc) %10.4g (-c1+sdisc) %10.4g \n", 
0116               c0, c1, c2, t_near, t_far, sdisc, (-c1-sdisc), (-c1+sdisc)  );  
0117 
0118         float t_near_alt, t_far_alt, disc_alt, sdisc_alt ;   
0119         robust_quadratic_roots(t_near_alt, t_far_alt, disc_alt, sdisc_alt, c2, c1, c0 ) ;
0120 
0121         printf("//intersect_leaf_oldcone t_near_alt %10.4g t_far_alt %10.4g t_near_alt-t_near %10.4g t_far_alt-t_far %10.4g \n", 
0122              t_near_alt, t_far_alt, (t_near_alt-t_near), (t_far_alt-t_far) );
0123 #endif
0124 
0125 
0126         float z_near = o.z+t_near*d.z ; 
0127         float z_far  = o.z+t_far*d.z ; 
0128 
0129         t_near = z_near > z1 && z_near < z2  && t_near > t_min ? t_near : RT_DEFAULT_MAX ; // disqualify out-of-z
0130         t_far  = z_far  > z1 && z_far  < z2  && t_far  > t_min ? t_far  : RT_DEFAULT_MAX ; 
0131 
0132         // intersects with cap planes
0133         float idz = 1.f/d.z ; 
0134         float t_cap1 = d.z == 0.f ? RT_DEFAULT_MAX : (z1 - o.z)*idz ;   // d.z zero means no z-plane intersects
0135         float t_cap2 = d.z == 0.f ? RT_DEFAULT_MAX : (z2 - o.z)*idz ;
0136 
0137         // radii squared at cap intersects  
0138         float r_cap1 = (o.x + t_cap1*d.x)*(o.x + t_cap1*d.x) + (o.y + t_cap1*d.y)*(o.y + t_cap1*d.y) ;  
0139         float r_cap2 = (o.x + t_cap2*d.x)*(o.x + t_cap2*d.x) + (o.y + t_cap2*d.y)*(o.y + t_cap2*d.y) ;  
0140 
0141         t_cap1 = r_cap1 < r1r1 && t_cap1 > t_min ? t_cap1 : RT_DEFAULT_MAX ;  // disqualify out-of-radius
0142         t_cap2 = r_cap2 < r2r2 && t_cap2 > t_min ? t_cap2 : RT_DEFAULT_MAX ; 
0143  
0144         float t_capn = fminf( t_cap1, t_cap2 );    // order caps
0145         float t_capf = fmaxf( t_cap1, t_cap2 );
0146 
0147         // NB use of RT_DEFAULT_MAX to represent disqualified
0148         // roots is crucial to picking closest  qualified root with 
0149         // the simple fminf(tt) 
0150 
0151         float4 tt = make_float4( t_near, t_far, t_capn, t_capf );
0152         float t_cand = fminf(tt) ; 
0153         
0154         valid_isect = t_cand > t_min && t_cand < RT_DEFAULT_MAX ;
0155         if(valid_isect)
0156         {
0157             if( t_cand == t_cap1 || t_cand == t_cap2 )
0158             {
0159                 isect.x = 0.f ; 
0160                 isect.y = 0.f ;
0161                 isect.z =  t_cand == t_cap2 ? 1.f : -1.f  ;   
0162             }
0163             else
0164             { 
0165                 //     x^2 + y^2  - (z - z0)^2 tanth^2 = 0 
0166                 //     x^2 + y^2  - (z^2 -2z0 z - z0^2) tanth^2 = 0 
0167                 //
0168                 //   Gradient:    [2x, 2y, (-2z + 2z0) tanth^2 ] 
0169                 //   Gradient:    2*[x, y, (z0-z) tanth^2 ] 
0170                 float3 n = normalize(make_float3( o.x+t_cand*d.x, o.y+t_cand*d.y, (z0-(o.z+t_cand*d.z))*tth2  ))  ; 
0171                 // huh : surely simpler way to get normal, just from cone param ?
0172 
0173                 isect.x = n.x ; 
0174                 isect.y = n.y ;
0175                 isect.z = n.z ; 
0176             }
0177             isect.w = t_cand ; 
0178         }
0179     }
0180 }
0181 
0182