C++ 射线有界平面相交
我想在空闲时间写一个光线跟踪器。目前正在尝试进行光线边界平面相交 我的程序已经在无限平面上运行了。我在尝试计算非无限平面的数学。试图用谷歌搜索,但所有的资源都只讨论无限平面 我的平面有一个角点(称为位置),两个向量(u和v)从这里延伸(它们的长度对应于边的长度)。光线有原点和方向 首先,我用公式计算与无限平面的交点C++ 射线有界平面相交,c++,math,linear-algebra,intersection,raytracing,C++,Math,Linear Algebra,Intersection,Raytracing,我想在空闲时间写一个光线跟踪器。目前正在尝试进行光线边界平面相交 我的程序已经在无限平面上运行了。我在尝试计算非无限平面的数学。试图用谷歌搜索,但所有的资源都只讨论无限平面 我的平面有一个角点(称为位置),两个向量(u和v)从这里延伸(它们的长度对应于边的长度)。光线有原点和方向 首先,我用公式计算与无限平面的交点 t=normal*(位置-原点)/(normal*方向) 法线计算为u和v的叉积。 然后用公式 原点+方向*t 我得到了交点本身 下一步是检查这个点是否在矩形的边界内,这就是我遇到问
t=normal*(位置-原点)/(normal*方向)
法线计算为u和v的叉积。
然后用公式
原点+方向*t
我得到了交点本身
下一步是检查这个点是否在矩形的边界内,这就是我遇到问题的地方
我的想法是获得从平面角延伸到交点的相对向量交点位置
,然后将其转换为u、法线和v的新基,然后检查转换向量的长度是否比u和v向量短
bool边界平面::相交(常量向量3f和原点、常量向量3f和方向、浮点和t)常量{
t=法线*(位置-原点)/(法线*方向);
Vec3f相对=(原点+方向*t)-位置;
Mat3f变换{
Vec3f(u.x,正常x,v.x),
Vec3f(u.y,normal.y,v.y),
Vec3f(u.z,normal.z,v.z)
};
Vec3f local=transform.mul(相对);
返回t> 0 & &局部x>=0 & &局部.x我能建议另一种方法吗?
位置
和基向量
u = { u.x, u.y, u.z }
v = { v.x, v.y, v.z }
direction = { direction.x, direction.y, direction.z}
步骤1:形成矩阵
M = {
{u.x, v.x, direction.x},
{u.y, v.y, direction.y},
{u.z, v.z, direction.z}
}
第2步:计算向量w
,这是线性方程组的3 x 3解
M*w=原点位置
,即
w = inverse(M) * (origin - position);
确保方向
与u,v
不共面,否则不存在交点且反向(M)
不存在
第3步:如果0.0,什么是“奇怪的线条”?你有失败案例吗?在文章中添加了图片。失败案例是什么意思?当光线完全不相交时(在这种情况下,由于t>0条件,函数只返回false)?失败案例是指函数给出错误结果的案例。即,有界平面和射线应该相交,但不相交,或者不应该相交,但确实相交。我仍然不确定你的问题是什么。你是在问一个具体的数字案例吗?一系列可能的问题:1)传递到Mat3f
的向量是否为con结构或其行或列?-如果它们是行,那么它们应该是三个基向量。2)它们也应该被规范化,或者你需要考虑缩放。3)由于local
位于平面的…局部基中,因此它应该由(|u|,|v|)约束(或(宽度、长度)
如果您选择标准化u,v
),而不是(u.x,v.z)
这是世界坐标系。谢谢,我最终得到了原始的变换矩阵,但你的帖子告诉我,我的数学不正确,我必须求逆矩阵。它现在工作,但与以前相比速度非常慢。问题中的简单场景用了我大约2秒的时间来计算,4个平面大约需要20秒-30秒。@DanielSmith只是出于好奇,是矩阵求逆减慢了速度吗?你用什么算法求矩阵求逆(我想它是库的一部分)?是的,我认为是求逆减慢了速度。我用的是一个自编的线性代数标题(我试过Eigen 3,但它大大减慢了计算速度).现在它只是一个硬编码的3x3逆,我写它是为了检查你的答案是否给了我正确的结果。我将重做它。@DanielSmith从技术上讲,你不需要反转矩阵,你只需要在步骤2中解线性方程组。也许我们可以想出一个线性系统的快速解算器,而不是反转。到目前为止,我尽量避免使用任何库,因为它们对于这么多的计算来说速度太慢,而且我在大学学习线性代数已经有几年了,所以逆运算听起来比线性方程求解器更容易。不过,我对一切都持开放态度。
w0 = { w.x, w.y , 0 };
intersection = position + M * w0;
a b c
d e f
g h i
(1 / det(M)) * {
{e*i - f*h, c*h - b*i, b*f - c*e},
{f*g - d*i, a*i - c*g, c*d - a*f},
{d*h - e*g, b*g - a*h, a*e - b*d},
}
det(M) = a*(e*i - f*h) + b*(f*g - d*i) + c*(d*h - e*h)
M = {
{a, b, c},
{d, e, f},
{g, h, i},
}
inv_M = {
{e*i - f*h, c*h - b*i, b*f - c*e},
{f*g - d*i, a*i - c*g, c*d - a*f},
{d*h - e*g, b*g - a*h, a*e - b*d},
};
det_M = a*inv_M[1][1] + b*inv_M[2][1] + c*inv_M[3][1];
inv_M = (1/det_M) * inv_M;
normal = cross(u, v);
u_dot_u = dot(u, u);
u_dot_v = dot(u, v);
v_dot_v = dot(v, v); // all these need to be computed only once for the u and v vectors
det = u_dot_u * v_dot_v - u_dot_v * u_dot_v; // again only once per u and v
t = dot(normal, position - origin) / dot(normal, direction);
int_point = origin + t * direction;
rhs = int_point - position;
u_dot_rhs = dot(u, rhs);
v_dot_rhs = dot(v, rhs);
w1 = (v_dot_v * u_dot_rhs - u_dot_v * v_dot_rhs) / det;
w2 = (- u_dot_v * u_dot_rhs + u_dot_u * v_dot_rhs) / det;
if (0 < = w1 && w1 <= 1 && 0 < = w2 && w2 <= 1 ){
int_point is in the parallelogram;
}
else{
int_point is not in the parallelogram;
}
int_point = position + w1 * u + w2 * v;
rhs = int_point - position = w1 * u + w2 * v