Проецирование экрана для камеры - PullRequest
3 голосов
/ 17 января 2009

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

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

Я надеюсь, что экран можно понять, используя только простую математику, которая не требует матриц вращения. Мое лучшее предположение следующее:

У меня есть направление камеры в виде вектора, это направление равно нормали плоскости проекционного экрана. Таким образом, у меня есть нормаль экрана, и оттуда я могу легко вычислить центр экрана, который является:

camera_location + (normal * distance) 

Где расстояние - это расстояние между экраном и камерой. Однако здесь я теряюсь и не могу найти способ определить угловые координаты плоскости для любого произвольного направления камеры.

Кто-нибудь из вас может помочь мне здесь? И если мой метод не может работать, что делает?

Ответы [ 2 ]

1 голос
/ 17 января 2009

РЕДАКТИРОВАТЬ: Вот некоторый код, который существенно уменьшен по сравнению с первоначально опубликованным, потому что он пропускает создание viewMatrix. Это было необходимо только для некоторого рендеринга отсканированной строки и не использовалось для трассировки лучей.

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

Фактическая функция для наведения лучей предполагает, что область просмотра экрана работает от -0,5 до +0,5 в направлении Y. Эта функция довольно проста и состоит только из сложения правильных пропорций векторов 'view', 'up' и 'right'.

public class Camera {

    protected Point3d       eye;
    protected Point3d       center;

    protected Vector3d      up;
    protected Vector3d      right;
    protected Vector3d      view;

    protected double        fovy;           // half FoV in radians
    protected double        tanf;
    protected double        aspect;

    public Ray castRay(double x, double y) {

        Vector3d dir = new Vector3d(view);
        Vector3d t = new Vector3d();
        t.scale(tanf * x * aspect, right);
        dir.add(t);
        t.scale(tanf * y, up);

        dir.add(t);
        dir.normalize();

        return new Ray(eye, dir);
    }

    /* algorithm taken from gluLookAt */
    public void lookAt(Point3d _eye, Point3d _center, Vector3d _up) {

        eye = new Point3d(_eye);
        center = new Point3d(_center);
        Vector3d u = new Vector3d(_up);

        Vector3d f = new Vector3d(center);
        f.sub(eye);
        f.normalize();

        Vector3d s = new Vector3d();
        u.normalize();
        s.cross(f, u);
        s.normalize();
        u.cross(s, f);

        view = new Vector3d(f);
        right = new Vector3d(s);
        up = new Vector3d(u);
    }

    /* algorithm taken from gluPerspective */
    public void setfov(double _fovy, double _aspect)
    {
        fovy = Math.toRadians(_fovy) / 2.0;
        tanf = Math.tan(fovy);
        aspect = _aspect;
    }
}
0 голосов
/ 18 января 2009

Спасибо за информацию. Лично мне не очень удобно с матричными преобразованиями, и я бы хотел как можно больше их избегать. Однако из вашего поста я понимаю, что преобразования - это единственный способ сделать то, что я хочу сделать? Это было бы очень плохо, так как я думал, что я был довольно близко (я получил нормальную и центральную точку экрана) и хотел бы получить чисто векторное математическое решение.

Я попытаюсь принять ваш код, но, к сожалению, я не знаю точно, что происходит внутри ваших объектов в некоторых точках, в основном в объектах Matrix4d.

PS: Если вы хотите ответить на ответ в StackOverflow как создателе вопроса, вы должны оставить комментарий к этому ответу, или это нормально, чтобы создать новый «ответ»?

...