如何计算光线与平面之间的交点?我一直在访问我能找到的每个可能的网站,这是我迄今为止取得的成就:
float denom = normal.dot(ray.direction);
if (denom > 0)
{
float t = -((center - ray.origin).dot(normal)) / denom;
if (t >= 0)
{
rec.tHit = t;
rec.anyHit = true;
computeSurfaceHitFields(ray, rec);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用:s
我的函数输入是:
ray:包含原点和方向.
rec:用于存储命中信息的容器类(bool,t等)
我的函数可以访问平面:
点:定义平面
法线的点:定义平面的法线
Tri*_*ian 19
正如你所评论的那样,你也希望分母为负数,否则你会错过与飞机前面的交叉点.但是,您仍然希望测试避免被零除,这表示光线与平面平行.你的计算中也有一个多余的否定t.总的来说,它应该是这样的:
float denom = normal.dot(ray.direction);
if (abs(denom) > 0.0001f) // your favorite epsilon
{
float t = (center - ray.origin).dot(normal) / denom;
if (t >= 0) return true; // you might want to allow an epsilon here too
}
return false;
Run Code Online (Sandbox Code Playgroud)
首先考虑光线平面交点的数学运算:
通常,一个与光线的参数形式相交,与几何的隐式形式相交.
因此,给定x = a*t + a0形式的光线,y = b*t + b0,z = c*t + c0;
和形式的平面:A x*B y*C z + D = 0;
现在将x,y和z射线方程代入平面方程,你将得到t中的多项式.然后你用t的实数值求解那个多项式.利用t的这些值,您可以将替代值替换为射线方程,以获得x,y和z的实际值.这是在千里马:

请注意,答案看起来像两个点产品的商!平面的法线是平面方程A,B和C的前三个系数.您仍然需要D来唯一地确定平面.然后用您选择的语言编写代码,如下所示:
Point3D intersectRayPlane(Ray ray, Plane plane)
{
Point3D point3D;
// Do the dot products and find t > epsilon that provides intersection.
return (point3D);
}
Run Code Online (Sandbox Code Playgroud)
定义:
令射线参数化地给出为q = p + t*v的初始点p和 的方向向量。vt >= 0
r令平面为满足dot(n, r) + d = 0法向量n = (a, b, c)和常数方程的点集d。完全展开后,平面方程也可以写成熟悉的形式ax + by + cz + d = 0。
当满足平面方程时,光线与q平面相交。代入,我们有:
d = -dot(n, q)
= -dot(n, p + t * v)
= -dot(n, p) + t * dot(n, v)
Run Code Online (Sandbox Code Playgroud)
重新排列:
t = -(dot(n, p) + d) / dot(n, v)
Run Code Online (Sandbox Code Playgroud)
该值t可用于通过将其插回 来确定交集p + t*v。
std::optional<vec3> intersectRayWithPlane(
vec3 p, vec3 v, // ray
vec3 n, float d // plane
) {
float denom = dot(n, v);
// Prevent divide by zero:
if (abs(denom) <= 1e-4f)
return std::nullopt;
// If you want to ensure the ray reflects off only
// the "top" half of the plane, use this instead:
//
// if (-denom <= 1e-4f)
// return std::nullopt;
float t = -(dot(n, p) + d) / dot(n, v);
// Use pointy end of the ray.
// It is technically correct to compare t < 0,
// but that may be undesirable in a raytracer.
if (t <= 1e-4)
return std::nullopt;
return p + t * v;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28980 次 |
| 最近记录: |