Вращающаяся трехмерная кубическая перспектива - PullRequest
4 голосов
/ 12 июля 2009

С 13 лет я играю с AMOS 3D и хочу научиться кодировать 3D-графику. Теперь, 10 лет спустя, я, наконец, думаю, что накопил достаточно математики, чтобы попробовать.

Я следовал различным учебникам и определил screenX (и screenY, соответственно) как

screenX = (pointX * cameraX) / distance

(плюс смещения и масштабирование.)

Моя проблема в том, к чему на самом деле относится переменная расстояния. Я видел расстояние, определяемое как разница в z между камерой и точкой. Однако это не может быть полностью правильным, поскольку x и y оказывают тот же эффект, что и z, на фактическое расстояние от камеры до точки. Я реализовал расстояние как фактическое расстояние, но результат дает несколько искаженную перспективу, как если бы она имела «слишком большую» перспективу.

Моя реализация "фактического расстояния" была следующей:

distance = new Vector(pointX, pointY, cameraZ - pointZ).magnitude()

Поэкспериментировав с кодом, я добавил в мое уравнение дополнительную переменную перспективный коэффициент следующим образом:

distance = new Vector(pointX * perspectiveCoefficient, 
  pointY * perspectiveCoefficient, cameraZ - pointZ).magnitude()

По какой-то причине, что за мной, я стремлюсь получить лучший результат, устанавливая перспективный коэффициент равным 1 / sqrt (2).

Мой трехмерный тестовый куб находится на http://vega.soi.city.ac.uk/~abdv866/3dcubetest/3dtest.svg. (протестировано в Safari и FF.) Он запрашивает у вас перспективный коэффициент, где 0 дает перспективу без учета расстояния х / у, а 1 - перспективу где x, y и z расстояние считается одинаково. По умолчанию 1 / sqrt (2). Куб можно вращать вокруг x и y с помощью клавиш со стрелками. (Для всех, кто заинтересован, соответствующий код находится в update () в файле View.js.)

Благодарен за любые идеи по этому поводу.

1 Ответ

5 голосов
/ 12 июля 2009

Обычно проекция выполняется на плоскости Z = 0 из положения глаза за этой плоскостью. Проецируемая точка - это пересечение линии (Pt, Eye) с плоскостью Z = 0. В конце вы получите что-то вроде:

screenX = scaling * pointX / (1 + pointZ/eyeDist)
screenY = scaling * pointY / (1 + pointZ/eyeDist)

Я предполагаю, что камера находится в точке (0,0,0), а глаз - в точке (0,0, -eyeDist). Если eyeDist становится бесконечным, вы получаете параллельную проекцию.

...