|
|
|||
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
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|