Jawaban:
Ya, Anda dapat menambahkan vektor untuk terjemahan. Alasan untuk menggunakan matriks bermuara pada memiliki cara yang seragam untuk menangani berbagai transformasi gabungan.
Sebagai contoh, rotasi biasanya dilakukan dengan menggunakan matriks (periksa komentar @MickLH untuk cara-cara lain untuk menangani rotasi), sehingga untuk menangani beberapa transformasi (rotasi / terjemahan / penskalaan / proyeksi ... dll) dengan cara yang seragam, Anda harus menyandikannya dalam sebuah matriks.
Nah, secara teknis lebih banyak; transformasi adalah memetakan suatu titik / vektor ke titik / vektor lain.
p` = T(p);
di mana p` adalah titik transformasi dan T (p) adalah fungsi transformasi.
Karena kami tidak menggunakan matriks, kami perlu melakukan ini untuk menggabungkan banyak transformasi:
p1 = T (p);
p final = M (p1);
Matriks tidak hanya dapat menggabungkan berbagai jenis transformasi menjadi matriks tunggal (misalnya affine, linear, projective).
Menggunakan matriks memberi kita kesempatan untuk menggabungkan rantai transformasi dan kemudian mengalikannya. Ini menghemat satu ton siklus yang biasanya dilakukan oleh GPU (terima kasih kepada @ChristianRau karena menunjukkannya).
T final = T * R * P; // terjemahkan proyek rotate
p final = T final * p;
Juga bagus untuk menunjukkan bahwa GPU dan bahkan beberapa CPU dioptimalkan untuk operasi vektor; CPU yang menggunakan SIMD dan GPU menjadi prosesor didorong data paralel oleh desain, sehingga menggunakan matriks sangat cocok dengan akselerasi perangkat keras (sebenarnya, GPU dirancang agar sesuai dengan operasi matriks / vektor).
Jika semua yang akan Anda lakukan adalah bergerak sepanjang sumbu tunggal dan tidak pernah menerapkan transformasi lain maka apa yang Anda sarankan baik-baik saja.
Kekuatan sebenarnya dari menggunakan matriks adalah Anda dapat dengan mudah menggabungkan serangkaian operasi kompleks bersama-sama, dan menerapkan serangkaian operasi yang sama untuk beberapa objek.
Sebagian besar kasus tidak sesederhana itu dan jika Anda memutar objek terlebih dahulu, dan ingin mengubah sepanjang sumbu lokalnya alih-alih sumbu dunia Anda akan menemukan Anda tidak dapat dengan mudah menambahkan 10 ke salah satu angka dan membuatnya bekerja dengan benar .
Untuk menjawab pertanyaan "mengapa" dengan ringkas, itu karena matriks 4x4 dapat menggambarkan operasi rotasi, terjemahan, dan penskalaan sekaligus. Mampu menggambarkan semua ini secara konsisten menyederhanakan banyak hal.
Berbagai jenis transformasi dapat lebih sederhana diwakili dengan operasi matematika yang berbeda. Seperti yang Anda perhatikan, terjemahan dapat dilakukan hanya dengan menambahkan. Penskalaan seragam dengan mengalikan dengan skalar. Tetapi matriks 4x4 yang dibuat dengan tepat dapat melakukan apa saja. Jadi menggunakan 4x4 secara konsisten membuat kode dan antarmuka menjadi lebih sederhana. Anda membayar beberapa kompleksitas dalam memahami 4x4 ini, tetapi kemudian banyak hal menjadi lebih mudah dan lebih cepat karenanya.
alasan untuk menggunakan matriks 4x4 adalah agar operasinya adalah transformasi linear . ini adalah contoh dari koordinat homogen . Hal yang sama dilakukan dalam kasus 2d (menggunakan matriks 3x3). Alasan untuk menggunakan koordinat homogen adalah agar ketiga informasi geometrik dapat dilakukan menggunakan satu operasi; jika tidak, kita perlu melakukan penggandaan matriks 3x3 dan penambahan matriks 3x3 (untuk terjemahan). ini Link dari cegprakash berguna.
Terjemahan tidak dapat diwakili oleh matriks 3D
Argumen sederhana adalah bahwa terjemahan dapat menggunakan vektor asal:
0
0
0
jauh dari asalnya, katakan kepada x = 1
:
1
0
0
Tetapi itu membutuhkan matriks sedemikian rupa sehingga:
| a b c | |0| |1|
| d e f | * |0| = |0|
| g h i | |0| |0|
Tapi itu tidak mungkin.
Argumen lain adalah teorema Dekomposisi Nilai Singular , yang mengatakan bahwa setiap matriks dapat dibuat dengan dua rotasi dan satu operasi penskalaan. Tidak ada terjemahan di sana.
Mengapa matriks dapat digunakan?
Banyak objek yang dimodelkan (misalnya sasis mobil) atau bagian dari objek yang dimodelkan (misalnya ban mobil, roda penggerak) adalah benda padat: jarak antara titik tidak pernah berubah.
Satu-satunya transformasi yang ingin kita lakukan adalah rotasi dan terjemahan.
Penggandaan matriks dapat menyandikan rotasi dan terjemahan.
Matriks rotasi memiliki rumus eksplisit, misalnya: matriks rotasi 2D untuk sudut a
berbentuk:
cos(a) -sin(a)
sin(a) cos(a)
Ada rumus analog untuk 3D , tetapi perhatikan bahwa rotasi 3D mengambil 3 parameter, bukan hanya 1 .
Terjemahan kurang sepele dan akan dibahas nanti. Mereka adalah alasan kami membutuhkan matriks 4D.
Mengapa keren menggunakan matriks?
Karena komposisi beberapa matriks dapat pra-dihitung dengan perkalian matriks .
Misalnya, jika kita akan menerjemahkan seribu vektor v
sasis mobil kami dengan matriks T
dan kemudian memutar dengan matriks R
, alih-alih melakukan:
v2 = T * v
lalu:
v3 = R * v2
untuk setiap vektor, kita dapat melakukan pra-perhitungan:
RT = R * T
dan kemudian lakukan hanya satu perkalian untuk setiap titik:
v3 = RT * v
Bahkan lebih baik: jika kita ingin menempatkan vertex ban dan roda penggerak relatif terhadap mobil, kita hanya mengalikan matriks sebelumnya RT
dengan matriks relatif terhadap mobil itu sendiri.
Ini secara alami menyebabkan pemeliharaan tumpukan matriks:
Bagaimana menambahkan satu dimensi memecahkan masalah
Mari kita perhatikan kasus dari 1D ke 2D yang lebih mudah divisualisasikan.
Matriks dalam 1D hanya satu angka, dan seperti yang telah kita lihat dalam 3D itu tidak dapat melakukan terjemahan, hanya penskalaan ..
Tetapi jika kita menambahkan dimensi ekstra sebagai:
| 1 dx | * |x| = | x + dx |
| 0 1 | |1| | 1 |
dan kemudian kita melupakan dimensi ekstra baru, kita mendapatkan:
x + dx
seperti yang kita inginkan.
Transformasi 2D ini sangat penting sehingga memiliki nama: transformasi geser .
Keren memvisualisasikan transformasi ini:
Perhatikan bagaimana setiap garis horizontal (tetap y
) baru saja diterjemahkan.
Kami kebetulan mengambil garis tersebut y = 1
sebagai garis 1D baru kami, dan menerjemahkannya dengan matriks 2D.
Hal-hal analog dengan 3D, dengan matriks geser bentuk 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 |
Dan rotasi / penskalaan 3D lama kami sekarang berbentuk:
| a b c 0 |
| d e f 0 |
| g h i 0 |
| 0 0 0 1 |
Video tutorial Jamie King ini juga layak ditonton.
Ruang Affine
Ruang Affine adalah ruang yang dihasilkan oleh semua transformasi linear 3D kami (perkalian matriks) bersama dengan geser 4D (terjemahan 3D).
Jika kita mengalikan matriks geser dan transformasi linear 3D, kita selalu mendapatkan sesuatu dalam bentuk:
| a b c dx |
| d e f dy |
| g h i dz |
| 0 0 0 1 |
Ini adalah transformasi affine yang paling umum, yang melakukan rotasi / penskalaan dan terjemahan 3D.
Salah satu properti penting adalah jika kita mengalikan 2 matriks affine:
| 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 |
kami selalu mendapatkan matriks affine bentuk lain:
| a3 b3 c3 (dx + dx2) |
| d3 e3 f3 (dy + dy2) |
| g3 h3 i3 (dz + dz2) |
| 0 0 0 1 |
Matematikawan menyebut penutupan properti ini , dan diharuskan menentukan ruang.
Bagi kami, itu berarti bahwa kami dapat terus melakukan penggandaan matriks untuk menghitung kalkulasi final dengan senang hati, itulah sebabnya mengapa menggunakan matriks yang digunakan sejak awal, tanpa pernah mendapatkan transformasi linear 4D yang lebih umum yang tidak affine.
Proyeksi frustum
Tapi tunggu, ada satu lagi transformasi penting yang kita lakukan sepanjang waktu glFrustum
:, yang membuat objek 2x lebih jauh, tampak 2x lebih kecil.
Pertama, dapatkan intuisi tentang glOrtho
vs glFrustum
di: https://stackoverflow.com/questions/2571402/explain-the-usage-of-glortho/36046924#36046924
glOrtho
dapat dilakukan hanya dengan terjemahan + scaling, tetapi bagaimana kita bisa menerapkannya glFrustum
dengan matriks?
Seandainya:
z = -1
itu adalah kuadrat panjang 2z = -2
Kalau saja kita mengizinkan jenis vektor 4 yang lebih umum:
(x, y, z, w)
dengan w != 0
, dan di samping kami mengidentifikasi setiap (x, y, z, w)
dengan (x/w, y/w, z/w, 1)
, maka transformasi frustum dengan matriks akan menjadi:
| 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 |
Jika kita membuang z
dan w
pada akhirnya, kita mendapatkan:
x_proj = x / -z
y_proj = y / -z
itulah yang kami inginkan! Kami dapat memverifikasi itu untuk beberapa nilai, misalnya:
z == -1
, tepatnya di pesawat yang kita proyeksikan, x_proj == x
dan y_proj == y
.z == -2
, maka x_proj = x/2
: objek berukuran setengah.Perhatikan bagaimana glFrustum
transformasi ini bukan dari bentuk affine: transformasi tidak dapat diimplementasikan hanya dengan rotasi dan terjemahan.
"Tipu daya" matematika untuk menambahkan w
dan membaginya disebut sebagai koordinat homogen
Lihat juga: pertanyaan Stack Overflow terkait: https://stackoverflow.com/questions/2465116/understanding-opengl-matrices
Lihat video ini untuk memahami konsep model, tampilan, dan proyeksi.
Matriks 4x4 tidak hanya digunakan untuk menerjemahkan objek 3D. Tetapi juga untuk berbagai keperluan lainnya.
Lihat ini untuk memahami bagaimana simpul di dunia direpresentasikan sebagai Matriks 4D dan bagaimana mereka ditransformasikan.