Ответы:
Да, вы можете добавить вектор в случае перевода. Причина использования матрицы сводится к тому, чтобы иметь единый способ обработки различных комбинированных преобразований.
Например, вращение обычно выполняется с использованием матрицы (см. Комментарий @MickLH, чтобы узнать о других способах обращения с вращениями), поэтому, чтобы иметь дело с несколькими преобразованиями (вращение / перемещение / масштабирование / проекция ... и т. Д.) Единообразным способом, вам нужно закодировать их в матрице.
Ну, более технически говоря; преобразование отображает точку / вектор в другую точку / вектор.
p` = T(p);
где p` - преобразованная точка, а T (p) - функция преобразования.
Учитывая, что мы не используем матрицу, нам нужно сделать это для объединения нескольких преобразований:
p1 = T (p);
р финал = М (р1);
Матрица может не только объединять несколько типов преобразований в одну матрицу (например, аффинно, линейно, проективно).
Использование матрицы дает нам возможность объединить цепочки преобразований, а затем пакетно умножить их. Это экономит нам массу циклов, обычно выполняемых графическим процессором (спасибо @ChristianRau за указание на это).
T финал = T * R * P; // перевод поворота проект
р финал = Т финал * р;
Также хорошо отметить, что графические процессоры и даже некоторые процессоры оптимизированы для векторных операций; Процессоры, использующие SIMD и графические процессоры, по своей конструкции являются управляемыми данными параллельными процессорами, поэтому использование матриц идеально подходит для аппаратного ускорения (фактически, графические процессоры были разработаны для работы с матрично-векторными операциями).
Если все, что вы когда-либо собираетесь сделать, это двигаться вдоль одной оси и никогда не применять какие-либо другие преобразования, то то, что вы предлагаете, это хорошо.
Реальная сила использования матрицы заключается в том, что вы можете легко объединить ряд сложных операций вместе и применить один и тот же ряд операций к нескольким объектам.
В большинстве случаев это не так просто, и если вы сначала поверните объект и захотите трансформироваться вдоль его локальных осей вместо мировых осей, вы обнаружите, что вы не можете просто добавить 10 к одному из чисел и заставить его работать правильно ,
Чтобы кратко ответить на вопрос «почему», это потому, что матрица 4x4 может описывать операции поворота, перемещения и масштабирования одновременно. Возможность последовательно описывать любое из них упрощает многие вещи.
Различные виды преобразований могут быть проще представлены с помощью различных математических операций. Как вы заметили, перевод можно сделать, просто добавив. Равномерное масштабирование путем умножения на скаляр. Но должным образом созданная матрица 4x4 может делать все что угодно. Таким образом, использование 4x4 последовательно делает код и интерфейсы намного проще. Вы платите немного за понимание этих 4х4, но потом многое становится проще и быстрее из-за этого.
причина использования матрицы 4x4 заключается в том, что операция представляет собой линейное преобразование . это пример однородных координат . То же самое делается в случае 2d (с использованием матрицы 3x3). Причиной использования однородных координат является то, что все 3 геометрических преобразования могут быть выполнены с использованием одной операции; в противном случае нужно будет умножить матрицу 3х3 и сложить матрицу 3х3 (для перевода). эта ссылка от cegprakash полезна.
Переводы не могут быть представлены 3D матрицами
Простой аргумент в том, что перевод может принимать исходный вектор:
0
0
0
от источника, скажи x = 1
:
1
0
0
Но для этого потребуется матрица, такая что:
| a b c | |0| |1|
| d e f | * |0| = |0|
| g h i | |0| |0|
Но это невозможно.
Другим аргументом является теорема разложения по сингулярному значению , которая говорит, что каждая матрица может быть составлена с двумя вращениями и одной операцией масштабирования. Там нет переводов.
Почему матрицы можно использовать?
Многие моделируемые объекты (например, автомобильное шасси) или часть моделируемых объектов (например, автомобильная шина, ведущее колесо) являются твердыми телами: расстояния между вершинами никогда не меняются.
Единственные преобразования, которые мы хотим сделать для них - это ротации и переводы.
Матричное умножение может кодировать как вращения, так и сдвиги.
Матрицы вращения имеют явные формулы, например: 2D матрица вращения для угла a
имеет вид:
cos(a) -sin(a)
sin(a) cos(a)
Существуют аналогичные формулы для 3D , но обратите внимание, что для 3D-поворотов требуется 3 параметра вместо 1 .
Переводы менее тривиальны и будут обсуждаться позже. Именно по этой причине нам нужны 4D-матрицы.
Почему круто использовать матрицы?
Потому что состав нескольких матриц может быть предварительно рассчитан путем умножения матриц .
Например, если мы собираемся перевести тысячу векторов v
нашего автомобильного шасси с матрицей, T
а затем вращаться с матрицей R
, вместо того, чтобы делать:
v2 = T * v
а потом:
v3 = R * v2
для каждого вектора мы можем предварительно рассчитать:
RT = R * T
и затем сделайте только одно умножение для каждой вершины:
v3 = RT * v
Еще лучше: если мы затем хотим расположить вершины шины и ведущего колеса относительно автомобиля, мы просто умножим предыдущую матрицу RT
на матрицу относительно самого автомобиля.
Это, естественно, ведет к поддержанию стека матриц:
Как добавление одного измерения решает проблему
Давайте рассмотрим случай от 1D до 2D, который проще визуализировать.
Матрица в 1D - это всего лишь одно число, и, как мы видели в 3D, она не может выполнять перевод, только масштабирование.
Но если мы добавим дополнительное измерение как:
| 1 dx | * |x| = | x + dx |
| 0 1 | |1| | 1 |
и тогда мы забываем о новом дополнительном измерении, мы получаем:
x + dx
как мы и хотели.
Это двумерное преобразование настолько важно, что оно имеет название: сдвиговое преобразование .
Круто представить это преобразование:
Обратите внимание, что каждая горизонтальная линия (фиксированная y
) просто переводится.
Мы просто взяли эту линию в y = 1
качестве нашей новой 1D линии и перевели ее с помощью 2D матрицы.
Вещи аналогичны в 3D, с 4D матрицами сдвига в виде:
| 1 0 0 dx | | x | | x + dx |
| 0 1 0 dy | * | y | = | y + dy |
| 0 0 1 dz | | z | | z + dz |
| 0 0 0 1 | | 1 | | 1 |
И наши старые 3D вращения / масштабирования теперь имеют форму:
| a b c 0 |
| d e f 0 |
| g h i 0 |
| 0 0 0 1 |
Это видеоурок Джейми Кинга также стоит посмотреть.
Аффинное пространство
Аффинное пространство - это пространство, генерируемое всеми нашими трехмерными линейными преобразованиями (матричными умножениями) вместе с 4D-сдвигом (трехмерные переводы).
Если мы умножим матрицу сдвига и линейное трехмерное преобразование, мы всегда получим что-то в форме:
| a b c dx |
| d e f dy |
| g h i dz |
| 0 0 0 1 |
Это наиболее общее возможное аффинное преобразование, которое выполняет 3D вращение / масштабирование и перевод.
Одним из важных свойств является то, что если мы умножим 2 аффинных матрицы:
| a b c dx | | a2 b2 c2 dx2 |
| d e f dy | * | d2 e2 f2 dy2 |
| g h i dz | | g2 h2 i2 dz2 |
| 0 0 0 1 | | 0 0 0 1 |
мы всегда получаем другую аффинную матрицу формы:
| a3 b3 c3 (dx + dx2) |
| d3 e3 f3 (dy + dy2) |
| g3 h3 i3 (dz + dz2) |
| 0 0 0 1 |
Математики называют это свойство замыканием и обязаны определять пространство.
Для нас это означает, что мы можем продолжать делать умножения матриц для успешного расчета конечных преобразований, поэтому в первую очередь используем используемые матрицы, не получая более общих 4D-линейных преобразований, которые не являются аффинными.
Проекция усеченного
Но подождите, есть еще одна важная трансформация, которую мы делаем все время: она glFrustum
делает объект в 2 раза дальше, выглядит в 2 раза меньше.
Во- первых получить некоторую интуицию о glOrtho
против glFrustum
на: https://stackoverflow.com/questions/2571402/explain-the-usage-of-glortho/36046924#36046924
glOrtho
может быть сделано только с переводами + масштабирование, но как мы можем реализовать glFrustum
с помощью матриц?
Предположим, что:
z = -1
- это квадрат длины 2z = -2
Если бы мы только допустили более общие 4-векторы типа:
(x, y, z, w)
с w != 0
, и, кроме того, мы отождествляем каждый (x, y, z, w)
с (x/w, y/w, z/w, 1)
, тогда преобразование усеченного с матрицей будет:
| 1 0 0 0 | | x | | x | | x / -z |
| 0 1 0 0 | * | y | = | y | identified to | y / -z |
| 0 0 1 0 | | z | | z | | -1 |
| 0 0 -1 0 | | w | | -z | | 0 |
Если мы выбрасываем z
и w
в конце мы получаем:
x_proj = x / -z
y_proj = y / -z
что именно то, что мы хотели! Мы можем проверить это для некоторых значений, например:
z == -1
именно на плоскости мы выступающую к, x_proj == x
и y_proj == y
.z == -2
, то x_proj = x/2
: объекты имеют половинный размер.Обратите внимание, что glFrustum
преобразование не имеет аффинной формы: оно не может быть реализовано только с помощью поворотов и переводов.
Математическая «хитрость» сложения w
и деления на нее называется однородными координатами
См. Также: связанный вопрос переполнения стека: https://stackoverflow.com/questions/2465116/understanding-opengl-matrices
Смотрите это видео, чтобы понять концепции модели, просмотра и проекции.
Матрицы 4х4 используются не только для перевода трехмерного объекта. Но и для различных других целей.
Посмотрите это, чтобы понять, как вершины в мире представлены в виде 4-мерных матриц и как они преобразуются.