问题描述
请问您有什么建议用C#编写我的raytracer。这是障碍:
在我的raytracer中检测射线和几何图形的命中时遇到问题。根据本文,我已经实现了几个功能:https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/ray-triangle-intersection-geometric-solution
这是计算生命值的代码:
public Vector3 GetHitPoint(Vector3 origin,Vector3 ray)
{
float D = Vector3.Dot(this.Getnormal(),vertices[0]);
float up = Vector3.Dot(this.Getnormal(),origin);
up = -1 * (up + D); //50
float down =Vector3.Dot(this.Getnormal(),ray); //0.999975
float t = up / -1* down; //50,00125003125078
Console.WriteLine(origin + Vector3.Multiply(t,ray));
return origin + Vector3.Multiply(t,ray);
}
不是很优雅,但是可以工作。我有精度问题。我准备了垂直于相机放置的测试三角形(中心-> 0,50)。该代码计算三角形和射线之间的交点。 原点代表摄影机位置,射线是从摄影机到几何的归一化向量,顶点[0]是顶点的位置,Getnormal()函数提供正确的三角形法线向量。在这种情况下,问题在于计算的准确性。完成所有这些计算后,我的命中点的z坐标为49.99975而不是50.0。
这是一个问题,因为我使用另一种算法(基于重心坐标)来检查击中点是否在三角形内。
public bool CheckHitPoint(Vector3 P)
{
Vector3 v0 = vertices[1] - vertices[0];
Vector3 v1 = vertices[2] - vertices[0];
Vector3 v2 = P - vertices[0];
float d00 = Vector3.Dot(v0,v0);
float d01 = Vector3.Dot(v0,v1);
float d11 = Vector3.Dot(v1,v1);
float d20 = Vector3.Dot(v2,v0);
float d21 = Vector3.Dot(v2,v1);
float denom = d00 * d11 - d01 * d01;
float v = (d11 * d20 - d01 * d21);
float w = (d00 * d21 - d01 * d20);
float u = 1.0f - v - w;
if (u < 0 || v < 0 || w < 0)
{
return false;
}
else if (u > 1 || v > 1 || w > 1)
{
return false;
}
else return true;
}
算法和本文中的条件相同,但是由于先前函数的结果不正确,因此u v w系数完全错误(因为命中点实际上位于三角形的前面)。
我能否请您帮助我解决第一种算法中的精度问题,或者在第二种算法中引入某种偏差,以便我能够获得精确的命中点并成功地在三角形内部检测到它?
编辑:对不起,我认为这个问题很明确。让我更深入地解释。让我们看一下三角形:
Vector3[] vertices =
{
new Vector3(-5,-5,50),new Vector3(5,new Vector3(0,5,50)
};
Vector3[] normals =
{
new Vector3(0,-1),-1)
};
很明显,这个三角形的法线向量为n(0,0,-1),并且结合其表面上的任何点,都可以用数学方式描述该表面。
D是(0,0)到三角形所位于的曲面上的点之间的距离。由于可以将表面描述为一对参数(法向矢量和表面上的任何点),因此这些参数的点积描述为D。
接下来的四行描述该方程式: t = N(A,B,C)⋅O+ D / -N(A,B,C)⋅R
其中
N(A,B,C)-三角形的法线向量
O-摄像机位置
D-(0,0)到曲面的距离
R-归一化射线矢量
等式计算从摄像机位置到交叉点的距离。
按照这些方程式,在附加了三角形参数I并将摄像机位置(0,0)初始化为(0,50)的情况下,返回值应为坐标为(x,y,50)的点我创建射线的像素是什么? 问题是,c#中的矢量方法通常使用浮点数进行计算,这就是为什么z坐标接近但不精确为50的原因。 从数学上讲,这是100%正确的,但精度很差。
当我尝试检查点是否通过重心坐标转换而位于三角形内部时,这会带来问题。 第二种方法在数学上也是可以的。假设Hitpoint在表面上,如果所有坐标都在0到1之间,则表示该点位于三角形上。此处的详细信息:https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates
如果我只能精确计算以前方法中的坐标,那将起作用。问题是,由于缺乏精度,命中点略微位于曲面的顶部或下方,并且重心坐标具有疯狂的价值。
问题是,我怎样才能使第一种方法更加精确,这意味着重现相机与命中点之间的t-距离,使其精度足以达到50。哪种解决方案是最好的,四舍五入,创建自定义方法用于替换内置的基于float的方法的矢量,或者某些算法的修改? 如果有射线跟踪经验的人能给我一些建议,将不胜感激。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)