Основы 3D математики - Векторные и матричные преобразования

Материал из DRKB


Векторы[править | править код]

Вектор - направленный отрезок, имеющий направление и длину. Векторы обозначаются так: a = (x, y, z), например, b = (0, 1, -2). Еще одно представление вектора : AB = (x, y, z).

AB = (x, y, z) = (bx-ax, by-ay, bz-az),

где A и B - 2 точки, A(ax, ay, az) и B(bx, by, bz), A - начало вектора, B - конец вектора.


Длина вектора[править | править код]

Длина вектора, |a|, считается так:

|a| = sqrt(ax2 + ay2 + az2)

Сложение векторов[править | править код]

a + b = c;
a + b = (ax + bx, ay + by, az + bz).

т. е. как результат мы получаем вектор.


Вычитание векторов[править | править код]

c - a = b;
c - a = (cx - ax, cy - ay, cz - az).

как результат - также мы получаем вектор.


Скалярное произведение векторов[править | править код]

Скалярное произведение 2-х векторов - произведение длин 2-х векторов на cos угла между ними. Скалярное произведение векторов - это длина проекции вектора a на вектор b.

a · b = |a| |b| cos(α);

или

a · b = axbx + ayby + azbz;

Следствие: α - угол между двумя векторами:

cos(α) = a · b / (|a| |b|);

Проекция одного вектора на другой[править | править код]

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

an = a / |a|;
c = (an · b) an;

фактически, мы находим длину проекции и, умножая ее на вектор, проекцию которого мы нашли, масштабируем его до нужного размера.


Умножение вектора на вектор (Векторное произведение)[править | править код]

Умножая вектор a на вектор b, мы получим вектор, перпендикулярный плоскости, которую определяют вектора a и b.

a × b = (aybz - byaz, azbx - bzax, axby - bxay);

фактически, таким образом находиться вектор нормали к полигонам.

Матрицы[править | править код]

Здесь я постарался вкратце изложить то, что мы будем делать с матрицами.

Скалярное произведение векторов[править | править код]

[ a ]   [ d ]
[ b ] * [ f ] = a*d + b*f + c*g
[ c ]   [ g ]


Векторное произведение[править | править код]

        [ a ]   [ d ]   [ b*f - c*e ]
A × B = [ b ] × [ e ] = [ c*d - a*f ]
        [ c ]   [ f ]   [ a*e - b*d ]


Сложение матриц[править | править код]

[ 1 2 3 ]   [ 10 11 12 ]   [ 1+10 2+11 3+12 ]
[ 4 5 6 ] + [ 13 14 15 ] = [ 4+13 5+14 6+15 ]
[ 7 8 9 ]   [ 16 17 18 ]   [ 7+16 8+17 9+18 ]


Умножение матриц[править | править код]

[ 1 2 3 ]   [ 10 11 12 ]   [ 1*10+2*13+3*16  1*11+2*14+3*17  1*12+2*15+3*18 ]
[ 4 5 6 ] * [ 13 14 15 ] = [ 4*10+5*13+6*16  4*11+5*14+6*17  4*12+5*15+6*18 ]
[ 7 8 9 ]   [ 16 17 18 ]   [ 7*10+8*13+9*16  7*11+8*14+9*17  7*12+8*15+9*18 ]


Очень важным является тот факт, что (A*B)*С = A*(B*C)


Векторные и матричные преобразования[править | править код]

Параллельный перенос[править | править код]

Переносим точку (x, y, z) на вектор (dx, dy, dz), в результате получим точку с координатами (x+dx, y+dy, z+dz);


Поворот[править | править код]

Поворачиваем точку (x, y) на угол α :

x' = x cos(α) - y*sin(α)
y' = x sin(α) + y*cos(α)

для трехмерного случая - аналогично для каждой плоскости.

ясно, что если нам потребуется (а нам потребуется :) ) проводить для каждой точки в пространстве параллельный перенос + поворот в пространстве, то придется сделать огромное количество преобразований.

можно построить матрицы преобразований, помножив точку - вектор на которую, мы получим результат - координаты искомой точки.


Матрица параллельного переноса[править | править код]

[ 1  0  0  0 ]
[ 0  1  0  0 ]
[ 0  0  1  0 ]
[ x  y  z  1 ]


Матрица растяжения/сжатия[править | править код]

[ z  0  0  0 ]
[ 0  y  0  0 ]
[ 0  0  x  0 ]
[ 0  0  0  1 ]


Матрица поворота вокруг оси x[править | править код]

[ 0  0        0       0 ]
[ 0  cos(α)   sin(α)  0 ]
[ 0  -sin(α)  cos(α)  0 ]
[ 0  0        0       1 ]


Матрица поворота вокруг оси y[править | править код]

[ cos(α)  0  -sin(α)  0 ]
[ 0       1  0        0 ]
[ sin(α)  0  cos(α)   0 ]
[ 0       0  0        1 ]


Матрица поворота вокруг оси z[править | править код]

[ cos(α)  sin(α)  0  0 ]
[-sin(α)  cos(α)  0  0 ]
[ 0       0       1  0 ]
[ 0       0       0  1 ]


Теперь - зачем нужны матрицы в 3D-программировании, если можно все сделать с помощью векторов, и если, например, поворот точки с помощью векторов занимает меньше операций, чем используя матрицы.

Например, мы отодвигаем камеру и поворачиваем ее. Для этого требуется произвести серию операций (переносов, поворотов) с точками (вершинами полигонов) в 3D-сцене. Т.е. для каждой точки произвести сначала параллельный перенос, а затем - повороты по всем осям. При использовании векторов мы просто проведем все эти операции отдельно для каждой точки... Что весьма ресурсоёмко. Или - матричные параллельные переносы, повороты.... Еще более ресурсоёмко, но вспомним:

(A*B)*C = A*(B*C)

Для матриц.. А нам требуется провести такие преобразования: a*A*B*C*D, где - а-точка-вектор, над которым требуется произвести действия, а A,B,C,D - матрицы переноса и поворотов. Мы вполне можем не последовательно умножать точку-вектор a на матрицы переносов, а сначала перемножить эти матрицы, а затем просто умножать получившуюся матрицу на каждую точку, которую требуется сместить - перемножение 4х матриц, а затем умножение 1 вектора на 1 матрицу на каждую точку. По сравнению с подвержением каждой точки векторным преобразованиям - весьма и весьма значительное сокращение производимых операций.


Author: Антон Ярославович Якушев
Source: https://gamedev.ru/code/articles/?id=4184
ID: 03959