netlib.narod.ru< Назад | Оглавление | Далее >

Основные преобразования

Создавая использующие Direct3D программы, для представления преобразований мы будем применять матрицы 4 × 4. Идея заключается в следующем: мы инициализируем элементы матрицы X размером 4 × 4 таким образом, чтобы они описывали требуемое преобразование. Затем мы помещаем координаты точки или компоненты вектора в столбцы вектора-строки v размером 1 × 4. Результатом произведения vX будет новый преобразованный вектор v'. Например, если матрица X представляет перемещение на 10 единиц вдоль оси X, и v = [2, 6, –3, 1], произведение vX = v' = [12, 6, –3, 1].

Следует пояснить несколько моментов. Мы используем матрицы размера 4 × 4 по той причине, что они позволяют представить все необходимые нам преобразования. На первый взгляд матрицы размером 3 × 3 кажутся более подходящими для трехмерной графики. Однако, с их помощью нельзя представить ряд преобразований, которые могут нам потребоваться, таких как перемещение, перспективная проекция и отражение. Помните, что мы работаем с произведением вектора на матрицу и при выполнении преобразований ограничены правилами умножения матриц. Дополнение матрицы до размера 4 × 4 позволяет нам с помощью матрицы описать большинство преобразований и при этом произведение вектора на матрицу будет определено.

Мы упомянули, что координаты точки или компоненты вектора будем хранить в столбцах вектора-строки размером 1 × 4. Но наши точки и векторы — трехмерные! Зачем же использовать вектор-строку 1 × 4? Мы должны дополнить наши трехмерные точки/векторы до четырехмерного вектора-строки 1 × 4 чтобы был определен результат умножения вектора на матрицу; произведение вектора-строки 1 × 3 и матрицы 4 × 4 не определено.

Так какое же значение использовать для четвертой компоненты, которую, кстати, мы будем обозначать w? Когда вектор-строка 1 × 4 используется для представления точки, значение w будет равно 1. Это позволяет корректно выполнять перемещение точки. Поскольку вектор не зависит от местоположения, операция перемещения векторов не определена и результат попытки переместить вектор не имеет смысла. Чтобы предотвратить перемещение векторов мы, помещая компоненты вектора в вектор-строку 1 × 4, присваиваем компоненте w значение 0. Например, точка p = (p1p2p3), помещенная в вектор-строку 1 × 4 будет выглядеть как [p1p2p3, 1], а вектор v = (v1v2v3), помещенный в вектор-строку 1 × 4 будет выглядеть как [v1v2v3, 0].

ПРИМЕЧАНИЕ
Мы устанавливаем w = 1 чтобы корректно осуществлялось перемещение точек. Мы устанавливаем w = 0, чтобы предотвратить перемещение векторов. Это станет более ясно, когда мы рассмотрим реальную матрицу переноса.

 

ПРИМЕЧАНИЕ
Дополненный четырехмерный вектор называется однородным вектором (homogenous vector) и, поскольку однородный вектор может описывать и точки и векторы, мы будем использовать термин «вектор», подразумевая, что он может относиться как к точке, так и к вектору.

Иногда в результате преобразований компонента w вектора будет меняться таким образом, что w ≠ 0 и w ≠ 1. Взгляните на следующий пример:


формула 32

для p3 ≠ 0 и p3 ≠ 1.

Обратите внимание, что w = p3. Когда w ≠ 0 и w ≠ 1, мы говорим, что у нас есть вектор в однородном пространстве (homogeneous space), в противоположность векторам в трехмерном пространстве. Мы можем отобразить вектор в однородном пространстве обратно на трехмерное пространство, разделив каждую компоненту вектора на значение компоненты w. Например, для отображения вектора (xyzw) в однородном пространстве в трехмерный вектор x, выполним следующие операции:


формула 33

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

ПРИМЕЧАНИЕ
Когда мы записываем точку (xy, z) в виде (xyz, 1) мы фактически описываем наше трехмерное пространство как плоскость в четырехмерном пространстве, а именно четырехмерную плоскость w = 1. (Обратите внимание, что плоскость в четырехмерном пространстве является трехмерным пространством, точно так же как плоскость в трехмерном пространстве является двухмерным пространством.) Таким образом, присваивая w какое-нибудь другое значение, мы перемещаемся с полскости w = 1. Чтобы вернуться на эту плоскость, которая соответствует нашему трехмерному пространству, мы выполняем обратную проекцию путем деления каждой компоненты на w.

Матрица перемещения


Рис. 8. Перемещение

Рис. 8. Перемещение на 12 единиц по оси X и на –10 единиц по оси Y


Мы можем переместить вектор (xyz, 1) на px единиц по оси Х, py единиц по оси Y и pz единиц по оси Z умножив его на следующую матрицу:

формула 34

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

D3DXMATRIX *D3DXMatrixTranslation(
     D3DXMATRIX* pOut, // Результат
     FLOAT x,          // Количество единиц для перемещения по оси X
     FLOAT y,          // Количество единиц для перемещения по оси Y
     FLOAT z           // Количество единиц для перемещения по оси Z
);


УПРАЖНЕНИЕ

Пусть T(p) — это матрица, представляющая преобразование перемещения и пусть v = [v1v2v3, 0] — это произвольный вектор. Проверьте, что vT(p) = v (то есть, что если w = 0, преобразование перемещения не влияет на вектор).



Инверсия матрицы перемещения получается путем простой смены знака компонент вектора перемещения p.


формула 35

Матрицы вращения


Рис. 9. Вращение

Рис. 9. Поворот на 30 градусов против часовой стрелки вокруг оси Z


Используя приведенные ниже матрицы мы можем повернуть вектор на φ радиан вокруг осей X, Y или Z. Обратите внимание, что если смотреть вдоль оси вращения по направлению к началу координат, то углы измеряются по часовой стрелке.


формула 36

Для создания матрицы вращения вокруг оси X в библиотеке D3DX используется следующая функция:

D3DXMATRIX *D3DXMatrixRotationX(
     D3DXMATRIX* pOut, // Результат
     FLOAT Angle       // Угол поворота в радианах
);

формула 37

Для создания матрицы вращения вокруг оси Y в библиотеке D3DX используется следующая функция:

D3DXMATRIX *D3DXMatrixRotationY(
     D3DXMATRIX* pOut, // Результат
     FLOAT Angle       // Угол поворота в радианах
);

формула 38

Для создания матрицы вращения вокруг оси Z в библиотеке D3DX используется следующая функция:

D3DXMATRIX *D3DXMatrixRotationZ(
     D3DXMATRIX* pOut, // Результат
     FLOAT Angle       // Угол поворота в радианах
);

Инверсией матрицы вращения R является результат транспонирования этой матрицы: RT = R-1. Такие матрицы называются ортогональными.

Матрица масштабирования


Рис. 10. Масштабирование

Рис. 10. Масштабирование с коэффициентом 1/2 по оси X и коэффициентом 2 по оси Y


Мы можем масштабировать вектор с коэффициентом qx по оси Х, коэффициентом qy по оси Y и коэффициентом qz по оси Z, умножив его на следующую матрицу:


формула 39

Для создания матрицы масштабирования в библиотеке D3DX используется следующая функция:

D3DXMATRIX *D3DXMatrixScaling(
     D3DXMATRIX* pOut, // Результат
     FLOAT sx,         // Коэффициент масштабирования по оси X
     FLOAT sy,         // Коэффициент масштабирования по оси Y
     FLOAT sz          // Коэффициент масштабирования по оси Z
);

Чтобы инвертировать матрицу масштабирования надо взять обратную дробь для каждого коэффициента масштабирования:


формула 40

Комбинирование преобразований

Часто мы будем применять к векторам целую последовательность преобразований. Например, мы можем масштабировать вектор, затем повернуть его и потом переместить в требуемую позицию.

В качестве примера мы рассмотрим вектор p = [5, 0, 0, 1], который масштабируем по всем осям с коэффициентом 1/5, затем повернем его на π/4 радиан вокруг оси Y и, наконец, переместим на 1 единицу по оси X, 2 единицы по оси Y и –3 единицы по оси Z.

Обратите внимание, что мы должны выполнить масштабирование, поворот вокруг оси Y и перемещение. Мы инициализируем наши матрицы преобразований S, Ry, T для масштабирования, поворота и перемещения соответственно, следующим образом:


формула 41

Применив последовательность преобразований в заданном порядке — масштабирование, вращение, перемещение — получим:


формула 42

Ключевым преимуществом использования матриц является возможность использования умножения матриц для комбинирования нескольких преобразований в одной матрице. Вернемся к примеру, рассматриваемому в начале данного раздела. Давайте с помощью умножения матриц скомбинируем все три матрицы преобразований в одну, которая будет представлять все три преобразования сразу. Обратите внимание, что порядок, в котором мы умножаем матрицы должен соответствовать порядку применения отдельных преобразований.


формула 43

В результате получаем pQ = [1.707, 2, –3.707, 1].

Возможность комбинировать преобразования значительно увеличивает производительность. Представьте, что вам необходимо применить одну и ту же последовательность преобразований масштабирования, вращения и перемещения к большому набору векторов (это обычная задача в трехмерной компьютерной графике). Вместо того, чтобы применять к каждому вектору последовательность преобразований, как мы делали это в формуле (5), можно скомбинировать все три преобразования в одной матрице, как мы делали это в формуле (6). После этого остается только умножить каждый вектор на единственную матрицу, содержащую комбинацию всех трех преобразований. Благодаря этому количество выполняемых операций умножения вектора на матрицу значительно сокращается.

Некоторые функции для преобразования векторов

Библиотека D3DX предоставляет две функции для преобразования точек и векторов соответственно. Функция D3DXVec3TransformCoord используется для преобразования точек и предполагает, что четвертая компонента вектора равна 1. Функция D3DXVec3TransformNormal используется для преобразования векторов и предполагает, что четвертая компонента вектора равна 0.

D3DXVECTOR3 *D3DXVec3TransformCoord(
     D3DXVECTOR3* pOut,     // Результат
     CONST D3DXVECTOR3* pV, // Преобразуемая точка
     CONST D3DXMATRIX* pM   // Матрица преобразования
);

D3DXMATRIX T(...);                   // инициализация матрицы преобразований
D3DXVECTOR3 p(...);                  // инициализация точки
D3DXVec3TransformCoord(&p, &p, &T); // преобразование точки

D3DXVECTOR3 *D3DXVec3TransformNormal(
     D3DXVECTOR3 *pOut,     // Результат
     CONST D3DXVECTOR3 *pV, // Преобразуемый вектор
     CONST D3DXMATRIX *pM   // Матрица преобразования
);

D3DXMATRIX T(...);                    // инициализация матрицы преобразований
D3DXVECTOR3 v(...);                   // инициализация вектора
D3DXVec3TransformNormal(&v, &v, &T); // преобразование вектора
ПРИМЕЧАНИЕ
Библиотека D3DX также предоставляет функции D3DXVec3TransformCoordArray и D3DXVec3TransformNormalArray для преобразования массива точек и массива векторов соответственно.

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz