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_hyperboloid
0005 -----------------------------
0006 
0007 * http://mathworld.wolfram.com/One-SheetedHyperboloid.html
0008 
0009 ::
0010 
0011       x^2 +  y^2  =  r0^2 * (  (z/zf)^2  +  1 )
0012       x^2 + y^2 - (r0^2/zf^2) * z^2 - r0^2  =  0 
0013       x^2 + y^2 + A * z^2 + B   =  0 
0014 
0015       grad( x^2 + y^2 + A * z^2 + B ) =  [2 x, 2 y, A*2z ] 
0016 
0017 
0018      (ox+t sx)^2 + (oy + t sy)^2 + A (oz+ t sz)^2 + B = 0 
0019 
0020       t^2 ( sxsx + sysy + A szsz ) + 2*t ( oxsx + oysy + A * ozsz ) +  (oxox + oyoy + A * ozoz + B ) = 0 
0021 
0022 **/
0023 
0024 LEAF_FUNC
0025 void intersect_leaf_hyperboloid(bool& valid_isect, float4& isect, const quad& q0, const float t_min, const float3& ray_origin, const float3& ray_direction )
0026 {
0027     const float zero(0.f); 
0028     const float one(1.f); 
0029 
0030     const float r0 = q0.f.x ;  // waist (z=0) radius 
0031     const float zf = q0.f.y ;  // at z=zf radius grows to  sqrt(2)*r0 
0032     const float z1 = q0.f.z ;  // z1 < z2 by assertion  
0033     const float z2 = q0.f.w ;  
0034 
0035     const float rr0 = r0*r0 ;
0036     const float z1s = z1/zf ; 
0037     const float z2s = z2/zf ; 
0038     const float rr1 = rr0 * ( z1s*z1s + one ) ; // radii squared at z=z1, z=z2
0039     const float rr2 = rr0 * ( z2s*z2s + one ) ;
0040 
0041     const float A = -rr0/(zf*zf) ;
0042     const float B = -rr0 ;  
0043 
0044     const float& sx = ray_direction.x ; 
0045     const float& sy = ray_direction.y ; 
0046     const float& sz = ray_direction.z ;
0047 
0048     const float& ox = ray_origin.x ; 
0049     const float& oy = ray_origin.y ; 
0050     const float& oz = ray_origin.z ;
0051 
0052     const float d = sx*sx + sy*sy + A*sz*sz ; 
0053     const float b = ox*sx + oy*sy + A*oz*sz ; 
0054     const float c = ox*ox + oy*oy + A*oz*oz + B ; 
0055     
0056     float t1hyp, t2hyp, disc, sdisc ;   
0057     robust_quadratic_roots(t1hyp, t2hyp, disc, sdisc, d, b, c); //  Solving:  d t^2 + 2 b t +  c = 0 
0058 
0059     const float h1z = oz + t1hyp*sz ;  // hyp intersect z positions
0060     const float h2z = oz + t2hyp*sz ; 
0061 
0062     //  z = oz+t*sz -> t = (z - oz)/sz 
0063     float osz = one/sz ; 
0064     float t2cap = (z2 - oz)*osz ;   // cap plane intersects
0065     float t1cap = (z1 - oz)*osz ;
0066 
0067     const float3 c1 = ray_origin + t1cap*ray_direction ; 
0068     const float3 c2 = ray_origin + t2cap*ray_direction ; 
0069 
0070     float crr1 = c1.x*c1.x + c1.y*c1.y ;   // radii squared at cap plane intersects
0071     float crr2 = c2.x*c2.x + c2.y*c2.y ; 
0072 
0073     // NB must disqualify t < t_min at "front" and "back" 
0074     // as this potentially picks between hyp intersects eg whilst near(t_min) scanning  
0075 
0076     const float4 t_cand_ = make_float4(   // restrict radii of cap intersects and z of hyp intersects
0077                                           t1hyp > t_min && disc > zero && h1z > z1 && h1z < z2 ? t1hyp : RT_DEFAULT_MAX ,
0078                                           t2hyp > t_min && disc > zero && h2z > z1 && h2z < z2 ? t2hyp : RT_DEFAULT_MAX ,
0079                                           t2cap > t_min && crr2 < rr2                          ? t2cap : RT_DEFAULT_MAX ,
0080                                           t1cap > t_min && crr1 < rr1                          ? t1cap : RT_DEFAULT_MAX 
0081                                       ) ;
0082 
0083     float t_cand = fminf( t_cand_ );  
0084 
0085     valid_isect = t_cand > t_min && t_cand < RT_DEFAULT_MAX ;
0086     if(valid_isect)
0087     {        
0088         isect.w = t_cand ; 
0089         if( t_cand == t1hyp || t_cand == t2hyp )
0090         {
0091             const float3 p = ray_origin + t_cand*ray_direction ; 
0092             float3 n = normalize(make_float3( p.x,  p.y,  A*p.z )) ;   // grad(level-eqn) 
0093             isect.x = n.x ; 
0094             isect.y = n.y ; 
0095             isect.z = n.z ;      
0096         }
0097         else
0098         {
0099             isect.x = zero ; 
0100             isect.y = zero ; 
0101             isect.z = t_cand == t1cap ? -one : one ;  
0102         }
0103     }
0104 }
0105 
0106