Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Статьи / ЧАВО по матрицам и кватернионам

ЧАВО по матрицам и кватернионам

Автор:

Часто задаваемые вопросы по матрицам и кватернионам.

Введение
  Замечание по поводу OpenGL и этого документа
  Что такое матрица?
  Что такое порядок матрицы?
  Как я могу сделать матрицу в C/C++?
  В чем плюсы от использования матриц?
  Как матрицы влияют на систему координат?
АРИФМЕТИКА
  Что такое единичная матрица?
  Что такое главная диагональ матрицы?
  Что такое транспонирование матрицы?
  Как мне сложить две матрицы?
  Как мне вычесть две матрицы?
  Как мне умножить две матрицы?
  Как мне взять корень или возвести матрицу в квадрат?
  Как мне умножить один и более векторов на матрицу?
Определитель и обратная матрица
  Что такое определитель матрицы?
  Как мне посчитать определитель матрицы?
  Что такое изотропная и анизотропная матрицы?
  Что такое обратная матрица?
  Как мне посчитать обратную матрицу?
  Как мне посчитать обратную матрицу от единичной матрицы?
  Как мне посчитать обратную от матрицы вращения?
  Как мне посчитать обратную матрицу при помощи правила Крамера?
  Как мне посчитать обратную от 2х2 матрицы?
  Как мне посчитать обратную от 3х3 матрицы?
  Как мне посчитать обратную 4х4 матрицы?
  Как мне посчитать обратную матрицу с помощью линейных уравнений?
ТРАНСФОРМАЦИИ
  Что такое матрица поворота?
  Как матрицы вращения влияют на систему координат?
  Как сгенерировать матрицу поворота по оси X?
  Как сгенерировать матрицу поворота по оси Y?
  Как сгенерировать матрицу поворота по оси Z?
  Что такое углы Эйлера?
  Что такое рыск, качение и тангаж?
  Как мне комбинировать матрицы поворота?
  Что такое фиксация оси?
  Как правильно комбинировать матрицы вращения?
  Как сгенерировать матрицу вращения из углов Эйлера?
  Как мне перевести матрицу вращения в углы Эйлера?
  Как мне сгенерировать матрицу вращения для выбранных осей и углов?
  Как мне сгенерировать матрицу вращения, проецирующую один вектор на другой?
  Как мне использовать матрицы для перехода из одной системы координат в другую?
  Что такое матрица переноса?
  Что такое матрица скалирования?
  Что такое матрица сдвига?
  Как мне линейно интерполировать две матрицы?
  Как мне сделать кубическую интерполяцию между четырьмя матрицами?
  Как отрисовать матрицу?
КВАТЕРНИОНЫ
  Что такое кватернионы?
  Какое место занимают кватернионы в 3D анимации?
  Как вычислить сопряжение кватернионов?
  Как вычислить обратный кватернион?
  Как вычислить длину кватерниона?
  Как нормализовать кватернион?
  Как умножить два кватерниона?
  Как мне перевести кватернион в матрицу вращения?
  Как мне перевести матрицу в кватернион?
  Как мне преобразовать угол вращения ось в кватернион?
  Как мне преобразовать кватернион в ось и угол?
  Как мне преобразовать сферические углы вращения в кватернион?
  Как перевести кватернион в сферические углы вращения?
  Как преобразовать углы Эйлера в кватернион?
  Как мне с помощью кватернионов линейно интерполировать между матрицами?
  Как мне с помощью кватернионов сделать кубическую интерполяцию между матрицами?
  Пожертвования

Введение

Замечание по поводу OpenGL и этого документа

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

В этом документе, к примеру, матрица переноса 4x4 записывается в таком виде:

[cht]
  M=\(\matrix{
1 & 0 & 0 & X\cr
0 & 1 & 0 & Y\cr
0 & 0 & 1 & Z\cr
0 & 0 & 0 & 1\cr
}\)
[/cht]

В коде это можно записать вот так:

    M[0][1] = M[0][2] = M[0][3] = 
    M[1][0] = M[1][2] = M[1][3] =
    M[2][0] = M[2][1] = M[2][3] = 0 ;
    M[0][0] = M[1][1] = M[2][2] = m[3][3] = 1 ;
    M[3][0] = X ;
    M[3][1] = Y ;
    M[3][2] = Z ;

иначе говоря:

[cht]
M=\(\matrix{
M_{00} & M_{10} & M_{20} & M_{30}\cr
M_{01} & M_{11} & M_{21} & M_{31}\cr
M_{02} & M_{12} & M_{22} & M_{32}\cr
M_{03} & M_{13} & M_{23} & M_{33}\cr
}\)
[/cht]

OpenGL использует одномерный массив для хранения матриц, но, к счастью, они находятся в памяти в таком виде, что получив адрес pfMatrix и скастовав его к float* можно увидеть матрицу в том виде, в каком ее передают в glLoadMatrixf.

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

Этот документOpenGL

[cht]
  M=\(\matrix{
0 & 1 & 2 & 3\cr
4 & 5 & 6 & 7\cr
8 & 9 & 10 & 11\cr
12 & 13 & 14 & 15\cr
}\)[/cht]

[cht]
  M=\(\matrix{
0 & 4 & 8 & 12\cr
1 & 5 & 9 & 13\cr
2 & 6 & 10 & 14\cr
3 & 7 & 11 & 15\cr
}\)[/cht]

Что такое матрица?

Матрица это двумерный массив чисел, где каждый ряд или колонка состоит из одного и более чисел.

Матрицы можно складывать, вычитать, умножать и делить.

Размер матрицы определяется количеством рядов и колонок.

Матрица с M рядов и N колонок описывается как матрица MxN.

Описать отдельный элемент матрицы можно в виде двух индексов.

Используя математическую нотацию индексы обозначают переменными i и j. Сначала пишут строку, затем колонку.

К примеру, если есть матрица M с порядком 4x4, то элементы этой матрицы описываются парами индексов строк и колонок:

[cht]
  M=\(\matrix{
00 & 10 & 20 & 30\cr
01 & 11 & 21 & 31\cr
02 & 12 & 22 & 32\cr
03 & 13 & 23 & 33\cr
}\)
[/cht]

У верхнего правого элемента матрицы i=0 и j=3, что можно описать так:
[cht]
M_{ij}=M_{03}
[/cht]

В компьютерной анимации обычно используют матрицы 2x2, 3x3 и 4x4.

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

Матрицы 3x3 достаточны для хранения информации о повороте (вращении) и масшатбировании. Такие матрицы могут быть использованы для скелетной анимации.

Матрицы 4x3 достаточно, чтобы хранить поворот, масштабирование и перемещение.

Матрицы 4x4 используются для всего набора трансформаций в трёхмерном пространстве, включая перспективное проецирование.

Что такое порядок матрицы?

Порядок матрицы — это её размерность. Матрица из M строк и N столбцов имеет порядок MxN.

Как я могу сделать матрицу в C/C++?

Проще всего использовать ключевое слово typedef.

Матрицы 3x3 и 4x4 могут быть описаны так:

    typedef float MATRIX3[9];
    typedef float MATRIX4[16];

Так как матрицы имеют размерность 3x3 и 4x4, им необходимо 9 и 16 элементов соответственно.

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

    typedef float MATRIX3[3][3];
    typedef float MATRIX4[4][4];

Однако, использование двух систем отсчета для каждого элемента матрицы часто ведет к путанице. В математике, сначала записывают строку(i), а затем колонку(j): [cht]M_{ij}[/cht]

В C/C++, это будет так:

    matrix[j][i]

Использование двумерных массивов также подействует на производительность процессора, так как компилятор C всегда использует операцию умножения для определения индекса элемента.

Так что, эффективнее использовать одномерные массивы. Однако останется решить ещё один вопрос. Как двумерный массив проецируется в линейный?

Есть только два решения: строка сначала, колонка потом, либо колонка сначала, а строка потом.

Разница в производительности минимальна. Если все циклы раскрыты, то нет практически отличий в производительности для таких операций как умножение матрицы на матрицу.

При использовании C/C++ порядок элементов в матрице следующий:

mat[0]  = [cht]M_{00}[/cht], mat[3]  = [cht]M_{03}[/cht], mat[12] = [cht]M_{30}[/cht], mat[15] = [cht]M_{33}[/cht].


[cht]
  M=\(\matrix{
0 & 1 & 2 & 3\cr
4 & 5 & 6 & 7\cr
8 & 9 & 10 & 11\cr
12 & 13 & 14 & 15\cr
}\)[/cht]

[cht]
  M=\(\matrix{
0 & 1 & 2\cr
3 & 4 & 5\cr
6 & 7 & 8\cr
}\)[/cht]
                       

В чем плюсы от использования матриц?

Один из первых вопросов, задаваемых по использованию матриц в компьютерной анимации: «Зачем вообще они нужны?». Интуиция подсказывает, что придется хорошо потратиться на циклы, и тем самым матричные перемножения замедлят программу.

Решением этой проблемы, являются регистры процессора и процессорный кэш. Первый может быть счетчиком в цикле, а алгоритм предсказания с заполнением кэша позволит оптимизировать доступ к памяти.
 
Также можно указать и на плюсы. Используя этот математический подход в описании 3D алгоритмов, можно предсказать и спланировать систему 3D анимации. Этот подход позволяет реализовать анимацию персонажа, сплайны и инверсную кинематику.

Но чаще всего звучит такой вопрос: «А не будет ли быстрее, просто умножить каждую пару координат на коэффициенты поворота для оси, вместо того чтобы производить полное векторно-матричное умножение?»
 
  иначе говоря:
      Вращение в X преобразует Y и Z
      Вращение в Y преобразует X и Z
      Вращение в Z преобразует X и Y

За это приводятся следующие аргументы:

Дана вершина V = (x, y, z), углы поворота (A,B и C) и перенос (D,E,F).

И следующий алгоритм:

    sx = sin(A)             // Настройка - делается единожды
    cx = cos(A)
    sy = sin(B)
    cy = cos(B)
    sz = sin(C)
    cz = cos(C)

    x1 =  x * cz +  y * sz  // Поворот каждого вертекса
    y1 =  y * cz -  x * sz
    z1 =  z

    x2 = x1 * cy + z1 * sy
    y2 = z1
    z2 = z1 * cy - x1 * sy

    x3 = x2
    y3 = y2 * cx + z1 * sx
    z3 = z2 * cx - x1 * sx

    xr = x3 + D             // Перенос каждого вертекса
    yr = y3 + E
    zr = z3 + F

Вместе они займут следующее количество процессорного времени:

НастройкаНа одну вершину
6 тригонометрических функций
6 присваиваний.
12 присваиваний
12 умножений
9 сложений
 

Те же самые операции, но при использовании матричного умножения.
 
С матрицей 4х4 они займут:

НастройкаИзменениеНа одну вершинуИзменение
6 тригонометрических функций00
18 присваиваний-123 присваиваний-9
12 умножений+129  умножений-3
6  вычитаний+66  сложений-3

Сравнивая две таблицы, видно, что матрица поворота стоит как минимум 12 умножений и дополнительно 18 присваиваний.
 
Однако мы экономим на обработке вершин. Использование матричного умножения, от настройки всего 4 вершин, перевесит дополнительные затраты на настройке.

Как матрицы влияют на систему координат?

Матрицы поворота, переноса, сдвига очень просто действуют на систему координат.

Первые три колонки матрицы описывают направление осей X,Y,Z соответственно.

Если описана матрица 4х4 как:
[cht]
  M=\(\matrix{
A & B & C & D\cr
E & F & G & H\cr
I & J & K & L\cr
M & N & O & P\cr
}\)[/cht]

Вектор направления для каждой оси будет следующий:

ось [cht]X = [ A E I][/cht]
ось [cht]Y = [ B F J ][/cht]
ось [cht]Z = [ C G K][/cht]

Страницы: 1 2 3 4 5 6 Следующая »

9 марта 2011

#C++, #OpenGL, #кватернионы, #математика, #матрицы


Обновление: 13 сентября 2012

Как выбрать обои под покраску atik.su.
2001—2018 © GameDev.ru — Разработка игр