Tutorial iOS ARKit: Menggambar di Udara dengan Jari Telanjang

Diterbitkan: 2022-03-11

Baru-baru ini, Apple mengumumkan perpustakaan augmented reality (AR) baru bernama ARKit. Bagi banyak orang, itu tampak seperti perpustakaan AR yang bagus, bukan pengganggu teknologi yang perlu diperhatikan. Namun, jika Anda melihat kemajuan AR dalam beberapa tahun terakhir, orang tidak boleh terlalu cepat menarik kesimpulan seperti itu.

Ilustrasi tutorial ARKit: Berinteraksi dengan objek virtual di aplikasi ARKit iOS

Dalam posting ini, kami akan membuat proyek contoh ARKit yang menyenangkan menggunakan iOS ARKit. Pengguna akan meletakkan jari-jarinya di atas meja seolah-olah sedang memegang pena, mengetuk gambar mini dan mulai menggambar. Setelah selesai, pengguna akan dapat mengubah gambar mereka menjadi objek 3D, seperti yang ditunjukkan pada animasi di bawah ini. Kode sumber lengkap untuk contoh ARKit iOS kami tersedia di GitHub.

Demonstrasi aplikasi augmented reality sampel ARKit iOS kami sedang digunakan

Mengapa Kita Harus Peduli dengan iOS ARKit Sekarang?

Setiap pengembang berpengalaman mungkin menyadari fakta bahwa AR adalah konsep lama. Kami dapat menemukan perkembangan serius pertama dari AR hingga saat pengembang mendapatkan akses ke masing-masing frame dari webcam. Aplikasi pada waktu itu biasanya digunakan untuk mengubah wajah Anda. Namun, umat manusia tidak butuh waktu lama untuk menyadari bahwa mengubah wajah menjadi kelinci bukanlah salah satu kebutuhan mereka yang paling mendesak, dan segera hype memudar!

Saya percaya AR selalu kehilangan dua lompatan teknologi utama untuk membuatnya berguna: kegunaan dan imersi. Jika Anda menelusuri hype AR lainnya, Anda akan melihat ini. Misalnya, sensasi AR kembali muncul ketika pengembang mendapatkan akses ke setiap frame dari kamera ponsel. Selain kembalinya transformator kelinci yang hebat, kami melihat gelombang aplikasi yang menjatuhkan objek 3D pada kode QR yang dicetak. Tapi mereka tidak pernah lepas landas sebagai sebuah konsep. Mereka bukan augmented reality, melainkan kode QR yang ditambah.

Kemudian Google mengejutkan kami dengan sepotong fiksi ilmiah, Google Glass. Dua tahun berlalu, dan pada saat produk yang luar biasa ini diharapkan untuk hidup, itu sudah mati! Banyak kritikus menganalisis alasan kegagalan Google Glass, menyalahkan apa pun mulai dari aspek sosial hingga pendekatan Google yang membosankan saat meluncurkan produk. Namun, kami peduli dalam artikel ini untuk satu alasan tertentu - perendaman di lingkungan. Sementara Google Glass memecahkan masalah kegunaan, itu masih tidak lebih dari gambar 2D yang diplot di udara.

Raksasa teknologi seperti Microsoft, Facebook, dan Apple mempelajari pelajaran keras ini dengan hati. Pada bulan Juni 2017, Apple mengumumkan perpustakaan ARKit iOS yang indah, menjadikan imersi sebagai prioritas utama. Memegang telepon masih merupakan pemblokir pengalaman pengguna yang besar, tetapi pelajaran Google Glass mengajari kami bahwa perangkat keras bukanlah masalahnya.

Saya yakin kita akan segera menuju puncak sensasi AR baru, dan dengan poros signifikan baru ini, pada akhirnya dapat menemukan pasar asalnya, memungkinkan lebih banyak pengembangan aplikasi AR menjadi arus utama. Ini juga berarti bahwa setiap perusahaan pengembang aplikasi augmented reality di luar sana akan dapat memanfaatkan ekosistem dan basis pengguna Apple.

Tapi sejarah yang cukup, mari kita mengotori tangan kita dengan kode dan melihat augmented reality Apple beraksi!

Fitur Perendaman ARKit

ARKit menyediakan dua fitur utama; yang pertama adalah lokasi kamera dalam ruang 3D dan yang kedua adalah deteksi bidang horizontal. Untuk mencapai yang pertama, ARKit mengasumsikan bahwa ponsel Anda adalah kamera yang bergerak di ruang 3D nyata sehingga menjatuhkan beberapa objek virtual 3D di titik mana pun akan ditambatkan ke titik itu di ruang 3D nyata. Dan yang terakhir, ARKit mendeteksi bidang horizontal seperti tabel sehingga Anda dapat menempatkan objek di atasnya.

Jadi bagaimana ARKit mencapai ini? Ini dilakukan melalui teknik yang disebut Visual Inertial Odometry (VIO). Jangan khawatir, seperti halnya pengusaha yang menemukan kesenangan mereka dalam jumlah tawa yang Anda cekikikan ketika Anda mengetahui sumber di balik nama startup mereka, peneliti menemukan mereka dalam jumlah garukan kepala yang Anda lakukan saat mencoba menguraikan istilah apa pun yang mereka buat ketika menamai penemuan mereka - jadi biarkan mereka bersenang-senang, dan lanjutkan.

VIO adalah teknik di mana bingkai kamera digabungkan dengan sensor gerak untuk melacak lokasi perangkat dalam ruang 3D. Pelacakan gerakan dari bingkai kamera dilakukan dengan mendeteksi fitur, atau, dengan kata lain, titik tepi pada gambar dengan kontras tinggi - seperti tepi antara vas biru dan meja putih. Dengan mendeteksi seberapa banyak titik-titik ini bergerak relatif satu sama lain dari satu bingkai ke bingkai lainnya, seseorang dapat memperkirakan di mana perangkat berada dalam ruang 3D. Itulah sebabnya ARKit tidak akan berfungsi dengan baik saat ditempatkan menghadap dinding putih tanpa fitur atau saat perangkat bergerak sangat cepat sehingga menghasilkan gambar yang kabur.

Memulai ARKit di iOS

Pada saat penulisan artikel ini, ARKit adalah bagian dari iOS 11, yang masih dalam versi beta. Jadi, untuk memulai, Anda perlu mengunduh iOS 11 Beta di iPhone 6s atau lebih tinggi, dan Xcode Beta baru. Kita dapat memulai proyek ARKit baru dari New > Project > Augmented Reality App . Namun, saya merasa lebih nyaman untuk memulai tutorial augmented reality ini dengan sampel resmi Apple ARKit, yang menyediakan beberapa blok kode penting dan sangat membantu untuk deteksi pesawat. Jadi, mari kita mulai dengan kode contoh ini, jelaskan poin utama di dalamnya terlebih dahulu, lalu modifikasi untuk proyek kita.

Pertama, kita harus menentukan mesin mana yang akan kita gunakan. ARKit dapat digunakan dengan Sprite SceneKit atau Metal. Dalam contoh Apple ARKit, kami menggunakan iOS SceneKit, mesin 3D yang disediakan oleh Apple. Selanjutnya, kita perlu menyiapkan tampilan yang akan membuat objek 3D kita. Ini dilakukan dengan menambahkan tampilan tipe ARSCNView .

ARSCNView adalah subkelas dari tampilan utama SceneKit bernama SCNView , tetapi ini memperluas tampilan dengan beberapa fitur yang berguna. Itu membuat umpan video langsung dari kamera perangkat sebagai latar belakang pemandangan, sementara itu secara otomatis mencocokkan ruang SceneKit ke dunia nyata, dengan asumsi perangkat adalah kamera yang bergerak di dunia ini.

ARSCNView tidak melakukan pemrosesan AR sendiri, tetapi memerlukan objek sesi AR yang mengelola kamera perangkat dan pemrosesan gerakan. Jadi, untuk memulai, kita perlu menetapkan sesi baru:

 self.session = ARSession() sceneView.session = session sceneView.delegate = self setupFocusSquare()

Baris terakhir di atas menambahkan indikator visual yang membantu pengguna secara visual dalam menggambarkan status deteksi pesawat. Focus Square disediakan oleh kode sampel, bukan perpustakaan ARKit, dan itu adalah salah satu alasan utama kami memulai dengan kode sampel ini. Anda dapat menemukan lebih banyak tentangnya di file readme yang disertakan dalam kode sampel. Gambar berikut menunjukkan persegi fokus yang diproyeksikan pada tabel:

Persegi fokus diproyeksikan di atas meja menggunakan Apple ARKit

Langkah selanjutnya adalah memulai sesi ARKit. Masuk akal untuk memulai kembali sesi setiap kali tampilan muncul karena kami tidak dapat menggunakan informasi sesi sebelumnya jika kami tidak melacak pengguna lagi. Jadi, kita akan memulai sesi di viewDidAppear:

 override func viewDidAppear(_ animated: Bool) { let configuration = ARWorldTrackingSessionConfiguration() configuration.planeDetection = .horizontal session.run(configuration, options: [.resetTracking, .removeExistingAnchors]) }

Pada kode di atas, kita mulai dengan mengatur konfigurasi sesi ARKit untuk mendeteksi bidang horizontal. Saat menulis artikel ini, Apple tidak menyediakan opsi selain ini. Namun ternyata, itu mengisyaratkan untuk mendeteksi objek yang lebih kompleks di masa depan. Kemudian, kami mulai menjalankan sesi dan memastikan kami mengatur ulang pelacakan.

Terakhir, kita perlu memperbarui Focus Square setiap kali posisi kamera, yaitu, orientasi atau posisi perangkat yang sebenarnya, berubah. Ini dapat dilakukan dalam fungsi delegasi penyaji SCNView, yang dipanggil setiap kali bingkai baru dari mesin 3D akan dirender:

 func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { updateFocusSquare() }

Pada titik ini, jika Anda menjalankan aplikasi, Anda akan melihat kotak fokus di atas aliran kamera yang mencari bidang horizontal. Di bagian berikutnya, kami akan menjelaskan bagaimana bidang terdeteksi, dan bagaimana kami dapat memposisikan kotak fokus yang sesuai.

Mendeteksi Pesawat di ARKit

ARKit dapat mendeteksi pesawat baru, memperbarui yang sudah ada, atau menghapusnya. Untuk menangani bidang dengan cara yang praktis, kami akan membuat beberapa simpul SceneKit dummy yang menyimpan informasi posisi bidang dan referensi ke kotak fokus. Bidang didefinisikan dalam arah X dan Z, di mana Y adalah normal permukaan, yaitu, kita harus selalu menjaga posisi simpul gambar kita dalam nilai Y yang sama dari bidang jika kita ingin membuatnya terlihat seolah-olah dicetak pada bidang .

Deteksi pesawat dilakukan melalui fungsi panggilan balik yang disediakan oleh ARKit. Misalnya, fungsi panggilan balik berikut dipanggil setiap kali pesawat baru terdeteksi:

 var planes = [ARPlaneAnchor: Plane]() func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { if let planeAnchor = anchor as? ARPlaneAnchor { serialQueue.async { self.addPlane(node: node, anchor: planeAnchor) self.virtualObjectManager.checkIfObjectShouldMoveOntoPlane(anchor: planeAnchor, planeAnchorNode: node) } } } func addPlane(node: SCNNode, anchor: ARPlaneAnchor) { let plane = Plane(anchor) planes[anchor] = plane node.addChildNode(plane) } ... class Plane: SCNNode { var anchor: ARPlaneAnchor var focusSquare: FocusSquare? init(_ anchor: ARPlaneAnchor) { self.anchor = anchor super.init() } ... }

Fungsi callback memberi kita dua parameter, anchor dan node . node adalah node SceneKit normal yang ditempatkan pada posisi dan orientasi bidang yang tepat. Ia tidak memiliki geometri, sehingga tidak terlihat. Kami menggunakannya untuk menambahkan simpul bidang kami sendiri, yang juga tidak terlihat, tetapi menyimpan informasi tentang orientasi bidang dan posisi di anchor .

Jadi bagaimana posisi dan orientasi disimpan di ARPlaneAnchor ? Posisi, orientasi, dan skala semuanya dikodekan dalam matriks 4x4. Jika saya memiliki kesempatan untuk memilih satu konsep matematika untuk Anda pelajari, itu pasti akan menjadi matriks. Bagaimanapun, kita dapat menghindarinya dengan menjelaskan matriks 4x4 ini sebagai berikut: Array 2 dimensi brilian yang berisi angka floating point 4x4. Dengan mengalikan angka-angka ini dengan cara tertentu dengan simpul 3D, v1, di ruang lokalnya, itu menghasilkan simpul 3D baru, v2, yang mewakili v1 di ruang dunia. Jadi, jika v1 = (1, 0, 0) dalam ruang lokalnya, dan kita ingin menempatkannya di x = 100 dalam ruang dunia, v2 akan sama dengan (101, 0, 0) terhadap ruang dunia. Tentu saja, matematika di balik ini menjadi lebih kompleks ketika kita menambahkan rotasi tentang sumbu, tetapi kabar baiknya adalah bahwa kita dapat melakukannya tanpa memahaminya (saya sangat menyarankan untuk memeriksa bagian yang relevan dari artikel yang luar biasa ini untuk penjelasan mendalam tentang konsep ini. ).

checkIfObjectShouldMoveOntoPlane memeriksa apakah kita sudah memiliki objek yang digambar dan memeriksa apakah sumbu y dari semua objek ini cocok dengan bidang yang baru terdeteksi.

Sekarang, kembali ke updateFocusSquare() , yang dijelaskan di bagian sebelumnya. Kami ingin mempertahankan kotak fokus di tengah layar, tetapi diproyeksikan pada bidang terdekat yang terdeteksi. Kode di bawah ini menunjukkan ini:

 func updateFocusSquare() { let worldPos = worldPositionFromScreenPosition(screenCenter, self.sceneView) self.focusSquare?.simdPosition = worldPos } func worldPositionFromScreenPosition(_ position: CGPoint, in sceneView: ARSCNView) -> float3? { let planeHitTestResults = sceneView.hitTest(position, types: .existingPlaneUsingExtent) if let result = planeHitTestResults.first { return result.worldTransform.translation } return nil }

sceneView.hitTest mencari pesawat dunia nyata yang sesuai dengan titik 2D di tampilan layar dengan memproyeksikan titik 2D ini ke bidang terdekat di bawahnya. result.worldTransform adalah matriks 4x4 yang menyimpan semua informasi transformasi bidang yang terdeteksi, sedangkan result.worldTransform.translation adalah fungsi praktis yang mengembalikan posisi saja.

Sekarang, kami memiliki semua informasi yang kami butuhkan untuk menjatuhkan objek 3D pada permukaan yang terdeteksi dengan titik 2D di layar. Jadi, mari kita mulai menggambar.

Menggambar

Mari kita jelaskan pendekatan menggambar bentuk yang mengikuti jari manusia dalam computer vision. Menggambar bentuk dilakukan dengan mendeteksi setiap lokasi baru untuk jari yang bergerak, menjatuhkan titik di lokasi tersebut, dan menghubungkan setiap titik dengan titik sebelumnya. Simpul dapat dihubungkan dengan garis sederhana, atau melalui kurva Bezier jika kita membutuhkan keluaran yang halus.

Untuk kesederhanaan, kita akan mengikuti sedikit pendekatan naif untuk menggambar. Untuk setiap lokasi jari yang baru, kami akan menjatuhkan kotak yang sangat kecil dengan sudut membulat dan ketinggian hampir nol pada denah yang terdeteksi. Ini akan muncul seolah-olah itu adalah titik. Setelah pengguna selesai menggambar dan memilih tombol 3D, kami akan mengubah ketinggian semua objek yang dijatuhkan berdasarkan gerakan jari pengguna.

Kode berikut menunjukkan kelas PointNode yang mewakili sebuah titik:

 let POINT_SIZE = CGFloat(0.003) let POINT_HEIGHT = CGFloat(0.00001) class PointNode: SCNNode { static var boxGeo: SCNBox? override init() { super.init() if PointNode.boxGeo == nil { PointNode.boxGeo = SCNBox(width: POINT_SIZE, height: POINT_HEIGHT, length: POINT_SIZE, chamferRadius: 0.001) // Setup the material of the point let material = PointNode.boxGeo!.firstMaterial material?.lightingModel = SCNMaterial.LightingModel.blinn material?.diffuse.contents = UIImage(named: "wood-diffuse.jpg") material?.normal.contents = UIImage(named: "wood-normal.png") material?.specular.contents = UIImage(named: "wood-specular.jpg") } let object = SCNNode(geometry: PointNode.boxGeo!) object.transform = SCNMatrix4MakeTranslation(0.0, Float(POINT_HEIGHT) / 2.0, 0.0) self.addChildNode(object) } . . . }

Anda akan melihat dalam kode di atas bahwa kami menerjemahkan geometri sepanjang sumbu y dengan setengah tinggi. Alasan untuk ini adalah untuk memastikan bahwa bagian bawah objek selalu di y = 0 , sehingga muncul di atas bidang.

Selanjutnya, dalam fungsi callback renderer SceneKit, kita akan menggambar beberapa indikator yang bertindak seperti titik ujung pena, menggunakan kelas PointNode yang sama. Kami akan menjatuhkan titik di lokasi itu jika menggambar diaktifkan, atau menaikkan gambar menjadi struktur 3D jika mode 3D diaktifkan:

 func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { updateFocusSquare() // Setup a dot that represents the virtual pen's tippoint if (self.virtualPenTip == nil) { self.virtualPenTip = PointNode(color: UIColor.red) self.sceneView.scene.rootNode.addChildNode(self.virtualPenTip!) } // Draw if let screenCenterInWorld = worldPositionFromScreenPosition(self.screenCenter, self.sceneView) { // Update virtual pen position self.virtualPenTip?.isHidden = false self.virtualPenTip?.simdPosition = screenCenterInWorld // Draw new point if (self.inDrawMode && !self.virtualObjectManager.pointNodeExistAt(pos: screenCenterInWorld)){ let newPoint = PointNode() self.sceneView.scene.rootNode.addChildNode(newPoint) self.virtualObjectManager.loadVirtualObject(newPoint, to: screenCenterInWorld) } // Convert drawing to 3D if (self.in3DMode ) { if self.trackImageInitialOrigin != nil { DispatchQueue.main.async { let newH = 0.4 * (self.trackImageInitialOrigin!.y - screenCenterInWorld.y) / self.sceneView.frame.height self.virtualObjectManager.setNewHeight(newHeight: newH) } } else { self.trackImageInitialOrigin = screenCenterInWorld } } }

virtualObjectManager adalah kelas yang mengelola poin yang ditarik. Dalam mode 3D, kami memperkirakan perbedaan dari posisi terakhir dan menambah/mengurangi ketinggian semua titik dengan nilai itu.

Sampai sekarang, kami menggambar pada permukaan yang terdeteksi dengan asumsi pena virtual berada di tengah layar. Sekarang untuk bagian yang menyenangkan—mendeteksi jari pengguna dan menggunakannya sebagai ganti pusat layar.

Mendeteksi Ujung Jari Pengguna

Salah satu library keren yang diperkenalkan Apple di iOS 11 adalah Vision Framework. Ini menyediakan beberapa teknik visi komputer dengan cara yang cukup praktis dan efisien. Secara khusus, kita akan menggunakan teknik pelacakan objek untuk tutorial augmented reality kita. Pelacakan objek berfungsi sebagai berikut: Pertama, kami menyediakannya dengan gambar dan koordinat persegi di dalam batas gambar untuk objek yang ingin kami lacak. Setelah itu kami memanggil beberapa fungsi untuk menginisialisasi pelacakan. Akhirnya, kami memasukkan gambar baru di mana posisi objek itu berubah dan hasil analisis dari operasi sebelumnya. Mengingat itu, itu akan mengembalikan lokasi baru objek bagi kita.

Kami akan menggunakan trik kecil. Kami akan meminta pengguna untuk meletakkan tangan mereka di atas meja seolah-olah mereka sedang memegang pena, dan untuk memastikan gambar mini mereka menghadap kamera, setelah itu mereka harus mengetuk gambar mini di layar. Ada dua poin yang perlu dijabarkan di sini. Pertama, thumbnail harus memiliki fitur unik yang cukup untuk dilacak melalui kontras antara thumbnail putih, kulit, dan tabel. Ini berarti bahwa pigmen kulit yang lebih gelap akan menghasilkan pelacakan yang lebih andal. Kedua, karena pengguna meletakkan tangan mereka di atas meja, dan karena kami telah mendeteksi meja sebagai bidang, memproyeksikan lokasi gambar mini dari tampilan 2D ke lingkungan 3D akan menghasilkan lokasi jari yang hampir tepat di atas meja. meja.

Gambar berikut menunjukkan titik fitur yang dapat dideteksi oleh perpustakaan Vision:

Poin Fitur iOS ARKit terdeteksi oleh perpustakaan Vision

Kami akan menginisialisasi pelacakan thumbnail dalam gerakan tap sebagai berikut:

 // MARK: Object tracking fileprivate var lastObservation: VNDetectedObjectObservation? var trackImageBoundingBox: CGRect? let trackImageSize = CGFloat(20) @objc private func tapAction(recognizer: UITapGestureRecognizer) { lastObservation = nil let tapLocation = recognizer.location(in: view) // Set up the rect in the image in view coordinate space that we will track let trackImageBoundingBoxOrigin = CGPoint(x: tapLocation.x - trackImageSize / 2, y: tapLocation.y - trackImageSize / 2) trackImageBoundingBox = CGRect(origin: trackImageBoundingBoxOrigin, size: CGSize(width: trackImageSize, height: trackImageSize)) let t = CGAffineTransform(scaleX: 1.0 / self.view.frame.size.width, y: 1.0 / self.view.frame.size.height) let normalizedTrackImageBoundingBox = trackImageBoundingBox!.applying(t) // Transfrom the rect from view space to image space guard let fromViewToCameraImageTransform = self.sceneView.session.currentFrame?.displayTransform(withViewportSize: self.sceneView.frame.size, orientation: UIInterfaceOrientation.portrait).inverted() else { return } var trackImageBoundingBoxInImage = normalizedTrackImageBoundingBox.applying(fromViewToCameraImageTransform) trackImageBoundingBoxInImage.origin.y = 1 - trackImageBoundingBoxInImage.origin.y // Image space uses bottom left as origin while view space uses top left lastObservation = VNDetectedObjectObservation(boundingBox: trackImageBoundingBoxInImage) }

Bagian tersulit di atas adalah bagaimana mengubah lokasi tap dari ruang koordinat UIView ke ruang koordinat gambar. ARKit memberi kita matriks displayTransform yang mengonversi dari ruang koordinat gambar ke ruang koordinat viewport, tetapi tidak sebaliknya. Jadi bagaimana kita bisa melakukan kebalikannya? Dengan menggunakan invers matriks. Saya benar-benar mencoba meminimalkan penggunaan matematika dalam posting ini, tetapi terkadang tidak dapat dihindari di dunia 3D.

Selanjutnya, di penyaji, kami akan memasukkan gambar baru untuk melacak lokasi baru jari:

 func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { // Track the thumbnail guard let pixelBuffer = self.sceneView.session.currentFrame?.capturedImage, let observation = self.lastObservation else { return } let request = VNTrackObjectRequest(detectedObjectObservation: observation) { [unowned self] request, error in self.handle(request, error: error) } request.trackingLevel = .accurate do { try self.handler.perform([request], on: pixelBuffer) } catch { print(error) } . . . }

Setelah pelacakan objek selesai, itu akan memanggil fungsi panggilan balik di mana kami akan memperbarui lokasi thumbnail. Ini biasanya kebalikan dari kode yang ditulis dalam pengenal ketuk:

 fileprivate func handle(_ request: VNRequest, error: Error?) { DispatchQueue.main.async { guard let newObservation = request.results?.first as? VNDetectedObjectObservation else { return } self.lastObservation = newObservation var trackImageBoundingBoxInImage = newObservation.boundingBox // Transfrom the rect from image space to view space trackImageBoundingBoxInImage.origin.y = 1 - trackImageBoundingBoxInImage.origin.y guard let fromCameraImageToViewTransform = self.sceneView.session.currentFrame?.displayTransform(withViewportSize: self.sceneView.frame.size, orientation: UIInterfaceOrientation.portrait) else { return } let normalizedTrackImageBoundingBox = trackImageBoundingBoxInImage.applying(fromCameraImageToViewTransform) let t = CGAffineTransform(scaleX: self.view.frame.size.width, y: self.view.frame.size.height) let unnormalizedTrackImageBoundingBox = normalizedTrackImageBoundingBox.applying(t) self.trackImageBoundingBox = unnormalizedTrackImageBoundingBox // Get the projection if the location of the tracked image from image space to the nearest detected plane if let trackImageOrigin = self.trackImageBoundingBox?.origin { self.lastFingerWorldPos = self.virtualObjectManager.worldPositionFromScreenPosition(CGPoint(x: trackImageOrigin.x - 20.0, y: trackImageOrigin.y + 40.0), in: self.sceneView) } } }

Terakhir, kita akan menggunakan self.lastFingerWorldPos alih-alih pusat layar saat menggambar, dan selesai.

ARKit dan Masa Depan

Dalam posting ini, kami telah mendemonstrasikan bagaimana AR dapat menjadi imersif melalui interaksi dengan jari pengguna dan tabel kehidupan nyata. Dengan lebih banyak kemajuan dalam visi komputer, dan dengan menambahkan lebih banyak perangkat keras ramah AR ke gadget (seperti kamera kedalaman), kita bisa mendapatkan akses ke struktur 3D dari lebih banyak objek di sekitar kita.

Meski belum dirilis ke publik, patut disebutkan bagaimana Microsoft sangat serius untuk memenangkan perlombaan AR melalui perangkat Hololens-nya, yang menggabungkan perangkat keras yang dirancang khusus untuk AR dengan teknik pengenalan lingkungan 3D yang canggih. Anda dapat menunggu untuk melihat siapa yang akan memenangkan perlombaan ini, atau Anda dapat menjadi bagian darinya dengan mengembangkan aplikasi augmented reality yang imersif sekarang! Tapi tolong, bantulah umat manusia dan jangan mengubah benda hidup menjadi kelinci.