c++ - Ray Cylinder intersection -


i developing ray tracing system , working, trying support more primitives (for supports: spheres, boxes, planes , triangles), , having problems cylinders.

i know intersect ray cylinder need 2 check, first body (with infinite cylinder), assume circle in 2 dimensions, in plane xz (x² + z² = r, r radius) need check y coordinate between 0 , height , need check if intersection in caps (x²+z²<=r, r radius).

my code follow (see comments more explanations)

intersection cylinder::hit(ray ray) {     ray.setorigin(vec3(getinversetransform() * vec4(ray.getorigin(),1)));     ray.setdirection(glm::normalize(vec3(getinversetransform() * vec4(ray.getdirection(),0))));      // r(t) = o + td     // x² + z² = r²     // (ox+tdx)² + (oz+tdz)² = r²     // (ox)² + 2oxtdx + (tdx)² + (oz)² + 2oztdz + (tdz)² = r²     // t²(dx + dz) + 2t(oxdx + ozdz) + (ox)² + (oz)² - r² = 0     // a=(dx + dz); b = 2(oxdx + ozdz); c = (ox)² + (oz)² - r²     float = ray.getdirection().x*ray.getdirection().x + ray.getdirection().z*ray.getdirection().z;     float b = 2*(ray.getorigin().x*ray.getdirection().x + ray.getorigin().z*ray.getdirection().z);     float c = ray.getorigin().x*ray.getorigin().x + ray.getorigin().z*ray.getorigin().z - m_radius*m_radius;      float discr = b*b - 4*a*c;     if (discr < 0)     {         return intersection(false);     }      float x1 = (-b+sqrt(discr))/(2*a);     float x2 = (-b-sqrt(discr))/(2*a);      float t;     //choose smallest , >=0 t     if (x1 > x2)     {         t=x2;     }      if (t < 0)     {         t=x1;     }       // if both solution <0 => no intersection!     if (t<0)     {         return intersection(false);     }      // normal calculation     // f(x,y) = x² + z² - r² = 0     // t = (dx/dt, y, dz/dt)     // 0 = df/dt = (df/dx, y, df/dz) · t     // n = (2x, 0, 2z)     vec3 point = ray.getorigin() + ray.getdirection()*t;     vec3 normal = vec3(2*point.x, 0.0f, 2*point.z);       // if y-component point computed smaller 0 or bigger height => no intersection!     if (point.y < 0 || point.y > m_height)     {         return intersection(false);     }      //if ray direction not pararel y plane     if (ray.getdirection().y != 0.0f) //paralel     {         //compute t's point intersection in y plane         float t3 = (0-ray.getorigin().y)/ray.getdirection().y;         float t4 = (m_height-ray.getorigin().y)/ray.getdirection().y;         float t2;          //choose smallest , >=0 t         t2 = std::min(t3,t4);         if (t2 < 0)         {             t2 = std::max(t3,t4);         }         if (t2 >= 0)         {             // if there t >= 0 compute de point , check if point inside cap             vec3 point1 = ray.getorigin() + ray.getdirection()*t2;             std::cout << "point " << point1.y << " hipo "  << point1.x*point1.x + point1.z*point1.z << " radio " << m_radius*m_radius << std::endl;             if (point1.x*point1.x + point1.z*point1.z <= m_radius*m_radius+0.9f)             {                 // intersection point inside cap but, t smallest? t cap or t body cylinder?                 // choose smallest t , check if t cap , compute normal , return intersection.                 t = std::min(t,t2);                 if (t == t3)                 {                     normal = vec3(0.0f,-1.0f,0.0f);                     return intersection(true, point1, normal);                 }                 else if (t == t4)                 {                     normal = vec3(0.0f,1.0f,0.0f);                     return intersection(true, point1, normal);                 }             }         }     }      // intersection in body cylinder, compute point , return intersection     point = ray.getorigin() + ray.getdirection()*t;      return intersection(true, point, normal); } 

this code result in following image

enter image description here

(as can see top cap not rendering, , want render caps also)

i have been researching , problem here:

point1.x*point1.x + point1.z*point1.z <= m_radius*m_radius

the code never enter here, here output text (generated std::cout << "point " << point1.y << " hipo " << point1.x*point1.x + point1.z*point1.z << " radio " << m_radius*m_radius << std::endl;) firsts pixeles (that should enter in condition because first pixeles corresponds top cap)

point 0.5 hipo 0.0900812 radio 0.09 point 0.5 hipo 0.0900206 radio 0.09 point 0.5 hipo 0.0900812 radio 0.09 point 0.5 hipo 0.0900206 radio 0.09 pixel: y: 280 point 0.5 hipo 0.0913921 radio 0.09 point 0.5 hipo 0.120013 radio 0.09 point 0.5 hipo 0.0913921 radio 0.09 point 0.5 hipo 0.120013 radio 0.09 pixel: y: 281 point 0.5 hipo 0.0930369 radio 0.09 point 0.5 hipo 0.183345 radio 0.09 point 0.5 hipo 0.0930369 radio 0.09 point 0.5 hipo 0.183345 radio 0.09 pixel: y: 282 point 0.5 hipo 0.0950108 radio 0.09 point 0.5 hipo 0.261889 radio 0.09 point 0.5 hipo 0.0903952 radio 0.09 point 0.5 hipo 0.0903952 radio 0.09 point 0.5 hipo 0.0950108 radio 0.09 point 0.5 hipo 0.261889 radio 0.09 pixel: y: 283 point 0.5 hipo 0.0973093 radio 0.09 point 0.5 hipo 0.347767 radio 0.09 point 0.5 hipo 0.0927148 radio 0.09 point 0.5 hipo 0.0927148 radio 0.09 point 0.5 hipo 0.0973093 radio 0.09 point 0.5 hipo 0.347767 radio 0.09 

as can see never hipo < radio

i want render whole cylinder caps. can guide me render whole cylinder? (body , caps)

thanks

i assume able find intersection points between ray , cylinder surface, obtained t values along ray. similar computation find intersections planes of 2 basis.

you 2 pairs [tc0, tc1], [tp0, tp1]. if these intervals not overlap, ray doesn't hit cylinder. otherwise, largest of tc0 , tp0 tells surface hit, , t value tells where.


Comments

Popular posts from this blog

Delphi XE2 Indy10 udp client-server interchange using SendBuffer-ReceiveBuffer -

Qt ActiveX WMI QAxBase::dynamicCallHelper: ItemIndex(int): No such property in -

Enable autocomplete or intellisense in Atom editor for PHP -