Пересечения трассировки лучей - PullRequest
0 голосов
/ 18 января 2012

Итак, я вернулся с другим вопросом о трассировке лучей. Мой код хорошо отображает сферы, но кубы на самом деле не работают. Я использую этот код для проверки пересечений: http://pastebin.com/qgm6vpdx (это рекурсивная функция, t - расстояние до точки пересечения) Ограничительная рамка определяется как:

Cube* c1 = new Cube;      
c1->Corner1 = Vec3(100, 100, 100);      
c1->Corner2 = Vec3(200, 200, 200);

Я подтвердил, что камера не находится внутри куба. Теперь единственная проблема заключается в том, что весь экран отображается зеленым цветом (цвет, обозначенный для куба)

Я не думаю, что правильно делаю пересечения кубов, может ли кто-нибудь проверить мой код?

Ответы [ 2 ]

6 голосов
/ 20 января 2012

Один из лучших алгоритмов для вычисления пересечений между лучами - метод slab . Я обрисовал в общих чертах мою оптимизированную реализацию этого здесь , а также.

3 голосов
/ 18 января 2012

Вы можете сделать код намного короче и более читабельным.Например, измените int tNear = -2147000000 на int tNear = INT_MIN и измените

if(t1 > t2)
{
    float temp1 = t1;
    t1 = t2;
    t2 = temp1;
}

на

if(t1 > t2)
{
    // std::swap is built-in
    swap(t1, t2);
}

или лучше

// Define 'order' yourself
order(t1, t2);

и измените

if(t1 > tNear)
{
   tNear = t1;
}

до

// std::max is built in
tNear = max(tNear, t1);

Тогда одна часть вашего кода становится такой:

if ((ray.dir.x == 0) && (ray.start.x < Min.x) && (ray.start.x > Max.x))
{
    //parallel
    return false;
}
else
{
    float t1 = (Min.x - ray.start.x) / ray.dir.x;
    float t2 = (Max.x - ray.start.x) / ray.dir.x;
    order(t1, t2);
    tNear = max(tNear, t1);
    tFar = max(tFar, t1);
    if ((tNear > tFar) || (tFar < 0))
        return false;
}

И это обнаруживает одну проблему.tNear и tFar определяют интервал значений t, в пределах которого линия пересекает куб.Каждая проверяемая вами координата (x, y и z) дополнительно ограничивает интервал.Однако код tFar = max(tFar, t1) расширяет интервал.Измените его на tFar = min(tFar, t1).

Более фундаментально, это ограничивает вас кубоидами, выровненными по оси, хотя этот код может быть полезен позже в качестве быстрого теста на удар для более сложных фигур.В любом случае, как только это сработает, вы можете сделать его более общим.

Вы можете определить любой выпуклый многоугольник как набор бесконечных плоскостей с нормалями, обращенными наружу.Точка находится внутри многоугольника, если она «внутри» всех плоскостей.

Плоскость разбивает пространство на две половины.Определите половину, на которую нормаль указывает как «снаружи», а другую половину как «внутрь».Тогда точка находится вне плоскости, если уравнение плоскости в этой точке положительно, внутри плоскости, если значение отрицательно, и в плоскости, если значение равно нулю.

Чтобы проследить это лучом, вы определяете луч/ плоскости пересечений и выберите ближайший.Чтобы определить, находится ли эта точка внутри грани (помните, что плоскость бесконечна), вы проверяете, находится ли эта точка во всех других плоскостях.Если нет, проверьте следующее ближайшее пересечение и т. Д.

После того, как это сработает, довольно легко распространить его на общие пересечения и различия форм (например, куб с полусферическим отступом на одной из граней).).

...