Table of Contents

Menggunakan EasyAR dalam engine 3D

Untuk menggunakan EasyAR dalam engine 3D, Anda perlu merender gambar kamera dan objek virtual. Objek virtual yang dirender harus sejajar dengan gambar kamera. Saat merender gambar kamera, beberapa parameter pada saat gambar dihasilkan dan ditampilkan mungkin tidak cocok. Misalnya posisi, orientasi, frame size, aspect ratio kamera fisik, dan parameter lain mungkin berbeda dari gambar layar, sehingga perlu dipertimbangkan saat rendering. Jika Anda perlu mengintegrasikan EasyAR ke engine 3D yang belum didukung, perhatikan detail berikut secara khusus.

Memotong padding batas gambar kamera

Cropping, transposisi, dan encoding gambar semuanya memerlukan komputasi yang cukup besar. Untuk mengurangi komputasi dan latency, biasanya format yang relatif mentah digunakan. Agar video encoding lebih mudah, gambar keluaran kamera fisik sering disejajarkan ke grid seperti 8x8, 16x16, 32x32, atau 64x64. Misalnya, saat resolusi 1920x1080 dipilih pada beberapa ponsel, gambar keluaran dapat menjadi 1920x1088 karena 1080 bukan kelipatan 64.

image with padding

Ini mengharuskan bagian padding ekstra dihapus saat rendering. Ada beberapa pendekatan yang memungkinkan. Salah satunya adalah menentukan width saat meng-upload gambar ke video memory, misalnya menggunakan glPixelStorei(GL_PACK_ROW_LENGTH, ...) di OpenGL. Cara lain adalah menghitung koordinat UV secara manual dalam fragment shader dan memotong bagian yang melebihi saat sampling dari gambar.

Rendering mengikuti rotasi layar

Pada ponsel, gambar yang direkam kamera fisik biasanya tetap relatif terhadap body perangkat dan tidak berubah mengikuti orientasi tampilan layar. Namun perubahan orientasi body ponsel memengaruhi cara kita mendefinisikan arah atas, bawah, kiri, dan kanan gambar. Saat rendering, orientasi tampilan layar saat ini juga memengaruhi arah gambar yang ditampilkan.

Biasanya saat rendering, Anda perlu menentukan sudut rotasi gambar kamera relatif terhadap orientasi tampilan layar.

Jika \(\theta_{screen}\) menyatakan radian rotasi searah jarum jam gambar layar relatif terhadap orientasi natural layar, \(\theta_{phycam}\) menyatakan radian rotasi searah jarum jam yang diperlukan agar gambar kamera fisik tampil benar pada layar dalam orientasi natural, dan \(\theta\) menyatakan radian rotasi searah jarum jam yang diperlukan agar gambar kamera fisik tampil pada layar saat ini.

Untuk kamera belakang:

\[ \theta = \theta_{phycam} - \theta_{screen} \]

Misalnya, pada ponsel Android, saat ponsel digunakan dalam orientasi natural, \(\theta_{screen} = 0, \theta_{phycam} = \frac{\pi}{2}\), sehingga \(\theta = \frac{\pi}{2}\).

Untuk kamera depan, jika gambar dibalik kiri-kanan setelah rotasi selesai:

\[ \theta = \theta_{phycam} + \theta_{screen} \]
Catatan

Saat gambar layar berotasi, \(\theta\) harus segera dihitung ulang pada frame pertama setelah rotasi terjadi; jika tidak, arah gambar layar dapat salah sesaat.

Rendering background kamera dan objek virtual

Saat merender objek virtual pada ponsel, objek virtual harus sejajar dengan gambar kamera. Ini mengharuskan kamera rendering dan objek ditempatkan dalam ruang virtual yang benar-benar sesuai dengan ruang nyata, dan dirender dengan field of view serta aspect ratio yang sama dengan kamera fisik. Transformasi perspective projection yang diterapkan pada gambar kamera dan objek virtual hampir sama. Satu-satunya perbedaan adalah sebagian besar transformasi perspective projection gambar kamera terjadi di dalam kamera fisik, sedangkan transformasi perspective projection objek virtual sepenuhnya merupakan proses komputasi.

Bagian berikut menggunakan konvensi OpenGL. Jika konvensi lain digunakan, pemetaan sumbu koordinat yang sesuai diperlukan. Misalkan sumbu koordinat sistem koordinat kamera didefinisikan sebagai berikut: sumbu x mengarah ke kanan, sumbu y mengarah ke atas, dan sumbu z mengarah keluar dari layar. Sumbu koordinat sistem koordinat clip didefinisikan sebagai berikut: sumbu x mengarah ke kanan, sumbu y mengarah ke atas, sumbu z mengarah keluar dari layar, dan sumbu w adalah sumbu virtual.

Pada kondisi ini, matrix transformasi perspective projection yang diperlukan untuk merender gambar kamera adalah sebagai berikut:

\[ P_i=\left( \begin{array}{cccc} (-1)^{\text{flip}} & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & 1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} \cos (-\theta ) & -\sin (-\theta ) & \phantom{0} & \phantom{0} \\ \sin (-\theta ) & \cos (-\theta ) & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} s_x & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & s_y & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right) \]

Di sini, flip menunjukkan apakah gambar dibalik secara horizontal. Nilainya 1 saat dibalik dan 0 saat tidak dibalik. \(\theta\) adalah sudut rotasi gambar searah jarum jam, dalam radian. \(s_x\) dan \(s_y\) adalah faktor skala untuk proportional scaling atau proportional filling, dan nilainya berubah mengikuti \(\theta\). Matrix transformasi ini pertama-tama menskalakan gambar kamera, lalu merotasinya, dan akhirnya membaliknya. Saat rendering, gunakan sebuah persegi panjang yang memenuhi layar. Misalnya, di OpenGL, vertex persegi panjang dapat ditempatkan pada \((-1, -1, 0)\), \((1, -1, 0)\), \((1, 1, 0)\), dan \((-1, 1, 0)\), dengan koordinat UV diatur pada empat sudut yang sesuai, lalu dirender menggunakan matrix perspective projection ini.

Matrix perspective projection yang diperlukan untuk merender objek virtual adalah sebagai berikut:

\[ P=P_i\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & 1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -\frac{f+n}{f-n} & -\frac{2 f n}{f-n} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \end{array} \right)\left( \begin{array}{cccc} \frac{2}{w} & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & \frac{2}{h} & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & -1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} f_x & \phantom{0} & c_x & \phantom{0} \\ \phantom{0} & f_y & c_y & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & -1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right) \]

Di sini, \(n\) dan \(f\) adalah parameter near clipping dan far clipping yang umum digunakan dalam matrix perspective projection rendering 3D. \(w\) dan \(h\) adalah lebar dan tinggi pixel gambar kamera. \(f_x\), \(f_y\), \(c_x\), dan \(c_y\) adalah parameter intrinsik umum dalam model kamera, dengan \(f_x\) dan \(f_y\) sebagai focal length dalam pixel, serta \(c_x\) dan \(c_y\) sebagai posisi pixel principal point. Matrix projection ini melakukan transformasi berikut secara berurutan: transformasi perspective projection dari intrinsics kamera (karena arah sumbu y dan z sistem koordinat gambar di OpenCV berlawanan dengan sistem koordinat kamera OpenGL, dilakukan dua transformasi sistem koordinat), transformasi dari sistem koordinat pixel gambar ke sistem koordinat persegi panjang gambar, transformasi near clipping dan far clipping, serta transformasi perspective projection yang digunakan saat merender gambar kamera.

Setelah disederhanakan, diperoleh:

\[ P=P_i\left( \begin{array}{cccc} \frac{2 f_x}{w} & \phantom{0} & 1-\frac{2 c_x}{w} & \phantom{0} \\ \phantom{0} & \frac{2 f_y}{h} & -1+\frac{2 c_y}{h} & \phantom{0} \\ \phantom{0} & \phantom{0} & -\frac{f+n}{f-n} & -\frac{2 f n}{f-n} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \end{array} \right) \]

Dari proses di atas, rendering biasanya perlu dilakukan dalam dua pass: satu pass merender gambar kamera, dan satu pass merender objek virtual, dengan objek virtual ditumpangkan di atas gambar kamera.

Beberapa engine 3D merepresentasikan matrix perspective projection dengan parameter seperti horizontal field of view dan aspect ratio. Jika rotasi dan flipping tidak dipertimbangkan serta offset principal point diabaikan, parameter ini dapat dihitung, dengan horizontal field of view \(\alpha=2 arctan{\frac{w}{2 f_x}}\) dan aspect ratio \(r=\frac{w}{h}\).

Perlu dicatat bahwa distorsi kamera tidak dipertimbangkan dalam proses ini, karena distorsi kamera pada sebagian besar ponsel saat ini sangat kecil.