Відповіді:
Так, ви можете додати вектор у випадку перекладу. Причина використання матриці зводиться до того, що є рівномірний спосіб обробляти різні комбіновані перетворення.
Наприклад, обертання зазвичай виконується за допомогою матриці (перевірити коментар @MickLH на інші способи боротьби з обертаннями), тому для того, щоб рівномірно боротися з декількома перетвореннями (обертання / переклад / масштабування / проекція ... тощо), їх потрібно закодувати в матриці.
Ну, технічніше кажучи; перетворення - це зіставлення точки / вектора до іншої точки / вектора.
p` = T(p);
де p` - перетворена точка, а T (p) - функція перетворення.
Зважаючи на те, що ми не використовуємо матрицю, нам потрібно це зробити для об'єднання декількох перетворень:
p1 = T (p);
p кінцевий = M (p1);
Матриця може не тільки поєднувати в одній матриці кілька типів перетворень (наприклад, афінну, лінійну, проективну).
Використання матриці дає нам можливість об'єднати ланцюги перетворень, а потім пакетно помножити їх. Це заощаджує нам тону циклів, як правило, GPU (дякує @ChristianRau, що вказав на це).
T кінцевий = T * R * P; // перекласти проект обертання
p кінцевий = T final * p;
Також добре зазначити, що GPU і навіть деякі процесори оптимізовані для векторних операцій; Процесорні процесори, що використовують SIMD та графічні процесори, будучи паралельними процесорами, керованими даними, тому використання матриць ідеально поєднується з апаратним прискоренням (насправді, графічні процесори були розроблені так, щоб відповідати матричним / векторним операціям).
Якщо все, що ви збираєтеся робити, - це рухатися по одній осі і ніколи не застосовувати жодних інших перетворень, то те, що ви пропонуєте, це добре.
Справжня сила використання матриці полягає в тому, що ви можете легко об'єднати ряд складних операцій разом і застосувати одну і ту ж серію операцій до декількох об'єктів.
Більшість випадків не такі прості, і якщо ви обертаєте спочатку об'єкт, і хочете перетворити його локальні осі замість світових осей, ви знайдете, що ви не можете просто додати 10 до одного з чисел, і це буде правильно працювати .
Щоб швидко відповісти на питання "чому", це тому, що матриця 4x4 може описати операції обертання, перекладу та масштабування всі відразу. Бути в змозі послідовно описати будь-яке з них спрощує багато речей.
Різні види перетворень можна простіше представити за допомогою різних математичних операцій. Як зазначаєте, переклад можна зробити лише додаванням. Рівномірне масштабування шляхом множення на скаляр. Але належним чином складена матриця 4x4 може зробити все, що завгодно. Тому використання 4x4 постійно робить код та інтерфейси набагато простішими. Ви платите певні складності в розумінні цих 4х4, але тоді багато речей стають легшими та швидшими через це.
причина використання матриці 4x4 полягає в тому, що операція є лінійним перетворенням . це приклад однорідних координат . Те ж саме робиться у випадку 2d (використовуючи матрицю 3x3). Причина використання однорідних координат полягає в тому, що всі 3 геометричні танформації можна виконати за допомогою однієї операції; в іншому випадку потрібно буде помножити матрицю 3x3 та доповнити матрицю 3x3 (для перекладу). це посилання від 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 |
Цей відео-посібник Джеймі Кінга також варто переглянути.
Прихильний простір
Аффінний простір - це простір, генерований усіма нашими 3D-лінійними перетвореннями (множення матриці) разом із 4D-зрушенням (3D-переклади).
Якщо ми помножимо матрицю зсуву та 3D-лінійну трансформацію, ми завжди отримаємо щось із вигляду:
| 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
vs за 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
Дивіться це відео, щоб зрозуміти поняття моделі, перегляду та проекції.
Матриці 4x4 використовуються не просто для перекладу 3D-об'єкта. Але також для різних інших цілей.
Дивіться це, щоб зрозуміти, як вершини у світі представлені як 4D-матриці та як вони перетворюються.