Ray-Box交叉正常

时间:2013-06-01 18:30:57

标签: c++ raytracing

我正在编写一个简单的光线跟踪器,并且在尝试获取轴对齐框的法线向量时,我已经碰到了墙,给定了交点。

我正在使用this intersection algorithm

float tmin, tmax, tymin, tymax, tzmin, tzmax;
if (ray.direction.x >= 0) {
    tmin = (min.x - ray.origin.x) / ray.direction.x;
    tmax = (max.x - ray.origin.x) / ray.direction.x;
}
else {
    tmin = (max.x - ray.origin.x) / ray.direction.x;
    tmax = (min.x - ray.origin.x) / ray.direction.x;
}
if (ray.direction.y >= 0) {
    tymin = (min.y - ray.origin.y) / ray.direction.y;
    tymax = (max.y - ray.origin.y) / ray.direction.y;
} else {
    tymin = (max.y - ray.origin.y) / ray.direction.y;
    tymax = (min.y - ray.origin.y) / ray.direction.y;
}
if ((tmin > tymax) || (tymin > tmax)) {
    return -1;
}
if (tymin > tmin) {
    tmin = tymin;
}
if (tymax < tmax) {
    tmax = tymax;
}
if (ray.direction.z >= 0) {
    tzmin = (min.z - ray.origin.z) / ray.direction.z;
    tzmax = (max.z - ray.origin.z) / ray.direction.z;
} else {
    tzmin = (max.z - ray.origin.z) / ray.direction.z;
    tzmax = (min.z - ray.origin.z) / ray.direction.z;
}
if ((tmin > tzmax) || (tzmin > tmax)) {
    return -1;
}
if (tzmin > tmin) {
    tmin = tzmin;
}
if (tzmax < tmax) {
    tmax = tzmax;
}
return tmin;

虽然我确信我可以将盒子分解为平面而不是将其视为一个单独的基元,使计算变得正常,我想保留这个优化的交叉码并以某种方式从交点计算法线。

1 个答案:

答案 0 :(得分:2)

我找到了办法:

v3 Box::normalAt(const v3 &point) {
    v3 normal;
    v3 localPoint = point - center;
    float min = std::numeric_limits<float>::max();
    float distance = std::abs(size.x - std::abs(localPoint.x));
    if (distance < min) {
        min = distance;
        normal.set(1, 0, 0);
        normal *= SIGN(localPoint.x);
    }
    distance = std::abs(size.y - std::abs(localPoint.y));
    if (distance < min) {
        min = distance;
        normal.set(0, 1, 0);
        normal *= SIGN(localPoint.y);
    }
    distance = std::abs(size.z - std::abs(localPoint.z));
    if (distance < min) { 
        min = distance; 
        normal.set(0, 0, 1);
        normal *= SIGN(localPoint.z);
    } 
    return normal;
}

它在框的边缘产生错误的结果,但现在可以接受。

sample