gpt4 book ai didi

c++ - 射线柱相交

转载 作者:行者123 更新时间:2023-12-03 07:04:33 25 4
gpt4 key购买 nike

我正在开发一个光线追踪系统并且它正在运行,现在我正在尝试支持更多基元(目前它支持:球体、长方体、平面和三角形),但我在使用圆柱体时遇到了问题。

我知道要使射线与圆柱体相交,我需要做两个检查,第一个是与主体(我得到一个无限圆柱体),为此我假设二维圆,在平面 xz (x² + z²) = r,其中 r 是半径)然后我需要检查 Y 坐标是否在 0 和高度之间,最后我需要检查交点是否在大写字母中(x²+z²<=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

代码从不在此处输入,这是第一个像素的输出文本(由 std::cout << "point " << point1.y << " hipo " << point1.x*point1.x + point1.z*point1.z << " radio " << m_radius*m_radius << std::endl; 生成)(应该在该条件下输入,因为第一个像素对应于顶盖)

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

我想渲染整个带帽的圆柱体。谁能指导我渲染整个圆柱体? ( body 和帽子)

谢谢

最佳答案

我假设您能够找到射线和圆柱表面之间的交点,作为沿射线的 t 值获得。做类似的计算,找到两个基平面的交点。

你会得到两对 [tc0, tc1], [tp0, tp1]。如果这些间隔不重叠,则光线不会击中圆柱体。否则,tc0 和 tp0 中的最大值告诉您实际击中了哪个表面,而这个 t 值告诉您在哪里。

关于c++ - 射线柱相交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35164707/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com