Пересечение Ray-Box нормальное

Я пишу простой raytracer, и я ударился о стену, пытаясь получить вектор нормали для выровненного по оси прямоугольника, учитывая точку пересечения.

я использую этот алгоритм пересечения:

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;

Хотя я уверен, что мог бы разбить прямоугольник на плоскости вместо того, чтобы рассматривать его как отдельный примитив, делая вычисление нормальным тривиальным, я хотел бы сохранить этот оптимизированный код пересечения и каким-то образом вычислять нормаль по точке пересечения.

0

Решение

Я нашел способ сделать это:

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;
}

Он дает неправильные результаты по краям окна, но пока это приемлемо.

образец

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]