问题
我正在编写光线追踪器,作为计算机图形学中特定机器学习方法的用例。
我的问题是,当我尝试找到射线与表面之间的交点时,结果不准确。
基本上,如果我将光线从 O点散射到位于(x,y,z)的表面,其中z = 81,则我希望解决方案是类似 S =(x,y,81)。
问题是:我得到了类似(x,y,81.000000005)的解决方案。
这当然是一个问题,因为后续操作取决于该解决方案,并且它必须是准确的解决方案。
问题
我的问题是:计算机图形学的人如何处理这个问题?我试图将变量从float
更改为double
,但这不能解决问题。
替代解决方案
我尝试使用功能std::round()
。这仅在特定情况下有帮助,但在确切的解决方案包含一个或多个有效数字时则无济于事。
std::ceil()
和std::floor()
相同。
编辑
这是我计算与平行于 xz 轴的表面(矩形)的交点的方式。
首先,我计算射线的原点与曲面之间的距离t
。如果我的射线在那个特定方向上没有撞击到表面,则t
返回为0。
class Rectangle_xy: public Hitable {
public:
float x1, x2, y1, y2, z;
...
float intersect(const Ray &r) const { // returns distance, 0 if no hit
float t = (y - r.o.y) / r.d.y; // ray.y = t* dir.y
const float& x = r.o.x + r.d.x * t;
const float& z = r.o.z + r.d.z * t;
if (x < x1 || x > x2 || z < z1 || z > z2 || t < 0) {
t = 0;
return 0;
} else {
return t;
}
....
}
具体来说,给定一个Ray和列表中一个对象的id
(我要命中):
inline Vec hittingPoint(const Ray &r, int &id) {
float t; // distance to intersection
if (!intersect(r, t, id))
return Vec();
const Vec& x = r.o + r.d * t;// ray intersection point (t calculated in intersect())
return x ;
}
如果我与某个对象相交,则上一段代码中的函数intersect()
将检查列表rect
中的每个Rectangle:
inline bool intersect(const Ray &r, float &t, int &id) {
const float& n = NUMBER_OBJ; //Divide allocation of byte of the whole scene, by allocation in byte of one single element
float d;
float inf = t = 1e20;
for (int i = 0; i < n; i++) {
if ((d = rect[i]->intersect(r)) && d < t) { // Distance of hit point
t = d;
id = i;
}
}
// Return the closest intersection, as a bool
return t < inf;
}
然后使用3D空间中的线和曲面之间的几何插值获得坐标:
Vec& x = r.o + r.d * t;
其中:
r.o
:代表射线原点。它被定义为r.o:Vec(float a, float b, float c
)
r.d
:这是射线的方向。如前所述:r.d:Vec(float d, float e, float f
)。
t
:float
代表物体与原点之间的距离。
答案 0 :(得分:0)
您可以考虑使用std::numeric_limits<T>::epsilon
进行浮动/双重比较。并查看结果是否在+-ε区域。
一种替代方法是不向点发出光线跟踪。也许只是在其中放置相对较小的盒子或球体即可。