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_disc
0005 ---------------------
0006 
0007 RTCD p197  (Real Time Collision Detection)
0008 
0009 CSG_DISC was implemented to avoid degeneracy/speckle problems when using CSG_CYLINDER
0010 to describe very flat cylinders such as Daya Bays ESR mirror surface. 
0011 Note that the simplicity of disc intersects compared to cylinder has allowed 
0012 inner radius handling (in param.f.z) for easy annulus definition without using CSG subtraction.
0013 
0014 NB ray-plane intersects are performed with the center disc only at:  z = zc = (z1+z2)/2 
0015 The t_center obtained is then deltared up and down depending on (z2-z1)/2
0016 
0017 This approach appears to avoid the numerical instability speckling problems encountered 
0018 with csg_intersect_cylinder when dealing with very flat disc like cylinders. 
0019 
0020 Note that intersects with the edge of the disk are not implemented, if such intersects
0021 are relevant you need to use CSG_CYLINDER not CSG_DISC.
0022 
0023 
0024 For testing see tboolean-esr and tboolean-disc.::
0025 
0026                 r(t) = O + t n 
0027 
0028                                ^ /         ^ 
0029                                |/          | d
0030          ----------------------+-----------|-------------------------------- z2
0031                               /            |
0032          - - - - - - - - - - * - - - - - - C- - -  - - - - - - - - - - - - - zc
0033                             /
0034          ------------------+------------------------------------------------ z1
0035                           /|
0036                          / V
0037                         /
0038                        O
0039 
0040           m = O - C
0041 
0042 
0043 To work as a CSG sub-object MUST have a different intersect 
0044 on the other side and normals must be rigidly attached to 
0045 geometry (must not depend on ray direction)
0046 
0047 
0048 Intersect of ray and plane::
0049 
0050     r(t) = ray_origin + t * ray_direction
0051 
0052     (r(t) - center).d  = ( m + t * n ).d  = 0    <-- at intersections of ray and plane thru center with normal d 
0053 
0054     t = -m.d / n.d 
0055 
0056 Consider wiggling center up to z2 and down to z1 (in direction of normal d) n.d is unchanged::
0057 
0058     (r(t) - (center+ delta d )).d = 0
0059 
0060     (m - delta d ).d + t * n.d = 0 
0061 
0062     m.d - delta + t* nd = 0 
0063 
0064     t =  -(m.d + delta) / n.d              
0065 
0066       = -m.d/n.d  +- delta/n.d
0067 
0068 
0069 Intersect is inside disc radius when::
0070 
0071     rsq =   (r(t) - center).(r(t) - center) < radius*radius
0072 
0073     (m + t n).(m + t n)  <  rr
0074 
0075     t*t nn + 2 t nm + mm  <  rr  
0076 
0077     t ( 2 nm + t nn ) + mm   <  rr    
0078 
0079     rsq < rr    checkr(from cylinder) is: rsq - rr 
0080 
0081 
0082 Determine whether the t_cand intersect hit after delta-ing 
0083 is on the upside (normal +Z) or downside (normal -Z) of disc
0084 from the sign of the below dot product, allowing determination 
0085 of the rigid outward normal direction.::
0086 
0087     r(t) = ray_origin + t * ray_direction
0088 
0089     (r(t_cand) - center).d  = m.d + t_cand n.d     
0090 
0091 **/
0092 
0093 LEAF_FUNC
0094 void intersect_leaf_disc(bool& valid_isect, float4& isect, const quad& q0, const quad& q1, const float t_min, const float3& ray_origin, const float3& ray_direction )
0095 {
0096     const float   inner  = q0.f.z ; 
0097     const float   radius = q0.f.w ; 
0098     const float       z1 = q1.f.x  ; 
0099     const float       z2 = q1.f.y  ;            // NB z2 > z1 by assertion in npy-/NDisc.cpp
0100     const float       zc = (z1 + z2)/2.f  ;     // avg
0101     const float       zdelta = (z2 - z1)/2.f ;  // +ve half difference 
0102 
0103     const float3 center = make_float3( q0.f.x, q0.f.y, zc ); // C: point at middle of disc
0104 
0105 #ifdef DEBUG
0106     printf("//intersect_leaf_disc (%10.4f, %10.4f, %10.4f) \n", center.x, center.y, center.z ); 
0107 #endif
0108 
0109 
0110     const float3 m = ray_origin - center ;            // m: ray origin in disc frame
0111     const float3 n = ray_direction ;                  // n: ray direction vector (not normalized)
0112     const float3 d = make_float3(0.f, 0.f, 1.f );     // d: normal to the disc (normalized)
0113 
0114     float rr = radius*radius ; 
0115     float ii = inner*inner ; 
0116 
0117     float mm = dot(m, m) ; 
0118     float nn = dot(n, n) ; 
0119     float nd = dot(n, d) ;   // >0 : ray direction in same hemi as normal
0120     float md = dot(m, d) ;
0121     float mn = dot(m, n) ; 
0122 
0123     float t_center = -md/nd ; 
0124     float rsq = t_center*(2.f*mn + t_center*nn) + mm  ;   // ( m + tn).(m + tn) 
0125 
0126     float t_delta  = nd < 0.f ? -zdelta/nd : zdelta/nd ;    // <-- pragmatic make t_delta +ve
0127 
0128     float root1 = t_center - t_delta ; 
0129     float root2 = t_center + t_delta ;   // root2 > root1
0130  
0131     float t_cand = ( rsq < rr && rsq > ii ) ? ( root1 > t_min ? root1 : root2 ) : t_min ; 
0132 
0133     float side = md + t_cand*nd ;    
0134 
0135     valid_isect = t_cand > t_min ;
0136     if(valid_isect)
0137     {        
0138         isect.x = 0.f ; 
0139         isect.y = 0.f ; 
0140         isect.z = side > 0.f ? 1.f : -1.f ; 
0141         isect.w = t_cand  ; 
0142     }
0143 }
0144 
0145