C++ 射线有界平面相交

C++ 射线有界平面相交,c++,math,linear-algebra,intersection,raytracing,C++,Math,Linear Algebra,Intersection,Raytracing,我想在空闲时间写一个光线跟踪器。目前正在尝试进行光线边界平面相交 我的程序已经在无限平面上运行了。我在尝试计算非无限平面的数学。试图用谷歌搜索,但所有的资源都只讨论无限平面 我的平面有一个角点(称为位置),两个向量(u和v)从这里延伸(它们的长度对应于边的长度)。光线有原点和方向 首先,我用公式计算与无限平面的交点 t=normal*(位置-原点)/(normal*方向) 法线计算为u和v的叉积。 然后用公式 原点+方向*t 我得到了交点本身 下一步是检查这个点是否在矩形的边界内,这就是我遇到问

我想在空闲时间写一个光线跟踪器。目前正在尝试进行光线边界平面相交

我的程序已经在无限平面上运行了。我在尝试计算非无限平面的数学。试图用谷歌搜索,但所有的资源都只讨论无限平面

我的平面有一个角点(称为位置),两个向量(u和v)从这里延伸(它们的长度对应于边的长度)。光线有原点和方向

首先,我用公式计算与无限平面的交点

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