ОСНОВЫ 3D ГРАФИКИ Рассмотрим любую камеру как точку - центр проецирования и экран - плоский прямоугольник в 3D пространстве, на плоскость которого идет проецирование. Наша стандартная камера, например, задается точкой (0,0,-dist) и экраном с вершинами (-xSize/2,ySize/2), ..., (xSize/2,-ySize/2). Можно задать эту систему тремя векторами, задающими с точки зрения камеры направления вперед, вправо и вверх; вектор "вперед" соединяет центр проецирования и центр экрана, вектор "вправо" соединяет центр экрана и правую его границу, вектор "вверх", соответственно, центр экрана и верхнюю его границу. Обозначим эти вектора как p, q и r соответственно, а центр проецирования за s. Вот пример для стандартной камеры. Здесь (для стандартной камеры; обозначим ее вектора как Sp, Sq, Sr, Ss) Sp = p = (0,0,dist) Любые три взаимно перпендикулярных вектора и точка - центр координат задают в 3D пространстве систему координат. Так что объект мы можем рассматривать в системе обычных координат (x,y,z), в системе координат стандартной камеры (Sp,Sq,Sr) или в системе (p,q,r), соответствующей какой-то произвольной камере. В любом случае, если (a,b,c) - координаты точки в системе координат камеры (точнее, в системе координат с центром в точке s и базисом (p,q,r)), то координаты проекции точки на экране равны screenX = xSize/2 + xSize/2 * a/c В случае стандартной камеры переход от обычной системы координат к системе координат камеры очевиден: a = x / (xSize/2) Подставив это в формулы для screenX, screenY, получим как раз те самые формулы для проекции на стандартную камеру. Поскольку со стандартной камерой нам достаточно удобно и понятно работать, для произвольной камеры мы должны сделаеть такое преобразование пространства, что как бы совместит произвольную камеру и стандартную камеру. То есть, такое преобразование, что вектора p, q, r перейдут в Sp, Sq, Sr, а точка s в точку Ss. Посчитаем матрицу для *обратного* преобразования; оно должно переводить Sp, Sq, Sr, Ss в p, q, r, s. Преобразование, переводящее Ss в s (и наоборот) - это обычный паралелльный перенос; остается написать преобразование перевода Sp, Sq, Sr в p, q, r. Пусть у нас есть координаты p, q, r в системе координат (x,y,z): p = (px,py,pz) Для Sp, Sq, Sr координаты (в этой же системе) известны и равны следующему: Sp = (0,0,dist) Пусть T - искомая матрица перевода, [ a b c ] T = [ d e f ], a..i - какие-то неизвестные. [ g h i ] Поскольку T переводит Sp, Sq, Sr в p, q, r; то есть p = T*Sp то, подставляя, например, p и Sp, получаем: [ px ] [ a b c ] [ 0 ] [ c*dist ] [ py ] = [ d e f ] [ 0 ] = [ f*dist ], откуда [ pz ] [ g h i ] [ dist ] [ i*dist ] c = px/dist, Аналогично находим все остальные элементы матрицы T: [ qx*2/xSize rx*2/ySize px/dist ] T = [ qy*2/xSize ry*2/ySize py/dist ] [ qz*2/xSize rz*2/ySize pz/dist ] Но нас интересует обратное к этому преобразование. Оно задается обратной матрицей к T, то есть такой матрицей T1, что [ 1 0 0 ] T * T1 = T1 * T = [ 0 1 0 ] [ 0 0 1 ] Обратная матрица, вообще говоря, существует далеко не всегда, да и вычисление ее в общем случае - достаточно неприятная задача. Однако в данном случае из-за специального вида матрицы T (конкретнее, из-за того, что T - ортогональная матрица) она не только всегда существует, но и считается очень просто: [ qx*2/xSize rx*2/ySize px/dist ] [ qx1 rx1 px1 ] T = [ qy*2/xSize ry*2/ySize py/dist ] = [ qy1 ry1 py1 ] [ qz*2/xSize rz*2/ySize pz/dist ] [ qz1 rz1 pz1 ] [ qx1/lq qy1/lq qz1/lq ] T1 = [ rx1/lr ry1/lr rz1/lr ] [ px1/lp py1/lp pz1/lp ] где lp = px1*px1 + py1*py1 + pz1*pz1 Сделав сначала параллельный перенос, совмещающий s и Ss, а потом полученное преобразование, как раз и получим преобразование, переводящее произвольную камеру в стандартную. Теперь надо выяснить, как, собственно посчитать координаты p, q, r через имеющиеся у нас характеристики: положение, направление, угол зрения и угол поворота. 3D Studio (и мы вслед за ней) рассчитывает эти вектора по такому алгоритму: 1. Считаем p = target - location Здесь мы не учитываем поворот камеры вокруг своей оси, его удобнее сделать после перехода к стандартной камере - в этом случае получаем обычный поворот относительно оси z на угол roll. Таким образом, окончательная матрица перевода должна представлять собой произведение матрицы параллельного переноса, матрицы T1 и матрицы поворота вокруг оси z на угол roll: FinalCameraMatrix = RollMatrix * T1 * MoveMatrix Расчет матриц RollMatrix и MoveMatrix очевиден. |
|