Векторы трассировки лучей - PullRequest
1 голос
/ 16 января 2012

Поэтому я решил написать трассировщик лучей на днях, но я застрял, потому что забыл всю свою векторную математику. У меня есть точка за экраном (глаз / камера, 400 300, -1000), а затем точка на экране (плоскость, от 0,0,0 до 800 600,0), которую я получаю просто используя значения x и y текущего пикселя, который я ищу (используя SFML для рендеринга, так что это что-то вроде 267,409,0)

Проблема в том, что я понятия не имею, как правильно навести луч. Я использую это для тестирования пересечения сферы (C ++):

bool SphereCheck(Ray& ray, Sphere& sphere, float& t)
{ //operator * between 2 vec3s is a dot product
    Vec3 dist = ray.start - sphere.pos; //both vec3s
    float B =  -1 * (ray.dir * dist);
    float D = B*B - dist * dist + sphere.radius * sphere.radius; //radius is float
    if(D < 0.0f)
        return false;
    float t0 = B - sqrtf(D);
    float t1 = B + sqrtf(D);
    bool ret = false;
    if((t0 > 0.1f) && (t0 < t))
    {
        t = t0;
        ret = true;
    }
    if((t1 > 0.1f) && (t1 < t))
    {
        t = t1;
        ret = true;
    }
    return ret;
}

Итак, я понял, что началом луча будет положение глаза, но в каком направлении?

Или, если это не удастся, есть ли лучший способ сделать это? Я слышал о некоторых людях, использующих начало луча как (x, y, -1000) и направление как (0,0,1), но я не знаю, как это будет работать.

Кстати, как бы вы делали трансформации? Я предполагаю, что для изменения угла камеры вы просто отрегулируете x и y камеры (или экрана, если вам нужно радикальное изменение)

Ответы [ 3 ]

1 голос
/ 27 апреля 2012

Параметр "луч" в функции

bool SphereCheck(Ray& ray, Sphere& sphere, float& t)
{
    ...
}

должен уже содержать информацию о направлении, и в этом направлении вам необходимо проверить, пересекает ли луч сферу или нет.(Входящий параметр "ray" - это вектор между точкой камеры и пикселем, на который посылается луч.)

Поэтому локальная переменная "dist" выглядит устаревшей.

0 голосов
/ 12 марта 2012

Итак, я понимаю, что началом луча будет положение глаза, но в каком направлении?

У вас есть камера, определяемая векторами front, up и right (перпендикулярными друг другу и нормализованными) и «позицией» (положением глаза).

У вас также есть width и height области просмотра (в пикселях), вертикального поля зрения (vfov) и горизонтального поля зрения (hfov) в градусах или радианах.

Существуют также 2D x и y координаты пикселя. Ось X (2D) указывает вправо, ось Y (2D) указывает вниз.

Для плоского экрана луч можно рассчитать так:

startVector = eyePos;
endVector = startVector 
    + front
    + right * tan(hfov/2) * (((x + 0.5)/width)*2.0 - 1.0)
    + up * tan(vfov/2) * (1.0 - ((y + 0.5f)/height)*2.0);

rayStart = startVector;
rayDir = normalize(endVector - startVector);

Предполагается, что плоскость экрана плоская . Для экстремальных углов поля зрения (fov> = 180 градусов) вам может потребоваться сферическая плоскость экрана и использование различных формул.

как бы вы делали трансформации

Матрицы.

0 голосов
/ 12 марта 2012

Я вижу одну вещь: когда вы создаете свои лучи, вы не используете центр каждого пикселя на экране в качестве точки для построения вектора направления.Вы не хотите использовать только координаты (x, y) на сетке для построения этих векторов.

Я посмотрел на ваш пример кода, и вычисление действительно неверно.Это то, что вы хотите.

http://www.csee.umbc.edu/~olano/435f02/ray-sphere.html (я проходил этот курс в колледже, этот парень знает свое дело)

По сути, это означает, что у вас есть этот луч, имеющий происхождениеи направление.У вас есть сфера с точкой и радиусом.Вы используете уравнение луча и вставляете его в уравнение сферы и решаете для t.Это t - расстояние между началом луча и точкой пересечения на сферах поверхность .Я не думаю, что ваш код делает это.

...