У цій статті я коротко розповім, як саме перетворюються координати точок при повороті камери в 3D іграх, css-перетвореннях і взагалі скрізь, де є якісь обертання камери або предметів у просторі. За сумісництвом це буде коротким введенням в лінійну алгебру: читач дізнається, що таке (насправді) вектор, скалярний твір і, нарешті, матриця повороту.
Введення
Завдання. Припустимо, що у нас є акціонерна картинка, як нижче (будиночок).
Припустимо також, що ми дивимося на будиночок з початку координат у напрямку ОХ. Тепер ми повернулися на деякий кут проти годинникової стрілки. Питання: як виглядатиме для нас будиночок? Інтуїтивно зрозуміло, що результат буде приблизно такий, як на картинці нижче.
Але як розрахувати результат? І, що найгірше, як це робити в тривимірному просторі? Якщо, наприклад, ми обертаємо камеру дуже хитро: спочатку вздовж осі OZ, потім ОХ, потім OY?
Відповіді на ці запитання дасть стаття нижче. Спочатку я розповім, як уявляти будиночок у вигляді цифр (тобто розповім про вектори), потім - про те, що таке кути між векторами (тобто про скалярний твір) і нарешті - про те, як обертати камеру (про матрицю повороту).
Координати вектора
Подумаймо про вектори. Тобто про стрілок з довжиною і напрямком.
У програмі до комп'ютерної графіки кожна така стрілка задає точку в просторі.
Їх-то ми і хочемо навчитися обертати. Тому що коли ми повернемо всі стрілки на картинці вище, ми повернемо будиночок. Давайте уявимо, що все, що ми вміємо робити з цими стрілками - це складати і домножувати на число. Як у школі: щоб скласти два вектори, треба провести лінію від початку першого вектора до кінця другого.
Поки ми зосередимося на акціонерних векторах. Для початку, нам хотілося б навчитися якось записувати ці вектори через числа, тому що кожен раз малювати їх на папері у вигляді стрілок не дуже зручно.
Навчимося це робити, згадавши про те, що будь-який вектор можна уявити як суму деяких спеціальних векторів (ОХ і ОУ), можливо, домножених на певні коефіцієнти. Ці спеціальні вектори називаються базисними, а коефіцієнти - ні що інше, як координати нашого вектора. Якщо ми будемо позначати базисні вектори через (тут i - це індекс вектора, він дорівнює або 1, або 2), розглянутий вектор як, а координати останнього як, то отримаємо формулу
(1)
Ви можете показати, що ці координати будуть єдиними для цього базису.
Користь від процедури приписування координат нашим стрілочкам очевидна - раніше треба було постійно малювати стрілку, щоб описати вектор, а тепер досить просто написати два числа - координати цього вектора. Наприклад, ми можемо домовитися писати ось так: . Або так: . Тоді, а. Чудово.
У справжній математиці процедура дещо інша. Спочатку описуються властивості, якими повинні задовольняти які завгодно об'єкти, щоб ми називали їх векторами. Вони дуже природні. Наприклад, вектори повинні підтримувати операцію додавання (двох векторів) і домноження на число. Сума двох векторів не повинна залежати від порядку доданків. Сума трьох векторів не повинна залежати від того, в якому порядку ми їх складаємо попарно. тощо. Повний список є на вікіпедії.
Якщо наші які завгодно штуки задовольняють цим властивостям, то ці штуки можна називати векторами (це такий duck typing). А все безліч цих штук - векторним або лінійним простором. Властивості вище називають аксіомами, і з них виводять всі інші властивості векторів (або лінійного простору - звідси і назву «лінійна алгебра»). Наприклад, можна вивести, що серед векторів будуть існувати такі особливі, базисні вектори, через які можна виразити будь-який вектор за формулою (1) і те, що це розкладання на координати буде єдиним для даного базису. Дуже швидко можна показати, що наші стрілочки якраз задовольняють цим аксіомам. Аксіоматичний підхід зручний, тому що якщо ми зіткнемося з якимись іншими об'єктами, які задовольняють аксіомам, то до них відразу можна застосувати всі результати нашої теорії. Крім того, так ми уникаємо визначень стрілочок на пальцях на початку теорії.
Можна легко показати (з тих самих аксіом), що при складанні векторів їх відповідні координати будуть складатися, а при домноженні вектора на число всі координати домножуються на це ж число. Тепер, щоб скласти два вектори, як на картинці нижче, ми можемо не малювати їх (і не вести лінію від початку першого вектора до кінця другого), а писати, наприклад,.
Скалярний твір
Давайте тепер введемо спеціальну функцію від двох довільних векторів a і b, яку будемо називати скалярним твором. Ми будемо позначати його ось так: . Ці модні дужки по-науковому називаються бра- і кет- вектори. Ніякої користі від них поки немає, але виглядає здорово - крім того, це позначення все-таки має глибокий сенс, особливо якщо вдаватися в математичні подробиці або квантову механіку.
У дусі нашого аксіоматичного підходу ми лише вимагатимемо, щоб скалярний твір задовольняв кільком аксіомам. Якщо замість першого вектора взяти суму векторів типу, то ми хочемо, щоб. Тут грецькі літери - множники, x і y - вектора. Ще ми хочемо, щоб якщо таку суму підставити замість другого вектора, то можна зробити такі ж перетворення (скалярний твір суми векторів теж виявляється сумою скалярних творів, а множники також виносяться за дужки). Крім того, ми хочемо, щоб значення завжди були неотрицательными. Нарешті, ми хочемо, щоб рівнялося нулю тоді і тільки тоді, коли сам вектор нульовий. Ах так, і ще, щоб.
Якщо ми додамо до наших стрілочок на папері лінійку і транспортир, то цим аксіомам буде задовольняти функція, відома зі школи: , де довжини векторів міряються лінійкою, кут між векторами - транспортиром.
Якщо ж лінійки і транспортиру у нас немає, то зі скалярного твору можна визначити довжину вектора - і кут між векторами: . Звичайно ж, кут залежить від способу визначення скалярного твору.
Давайте подивимося, як виражається скалярний твір через окремі координати векторів. Припустимо, що у нас є два вектори a і b, які виглядають ось так: , . Тоді.
Виглядає не дуже. Щоб зробити життя кращим, ми будемо далі працювати тільки з особливими системами координат. Ми виберемо тільки ті системи координат, у яких базисні вектори мають одиничну довжину і перпендикулярни між собою. Іншими словами,
(2a), якщо
(2b), якщо
Такі вектори називаються ортонормованими. Вираз для скалярного твору в ортонормованих системах координат перетворюється до невпізнання:
(3)
Всі системи координат у цій статті передбачаються ортонормованими. Дивно, але з нашої побудови випливає, що результат формули (3) не залежить від того, який саме ортонормований базис для координат вибрати.
Уважно подивившись на картинку «Розкладання вектора на координати» (вона наведена ще раз після цього абзацу), можна запідозрити, що координата вектора - це не що інше, як його проекція на відповідний базисний вектор. Тобто значення скалярного твору вихідного вектора з одним з базисних векторів:
(4)
Дійсно, наприклад,. Здається, що це тавтологія, тому що координати базисних векторів у своєму ж базисі завжди будуть (1, 0) і (0, 1). Але ж ми можемо взяти інші базисні вектори, і висловити їх через старий базис. Наприклад, новий ортонормований базис може виглядати в старому базисі як і. І тоді ми можемо визначити, наприклад, першу координату вектора в новому базисі за формулою (4) як.
Допитливий читач скаже «але ж формулу (3) можна використовувати як визначення скалярного твору, і тоді нам не треба ніякої ортонормованості базисних векторів». І буде правий у тому, що формула (3) може працювати як одне з визначень скалярного твору. Але тут є тонкий момент: тоді нам треба показати, що при зміні системи координат ця ж формула, але з координатами векторів a і b з іншого базису, дасть таке ж число. А це буде тільки в тому випадку, якщо всі базиси ортонормовані. Це можна буде показати, прочитавши наступний розділ.
Обертання системи координат
Давайте з'ясуємо, як змінюються координати векторів, якщо ми змінюємо всю систему координат. Навіщо нам взагалі змінювати систему координат? Якщо трохи подумати, то стане ясно, що поворот системи координат еквівалентний повороту камери в 3D або 2D-моделюванні (дивіться нижче трохи модифікований малюнок з будиночком). Так що навчитися обертати систему координат - це якраз те, що нам треба.
Давайте позначимо i-ю координату вектора а в новій системі координат як, а нові базисні вектори як. Крім того, позначимо j-ую координату СТАРОГО базисного вектора i в НОВОМУ базисі як. Нарешті, позначимо i-ую координату НОВОГО базисного вектора j у СТАРОМУ базисі як. Тепер ми можемо висловити вихідний вектор і старі базисні вектори через нові базисні вектори. А саме
(5) і
(6)
Крім того, можна висловити нові базисні вектори через старі:
(7)
Деякі з цих розкладів зображені на картинці нижче.
Тепер ми просто перепишемо формулу (1) через вектори нового базису:
Якщо порівняти це з формулою (5), і згадати, що координати векторів визначені однозначно, то можна помітити, що
(8) і
Дивно, як ці формула схожі на рівняння (3)! Вони виглядають як скалярний твір вектора з певними векторами (нижче ми покажемо, що це не випадково).
Якщо записати рівняння (9) однією формулою, то вийде
(9)
Цю формулу можна вивести по-іншому, об'єднавши (4), (1) і (7): . Якщо згадати властивості скалярного твору, то ця формула розпадається на чотири суми. Якщо ж тепер згадати про те, що наші базисні вектори ортонормовані, то отримуємо.
Ця формула виглядає не зовсім так, як формула (9): замість тут стоять. Це не помилка - просто. Тобто j-а координата СТАРОГО базисного вектора i в НОВОМУ базисі завжди дорівнює i-ій координаті НОВОГО базисного вектора j в СТАРОМУ базисі,. Це стане очевидно, якщо спробувати висловити ці координати через формулу (4):
(10) ,
А скалярний твір, як ми пам'ятаємо, не залежить від порядку твору векторів.
Це стане ще більш очевидно, якщо згадати про те, що ці скалярні твори - це кути між різними (одиничними) базисними векторами. Ці кути, зрозуміло, не залежать від того, чи відкладати їх по або проти годинникової стрілки.
Матриця повороту
Якщо ви знайомі з матрицями, то формулу (9) (дві формули) можна переписати в матричному вигляді
(11)
Що це взагалі все означає?! Як завжди, тут немає ніякої магії - просто ми домовляємося, що домноження цієї таблички з чисел ліворуч на вектор праворуч обчислюється як формула (9). Тобто кожну сходинку таблички ми домножуємо на стовпчик праворуч (начебто ми здійснюємо скалярний твір двох векторів), і результати записуємо один під одним, теж отримуючи стовпець.
Можна, до речі, поширити це правило на перемноження двох табличок: домовимося домножувати кожну сходинку першої таблички на кожен стовпець другий, і результати теж записувати в табличку: перемноження першого рядка з третім стовпчиком запишемо в першу сходинку і третій стовпчик. Формула (11) тоді стає приватним випадком цього правила. Схематично це все зображено на малюнку нижче.
Таблички з чисел, забезпечені таким правилом домноження на вектори та інші таблички, будемо називати матрицями.
Правило перемноження матриць виглядає ще більш природно, якщо дізнатися, що скалярний твір, як ми домовилися його позначати,, на самому припускає, що вектор a - це рядок, а вектор b - стовпець. До цього ми домовилися записувати вектори стовпчиками, і вектор-рядок a насправді - це не просто перевернутий вектор a, а об'єкт спеціального подвійного векторного простору. Але в разі ортонормованих базисів координати вихідного і двоїстого векторів збігаються (тобто а-рядок і а-стовпець однакові), так що ці деталі не впливають на наш виклад. Все нормально. Крім того, з іншого боку, формула (3) для скалярного твору - це приватний випадок перемноження матриць.
Взагалі, можна показати, що домноження на матриці відповідає певним трансформаціям векторів. Замість «трансформації» прийнято говорити оператори. А домноження на матрицю є лінійним оператором. Крім того, для будь-якого лінійного оператора існує одна і тільки одна матриця оператора. Про те, що це таке, можна почитати на вікіпедії. Якщо описувати це тут, стаття ніколи не закінчиться.
Отже, як ми з'ясували, поворот системи координат еквівалентний повороту камери в 3D або 2D-моделюванні. Тому матриця з формули (11) називається матрицею повороту. Формулу (11) можна інтерпретувати не як заміну системи координат, а як опис оператора повороту.
Поки не зовсім зрозуміло, як обчислювати цю матрицю. Це нескладно, якщо звернутися до формул (10) і згадати, що косинус кута між одиничними векторами дорівнює їх скалярному твору. Тоді, наприклад, де - кут обертання системи координат (камери). Він за визначенням позитивний, якщо обертання відбувається проти годинникової стрілки, і негативний при обертанні за годинниковою стрілкою (дивіться малюнок трохи нижче - він вже був, але тепер знову актуальний). Якщо трохи повозитися з геометрією або тригонометрією, то можна з'ясувати, що вся матриця повороту виглядає ось так:
(12a)
Якщо зазирнути у вікіпедію, то формула там виглядає трохи по-іншому:
(12b)
Це все тому, що в ній - це кут обертання самих векторів (або наших об'єктів типу будиночка). Він теж вважається позитивним, якщо обертання відбувається проти годинникової стрілки. Але обертання камери протилежне обертанню об'єктів, тобто кут обертання камери дорівнює куті обертання об'єктів, але взятому зі зворотним знаком.
Знову актуальний малюнок:
Приємні дрібниці
Ці матриці - дуже зручні штуки. Їх можна перемножувати і складати, притому не тільки по дві, але і по три і по чотири. Матриці можна позначати великими літерами. Наприклад, Т - звичайне позначення для матриць повороту (вона, безумовно, залежить від того, як повертати систему або камеру). Тоді формула (11) перейде в.
У матриць є одинична матриця - в тому сенсі, що будь-який вектор, будучи домноженим на неї зліва, залишається самим собою. І будь-яка матриця теж. Одинична матриця виглядає як таблиця, вся заповнена нулями, тільки на діагоналі стоять одиниці. Така матриця відповідає повороту на нуль градусів. Тобто відсутності повороту. Вона виглядає так:
(13)
Якщо трохи порахувати або подумати, то перемноження матриць повороту відповідає кільком поворотам, здійсненим один за одним (але в іншому порядку - справа наліво). Так що якщо у вашій програмі відбувається кілька заздалегідь відомих поворотів поспіль, то не поспішайте їх застосовувати для всіх точок у вашому тривимірному світі. Краще перемножте матриці, отримайте загальну матрицю повороту, і вже застосуйте її.
Для багатьох матриць можна знайти такі, що при домноженні першою на другу виходить одинична матриця. Ці нові матриці називаються зворотними, і для T вони позначаються як. Тобто.
Якщо ще трохи подумати, то така матриця повинна відповідати зворотному для Т повороту - такому, який нейтралізує Т. Це вже дуже зручно. Якщо навчитися обчислювати зворотні матриці, можна легко обертати камеру назад, при необхідності.
Якщо подумати зовсім не трохи, і навіть трохи порахувати, то для матриць повороту, в силу того, що вони володіють специа
