2016-02-02 41 views
-1

我开发光线追踪系统,它是工作,现在我想支持更多的原语(现在它支持:球,盒,飞机和三角形),和我有缸问题。我知道与圆柱相交的光线我需要做两个检查,第一个是与身体(与我得到一个无限圆柱体),为此,我假设圆二维,在平面XZ(X2 + Z 2 = r,其中r是半径),那么我需要检查Y坐标是0,并且高度和最后我需要检查的交集是在帽(X 2 + Z 2 < = r,其中r是半径)之间。雷圆柱相交

我的代码是后续(见更多的解释评论)

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 a = 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 the smallest and >=0 t 
    if (x1 > x2) 
    { 
     t=x2; 
    } 

    if (t < 0) 
    { 
     t=x1; 
    } 


    // if both solution are <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 the y-component from point computed is smaller than 0 or bigger than height => NO INTERSECTION! 
    if (point.y < 0 || point.y > m_height) 
    { 
     return Intersection(false); 
    } 

    //If ray direction is not pararel to Y Plane 
    if (ray.getDirection().y != 0.0f) //Paralel 
    { 
     //Compute t's for point intersection in the Y Plane 
     float t3 = (0-ray.getOrigin().y)/ray.getDirection().y; 
     float t4 = (m_height-ray.getOrigin().y)/ray.getDirection().y; 
     float t2; 

     //choose the smallest and >=0 t 
     t2 = std::min(t3,t4); 
     if (t2 < 0) 
     { 
      t2 = std::max(t3,t4); 
     } 
     if (t2 >= 0) 
     { 
      // If there is a t >= 0 compute de point and check if the point is inside the 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 is inside cap but, Which t is the smallest? t from cap or t from body cylinder? 
       // I choose the smallest t and check if the t is from cap and compute normal and 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 the body cylinder, compute the point and return the intersection 
    point = ray.getOrigin() + ray.getDirection()*t; 

    return Intersection(true, point, normal); 
} 

这段代码的结果如下图

enter image description here

中(正如你所看到的顶盖不渲染,而且我要渲染的帽子也)

我一直在研究和问题看起来像在这里:

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

的代码不会进入这里,这里是从首创pixeles输出文本(由std::cout << "point " << point1.y << " hipo " << point1.x*point1.x + point1.z*point1.z << " radio " << m_radius*m_radius << std::endl;生成)(应该在该条件下进入,因为第一pixeles与顶帽对应)

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 

正如你看到的永远是hipo比< radio

我想渲染与瓶盖整缸。任何人都可以指导我渲染整个圆柱体吗? (本体和帽)

由于

+0

实际上你的图形框架是什么? –

+0

我建立一个光线从头开始追查,我不使用框架 – RdlP

+1

好吧,发布[MCVE]强硬,或让你的问题更简洁。 _“任何建议”都太模糊。 –

回答

0

我假设你能够找到光线与圆柱面,沿射线吨值获得之间的交叉点。做一个类似的计算来找到两个基面的交点。

您将得到两双[TC0,TC1],[TP0,TP1。如果这些间隔不重叠,射线不会撞击圆柱体。否则,tc0和tp0中最大的值告诉你实际击中的是什么表面,这个t值告诉你在哪里。