File indexing completed on 2026-04-09 07:48:54
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #define CSG_OLDCYLINDER_PRECISION_ISSUE 1
0018
0019 LEAF_FUNC
0020 void intersect_leaf_oldcylinder( bool& valid_isect, float4& isect, const quad& q0, const quad& q1, const float t_min, const float3& ray_origin, const float3& ray_direction )
0021 {
0022 const float radius = q0.f.w ;
0023 const float z1 = q1.f.x ;
0024 const float z2 = q1.f.y ;
0025
0026 const float sizeZ = z2 - z1 ;
0027 const float3 position = make_float3( q0.f.x, q0.f.y, z1 );
0028
0029 #ifdef DEBUG_RECORD
0030 printf("//[intersect_leaf_cylinder radius %10.4f z1 %10.4f z2 %10.4f sizeZ %10.4f \n", radius, z1, z2, sizeZ );
0031 #endif
0032 const float3 m = ray_origin - position ;
0033 const float3 n = ray_direction ;
0034 const float3 d = make_float3(0.f, 0.f, sizeZ );
0035
0036 float rr = radius*radius ;
0037 float3 dnorm = normalize(d);
0038
0039 float mm = dot(m, m) ;
0040 float nn = dot(n, n) ;
0041 float dd = dot(d, d) ;
0042 float nd = dot(n, d) ;
0043 float md = dot(m, d) ;
0044 float mn = dot(m, n) ;
0045 float k = mm - rr ;
0046
0047
0048
0049
0050 float a = dd*nn - nd*nd ;
0051 float b = dd*mn - nd*md ;
0052 float c = dd*k - md*md ;
0053
0054
0055 float disc = b*b-a*c;
0056 float t_cand = t_min ;
0057
0058
0059 enum { ENDCAP_P=1, ENDCAP_Q=2 } ;
0060
0061
0062 if(fabs(a) < 1e-6f)
0063 {
0064
0065 #ifdef DEBUG_RECORD
0066 printf("//intersect_leaf_cylinder : axial ray endcap handling, a %10.4g c(dd*k - md*md) %10.4g dd %10.4g k %10.4g md %10.4g \n", a, c,dd,k,md );
0067 #endif
0068 if(c > 0.f)
0069 {
0070 valid_isect = false ;
0071 return ;
0072 }
0073
0074 #ifdef CSG_OLDCYLINDER_PRECISION_ISSUE
0075 float t_PCAP_AX = -mn/nn ;
0076 float t_QCAP_AX = (nd - mn)/nn ;
0077
0078 if(md < 0.f )
0079 {
0080 t_cand = t_PCAP_AX > t_min ? t_PCAP_AX : t_QCAP_AX ;
0081 }
0082 else if(md > dd )
0083 {
0084 t_cand = t_QCAP_AX > t_min ? t_QCAP_AX : t_PCAP_AX ;
0085 }
0086 else
0087 {
0088 t_cand = nd > 0.f ? t_QCAP_AX : t_PCAP_AX ;
0089 }
0090
0091
0092 #else
0093 float t_PCAP_AX = copysignf(1.f, ray_direction.z)*(z1 - ray_origin.z) ;
0094 float t_QCAP_AX = copysignf(1.f, ray_direction.z)*(z2 - ray_origin.z) ;
0095
0096 if(ray_origin.z < z1)
0097 {
0098 t_cand = t_PCAP_AX > t_min ? t_PCAP_AX : t_QCAP_AX ;
0099 }
0100 else if( ray_origin.z > z2 )
0101 {
0102 t_cand = t_QCAP_AX > t_min ? t_QCAP_AX : t_PCAP_AX ;
0103 }
0104 else
0105 {
0106 t_cand = ray_direction.z > 0.f ? t_QCAP_AX : t_PCAP_AX ;
0107 }
0108 #endif
0109
0110 unsigned endcap = t_cand == t_PCAP_AX ? ENDCAP_P : ( t_cand == t_QCAP_AX ? ENDCAP_Q : 0u ) ;
0111
0112 bool has_axial_intersect = t_cand > t_min && endcap > 0u ;
0113
0114 if(has_axial_intersect)
0115 {
0116 float sign = endcap == ENDCAP_P ? -1.f : 1.f ;
0117 isect.x = sign*dnorm.x ;
0118 isect.y = sign*dnorm.y ;
0119 isect.z = sign*dnorm.z ;
0120 isect.w = t_cand ;
0121
0122 #ifdef DEBUG_CYLINDER
0123 CSGDebug_Cylinder dbg = {} ;
0124
0125 dbg.ray_origin = ray_origin ;
0126 dbg.rr = rr ;
0127
0128 dbg.ray_direction = ray_direction ;
0129 dbg.k = k ;
0130
0131 dbg.m = m ;
0132 dbg.mm = mm ;
0133
0134 dbg.n = n ;
0135 dbg.nn = nn ;
0136
0137 dbg.d = d ;
0138 dbg.dd = dd ;
0139
0140 dbg.nd = nd ;
0141 dbg.md = md ;
0142 dbg.mn = mn ;
0143 dbg.checkz = ray_origin.z+ray_direction.z*t_cand ;
0144
0145 dbg.a = a ;
0146 dbg.b = b ;
0147 dbg.c = c ;
0148 dbg.disc = disc ;
0149
0150 dbg.isect = isect ;
0151
0152 CSGDebug_Cylinder::record.push_back(dbg);
0153 #endif
0154 }
0155 valid_isect = has_axial_intersect ;
0156 return ;
0157 }
0158
0159
0160
0161 if(disc > 0.0f)
0162 {
0163 float t_NEAR, t_FAR, sdisc ;
0164 robust_quadratic_roots(t_NEAR, t_FAR, disc, sdisc, a, b, c);
0165
0166 #ifdef DEBUG_CYLINDER
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 #endif
0193
0194
0195 float t_PCAP = -md/nd ;
0196 float t_QCAP = (dd-md)/nd ;
0197
0198
0199 float aNEAR = md + t_NEAR*nd ;
0200 float aFAR = md + t_FAR*nd ;
0201
0202 float3 P1 = ray_origin + t_NEAR*ray_direction ;
0203 float3 P2 = ray_origin + t_FAR*ray_direction ;
0204
0205 float3 N1 = (P1 - position)/radius ;
0206 float3 N2 = (P2 - position)/radius ;
0207
0208 float checkr = 0.f ;
0209 float checkr_PCAP = k + t_PCAP*(2.f*mn + t_PCAP*nn) ;
0210 float checkr_QCAP = k + dd - 2.0f*md + t_QCAP*(2.f*(mn-nd)+t_QCAP*nn) ;
0211
0212
0213 if( aNEAR > 0.f && aNEAR < dd )
0214 {
0215 t_cand = t_NEAR ;
0216 checkr = -1.f ;
0217 }
0218 else if( aNEAR < 0.f )
0219 {
0220 t_cand = nd > 0.f ? t_PCAP : t_min ;
0221 checkr = checkr_PCAP ;
0222 }
0223 else if( aNEAR > dd )
0224 {
0225 t_cand = nd < 0.f ? t_QCAP : t_min ;
0226 checkr = checkr_QCAP ;
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236 if( t_cand > t_min && checkr < 0.f )
0237 {
0238 isect.w = t_cand ;
0239 if( t_cand == t_NEAR )
0240 {
0241 isect.x = N1.x ;
0242 isect.y = N1.y ;
0243 isect.z = 0.f ;
0244 }
0245 else
0246 {
0247 float sign = t_cand == t_PCAP ? -1.f : 1.f ;
0248 isect.x = sign*dnorm.x ;
0249 isect.y = sign*dnorm.y ;
0250 isect.z = sign*dnorm.z ;
0251 }
0252 valid_isect = true ;
0253 return ;
0254 }
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266 if( aFAR > 0.f && aFAR < dd )
0267 {
0268 t_cand = t_FAR ;
0269 checkr = -1.f ;
0270 }
0271 else if( aFAR < 0.f )
0272 {
0273 t_cand = nd < 0.f ? t_PCAP : t_min ;
0274 checkr = checkr_PCAP ;
0275 }
0276 else if( aFAR > dd )
0277 {
0278 t_cand = nd > 0.f ? t_QCAP : t_min ;
0279 checkr = checkr_QCAP ;
0280 }
0281
0282 if( t_cand > t_min && checkr < 0.f )
0283 {
0284 isect.w = t_cand ;
0285 if( t_cand == t_FAR )
0286 {
0287 isect.x = N2.x ;
0288 isect.y = N2.y ;
0289 isect.z = 0.f ;
0290 }
0291 else
0292 {
0293 float sign = t_cand == t_PCAP ? -1.f : 1.f ;
0294 isect.x = sign*dnorm.x ;
0295 isect.y = sign*dnorm.y ;
0296 isect.z = sign*dnorm.z ;
0297 }
0298 valid_isect = true ;
0299 return ;
0300 }
0301
0302 }
0303
0304 valid_isect = false ;
0305 }
0306
0307
0308