Swift-də genişləndirilmiş reallığa başlamağın asan yolu

Ətrafınıza baxsanız, bu texnologiyanın qızıl dövrüdür. Hər bir açar sözlə, mövcud texnologiya yığını yeni bir şeylə genişləndirilir. Bu yeni texnologiyaların təsəvvür sərhədlərimizi necə aşdığını görmək çox həyəcanlıdır. İnkişaf edənlər olaraq bu texnologiyalardan özümüz istifadə etdiyimiz üçün fəxr etməliyik.

Ancaq hər yeni texnologiya olduqca dik bir öyrənmə əyrisi ilə gəlir. Youtube-da bir açar söz və ya video izləyə və bir proqram inkişaf etdirməyə başlaya bilməzsən. Ancaq yaxşı xəbər odur ki, Swift-də AR ilə əsas AR tətbiqetmələri ilə işləmək qəribə dərəcədə asandır. Ağır daşımaların çoxunu Apple sizin üçün etdi. Bizi izləyin və bunun nə qədər asan ola biləcəyini görəcəksiniz.

Bir az araşdırma aparaq ...

Bu dərsdə, döşəmənizi bəzi sərin döşəmə plitələri və taxta toxumaları ilə bəzəyəcək bir tətbiqetmə yaratmaq üçün istifadə edə biləcəyimiz Swift-də lazımlı AR alətləri və texnikaları haqqında məlumat əldə edəcəyik. Bitmiş tətbiqetmə belə görünür:

Xcode-da tək bir baxış tətbiqi yaratmağa və onu Ev Dekorası adlandırmağa başlayaq.

Kamera icazələrini əlavə edin

Əvvəlcə info.plist faylına gedirik və kameradan istifadəni aktivləşdiririk. Kamera qabiliyyəti bir AR tətbiqində ehtiyacınız olan ilk şeydir. Aşağıdakı şəkildəki kimi kameradan istifadə təsviri üçün açarı tapın və uyğun bir mesaj verin. Bu mesaj istifadəçidən kamera icazəsi istəyərkən tətbiqetmə ilk dəfə işə salındıqda göstərilir.

Tətbiqə ARKit xüsusiyyətləri əlavə olunur

Əsas baxışa keçin. ARKit SceneKit görünüşünü ViewController üzərinə sürüşdürün və ViewController kənarlarına əlavə edin.

ViewController sinfi üçün bir IBOutlet yaradın və adını sceneView qoyun. Etdiyiniz anda, görünüş nəzarətçimiz ARSCNView tipli bir şey tanımadığına görə ARSCNView-un elan edilmədiyini göstərən bir səhv görəcəksiniz. Bunu düzəltmək və digər ARKit xüsusiyyətlərindən istifadə etmək üçün ARKit'i Baxış Denetleyicisinə idxal etməlisiniz.

İndi storyboard-dan view controller.swift faylına keçin. ViewDidLoad () metodunun qarşısında ARWorldTrackingConfiguration tipli bir xüsusiyyət elan edin və konfiqurasiya edin. Və görünüş nəzarətçimiz belə görünür (didReceiveMemoryWarning metodu silindi):

İdxal UIKit ARKit idxal edin
ViewController sinfi: UIViewController {
@IBOutlet zəif var sceneView: ARSCNView! edək config = ARWorldTrackingConfiguration ()
Func viewDidLoad () {super.viewDidLoad ()} -ı ləğv et

Ayıklamaya icazə verin

Bu konfiqurasiya dəyişən səhnə sessiyasının konfiqurasiyasını təyin edir. Bu bölmədə daha sonra istifadəsini görəcəyik. İndi super.viewDidLoad () sonra viewDidLoad metoduna aşağıdakıları əlavə edin:

sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]

Burada, SceneView üçün AR çərçivəsinin funksiyaları ilə kamera görünüşündən başqa bir şey olmayan hata ayıklama seçimlərini aktivləşdiririk. ARSCNDebugOptions.showWorldOrigin ekranda dünya mənşəyini göstərir. Bu, bütün digər mövqelərin istinad nöqtəsini tapmaqda bizə kömək edir. ARSCNDebugOptions.showFeaturePoints, AR kamerasının ərazidə aşkarladığı bütün nöqtələri ekranda göstərir.

AR sessiyasına başlamaq üçün, SceneView-da konfiqurasiya dəyişənində göstərilən konfiqurasiyalarla bir sessiya aparmalıyıq. Birbaşa sceneView.debugOptions altında yazın:

sceneView.session.run (konfiqurasiya)

İndi tətbiqinizi cihazınızda işə salın (kamera olmadığı üçün simulyatorda deyil). Yazdığınız mesajda kamera icazə tələb edən xəbərdarlıq mesajı görünəcək və buna icazə verməlisiniz. Dünya mənşəli yüklənərkən bir az gözləyin.

Burada olduğunuz zaman AR tətbiqi artıq aktivdir. Təbrik edirik!

AR baltaları necə işləyir

Obyektlər qırmızı çubuq və ya X oxu ilə dünya mənşəli sola və ya sağa yerləşdirilir. Yaşıl çubuq və ya Y oxu, obyektləri dünya mənşəyinin yuxarı və ya aşağı hissəsində yerləşdirmək üçün istifadə olunur. Və mavi çubuq və ya Z oxu bir cisimin dünya mənşəyindən nə qədər yaxın və ya uzaqda yerləşdiyini təyin edir.

X-in müsbət dəyəri bir obyekti dünya mənşəyinin sağında, mənfi dəyəri isə solunda yerləşdirir. Y üçün müsbət dünya mənşəyində yuxarıda, mənfi aşağıda yerləşdirir. Z üçün pozitiv onu daha yaxın, mənfi isə dünya mənşəyindən daha uzaqda yerləşdirəcəkdir.

Virtual obyekt əlavə olunur

Səhnəyə bəzi virtual obyektlər əlavə edək. 3D kapsul yaxşı bir seçim olardı. SCNNode tipli bir kapsulNodu elan edin və ona bir kapsul həndəsi verin. 0,1 metr hündürlüyə və 0,03 metr radiusa daxil olun.

CapsuleNode = SCNNode tərk edin (həndəsə: SCNCapsule (capRadius: 0.03, hündürlük: 0.1

İndi dünya mənşəyindən 0,1 metr sola, dünya mənşəyindən 0,1 metr və dünya mənşəyindən 0,1 metr yuxarıda yerləşdirin:

capsuleNode.position = SCNVector3 (0.1, 0.1, -0.1)

İndi səhnəyə qovşaq əlavə edin:

sceneView.scene.rootNode.addChildNode (capsuleNode)

Səhnə görünüşü, 3D səhnəni təşkil edən SCNNode formatında bütün 3B obyektlərin saxlanmasından məsul olan bir səhnəni ehtiva edir. Kapsülü səhnənin kök düyününə əlavə edirik. Kök düyününün mövqeyi dünya mənşəli mövqeylə tam uyğunlaşdırılır. Yəni mövqeyi (0,0,0).

Hal-hazırda viewDidLoad metodumuz belə görünür:

Func viewDidLoad () {-ı ləğv et
super.viewDidLoad ()
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
sceneView.session.run (konfiqurasiya)
capsuleNode = SCNNode edək (həndəsə: SCNCapsule (capRadius: 0.03, hündürlük: 0.1))
capsuleNode.position = SCNVector3 (0.1, 0.1, -0.1)
sceneView.scene.rootNode.addChildNode (capsuleNode)
}

İndi tətbiqi işə salın.

Sərin! Bir az əvvəl real dünyada bir virtual obyekt yerləşdirdik. Daha çoxunu tapmaq üçün fərqli mövqelər və həndəsələr ilə oynaya bilərsiniz. İndi kapsulu Z oxu ətrafında 90 dərəcə döndərək ki, X oxunda düz uzansın və rəngi göyə dəyişsin.

Euler bucağı

Euler açıları bir SCN düyününün ekran açısından məsuldur. Kapsülü çevirmək üçün necə istifadə edəcəyini görəcəyik.

Həndəsənin görünüşünü təyin etmək üçün hər SCNGeometriyaya materiallar əlavə edilə bilər. Materiallar, müəyyən edildikdə, məzmunu bütün həndəsə boyunca paylayan diffuz bir xüsusiyyətə malikdir.

ViewDidLoad-da kapsul vəziyyətini təyin etdikdən sonra aşağıdakı sətirləri əlavə edin.

capsuleNode.geometry? .birinci material? .diffuse.contents = UIColor.blue // 1 capsuleNode.eulerAngles = SCNVector3 (0,0, Double.pi / 2) // 2

Birinci sətirdə mavi rəngi kapsulun üstünə yayılacaq düyünün ilk materialına qoyduq və mavi göründü. 2-ci sətirdə Z-Euler bucağını 90 dərəcə radiana təyin etdik. Nəticədə görünüşümüz yüklənir və belə görünür:

Func viewDidLoad () {-ı ləğv et
super.viewDidLoad ()
sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
sceneView.session.run (konfiqurasiya)
capsuleNode = SCNNode edək (həndəsə: SCNCapsule (capRadius: 0.03, hündürlük: 0.1))
capsuleNode.position = SCNVector3 (0.1, 0.1, -0.1)
capsuleNode.geometry? .birinci material? .diffuse.contents = UIColor.blue // 1
capsuleNode.eulerAngles = SCNVector3 (0,0, Double.pi / 2) // 2
sceneView.scene.rootNode.addChildNode (capsuleNode)
}

İndi tətbiqi işə salın.

Əla! Divarda mavi bir yuxu kapsulu! Bir obyektin daha real görünməsi üçün dokuları diffuz məzmun olaraq əlavə edə bilərsiniz. Yerdəki plitələrin toxumalarını düzəndə növbəti hissədə bundan istifadə edəcəyik.

Artıq real aləmdə virtual obyektləri uğurla yerləşdirdiyimiz üçün həqiqi mərtəbəmizi virtual döşəmə plitələri ilə bəzəməyin vaxtı gəldi. Döşəmə effektinə nail olmaq üçün bir SCNPlane həndəsəsindən istifadə edirik. SCNPlane digər 3D həndəsələr kimi dərinliyə malik deyil və bu səbəbdən tətbiqimizə tamamilə uyğundur.

ARSCENEleqentləri nəzərdən keçirin

Yerin aşkarlanmasına başlamazdan əvvəl davam edən bir AR sessiyası ilə qarşılıqlı əlaqə qurmaq üçün hansı imkanlara malik olduğumuzu anlamaq üçün SceneView-in bəzi həvalə olunmuş metodlarını araşdıracağıq.

Funk-Renderer (SCNSceneRenderer, didAdd: SCNNode, for: ARAnchor)

Cihazımızı AR oturumu ilə hərəkət etdirdiyimiz və ya əydiyimiz zaman ARKit ərazidə fərqli ARAnchors tapmağa çalışır. ARAnchor, bir obyekt yerləşdirmək üçün istifadə edilə bilən həqiqi bir mövqe və istiqamət haqqında məlumat ehtiva edir.

Başqa bir lövbər tapıldıqdan sonra, yeni tapılan lövbərin yerləşməsi üçün hadisə yerinə eyni məlumatlarla yeni bir qovşaq əlavə olunur. Bu nümayəndə üsulu bizə məlumat verəcəkdir. Plitələri yerləşdirmək üçün yerdəki bütün mövqeləri tapmaq üçün istifadə edəcəyik.

func renderer (_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, anchor for: ARAnchor)

Əksər hallarda, lövbərlər tərəfindən əlavə edilmiş bütün qovşaqlar eyni obyektə aiddir. Məsələn, yer üzündə gəzdiyinizi və cihazın fərqli yerlərdə çox sayda lövbər tapdığını düşünün. Bu lövbərlərin hamısının fərqli obyektlərə aid olduğu güman edildiyi üçün bu lövbərlər üçün bütün qovşaqları əlavə etməyə cəhd ediləcəkdir.

Ancaq ARKit sonunda hamısının eyni mərtəbədə olduqlarını başa düşür. Buna görə, birinci mərtəbədəki qovşaq digər təkrarlanan qovşaqların ölçüləri əlavə olunmaqla yenilənir. Bu nümayəndə üsulu bizə məlumat verəcəkdir.

Funk-Renderer (SCNSceneRenderer, didRemove: SCNNode, for: ARAnchor)

İlk unikal düyünü bütün digər dublikat qovşaqlarının ölçüləri ilə yenilədikdən sonra ARKit bütün dublikat qovşaqlarını silir və Delegate metodu bizə xəbər verir. Tətbiqimizdə yuxarıdakı bütün nümayəndə metodlarından istifadə edəcəyik (və məqsədləri daha aydın olacaq).

Təyyarələrin aşkarlanması

Hal-hazırda səhnəmiz qarşılaşdığı bütün lövbərləri toplamağa çalışır, çünki bu, standart davranışdır. Bununla birlikdə, bir döşəmə üfüqi bir səth olduğundan, yalnız üfüqi düzlüklərdə olan lövbərlərlə maraqlanırıq. Buna görə viewDidLoad metodumuza qayıdın və sessiya sətirini çalıştırmadan əvvəl aşağıdakı kodu yazın (yəni sceneView.session.run (config) əvvəl).

config.planeDetection = .torizontal

ViewDidLoad metodunda, sceneView.session.run (config) -dan sonra, kapsulu ekranda yerləşdirmək üçün istifadə olunan hər şeyi silə bilərsiniz və artıq buna ehtiyacımız yoxdur. Yuxarıda göstərilən nümayəndə metodlarının hamısını istifadə edəcəyimiz üçün viewController-i sceneView-in nümayəndəsi etməliyik. Bağlama mötərizəsindən əvvəl aşağıdakı sətiri viewDidLoad () metoduna əlavə edin.

sceneView.delegate = özünü

Baxış nəzarətçimiz hələ sceneView nümayəndə ilə uyğunlaşmadığı üçün indi bir səhv almalısınız. Bunu həyata keçirmək üçün ViewController.swift faylının sonunda Görünüş Denetleyicisinin bir uzantısı yaradacağıq.

Genişləndirmə ViewController: ARSCNViewDelegate {}

DidAdd SCNNode nümayəndə metodu döşəmənin hər hissəsi aşkar edildikdə işə salınır və lövbər əsasında səhnəyə yeni bir qovşaq əlavə olunur. Bu metod daxilində bir torpaq düyünü yaradacağıq və lövbər yerində bu yaxınlarda əlavə edilmiş düyünün uşağı olaraq əlavə edəcəyik.

ARArchor, dörd fərqli məqsədə xidmət etmək üçün dörd fərqli növ ola bilər. Bizi yalnız yatay və ya şaquli təyyarələri tanıyan ARPlaneAnchor maraqlandırır.

AR yer düyünləri yaradın

Bir ARPlaneAnchor'u parametr olaraq qəbul edən bir funksiya yarataq, lövbər yerində bir torpaq düyünü yaradıb qaytardıq.

func createFloorNode (çapa: ARPlaneAnchor) -> SCNNode {
floorNode = SCNNode edək (həndəsə: SCNPlane (eni: CGFloat (anchor.extent.x), hündürlüyü: CGFloat (anchor.extent.z)) // 1
floorNode.position = SCNVector3 (anchor.center.x, 0, anchor.center.z) // 2
floorNode.geometry? .birinci material? .diffuse.contents = UIColor.blue // 3
floorNode.geometry? .birinci material? .isDoubleSided = true // 4
floorNode.eulerAngles = SCNVector3 (Double.pi / 2,0,0) // 5
return floorNode // 6
}

Funksiya sətir-sinə keçək və daha ətraflı müzakirə edək. Xahiş edirəm hər sətrin təsvirini izləyin, çünki bu ən çətin hissədir.

1. SCNPlane-dən çapa ölçüsündə bir həndəsə ilə bir qovşaq yaradırıq. ARPlaneAnchor həcmi mövqe məlumatlarını ehtiva edir. Extent.z-nin Extent.y-dən yüksəklik olaraq istifadə edilməsi bir az qarışıq ola bilər. Bir 3D kubun bir yerə qoyulduğunu xəyal edirsinizsə və 2 ölçülü bir səth boyunca düz olmasını istəyirsinizsə, y-ı sıfıra dəyişdirin və düz olacaq. Bu 2D səthin uzunluğunu tapmaq üçün Z-ni nəzərə almalısan, elə deyilmi? Dibimiz düzdür, buna görə bir küpə deyil, düz bir düyünə ehtiyacımız var.

2. Düyünün mövqeyini təyin etdik. Zərbə ehtiyacımız olmadığından, y sıfır edək.

3. Döşəmə rəngini mavi rəngə qoyun.

4. Maddi rəng yalnız ikitərəfli olduğunu xüsusi qeyd etmədikdə yalnız bir tərəfdə göstərilir.

5. Varsayılan olaraq qat şaquli olaraq yerləşdirilir. Yatay vəziyyətə gətirmək üçün onu 90 dərəcə döndərməliyik.

Nümayəndə üsullarını tətbiq edin

İndi didAdd SCNNode nümayəndə metodunu tətbiq edək.

func renderer (_ renderer: SCNSceneRenderer, didAdd node: SCNNode, anchor for: ARAnchor) {
Çapa təyyarəsi = çapa kimi? ARPlaneAnchor else {return} // 1
qoyın planeNode = createFloorNode (anchor: planeAnchor) // 2
node.addChildNode (planeNode) // 3
}

1-ci sətirdə lövbərin ARPlaneAnchor olub olmadığını yoxlayırıq, çünki yalnız bu tip lövbərə baxırıq.

2-ci sətirdə lövbərə əsaslanan yeni bir qovşaq yaradılır. 3-cü sətirdə düyünə əlavə olunur.

İndi didUpdate SCNNode nümayəndə heyətindəki bütün əsas qovşaqlarımızı siləcəyik. Bunu cari düyünün ölçüləri dəyişdiyindən və köhnə torpaq düyünləri üst-üstə düşmədiyindən edirik. Sonra bu yenilənmiş düyünə yenidən yeni bir torpaq nodu əlavə edirik.

func renderer (_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, anchor for: ARAnchor) {
Çapa təyyarəsi = çapa kimi? ARPlaneAnchor else {return}
node.enumerateChildNodes {(node, _) in
node.removeFromParentNode ()
}
qoyın planeNode = createFloorNode (anchor: planeAnchor)
node.addChildNode (təyyarəNode)
}

DidRemove SCNNode nümayəndə üsulunda, bütün lazımsız qovşaqları mədəni bir şəkildə təmizləmək istəyirik.

func renderer (_ renderer: SCNSceneRenderer, didRemove node: SCNNode, anchor for: ARAnchor) {
Keşikçi icazə verin = = çapa qoyun? ARPlaneAnchor else {return}
node.enumerateChildNodes {(node, _) in
node.removeFromParentNode ()
}
}

Oğlum! Bu belədir! Tətbiqi işə salın.

Çini effekti əlavə olunur

Nə gözləyin Mavi mərtəbə? Xeyr, hələ tam bitməmişik. Yalnız bir kiçik dəyişiklik və biz çarpıcı döşəmə olacaq!

Mavi döşəməni plitələrə çevirmək üçün bir toxuma lazımdır. Döşəmə kafel toxumasını tapaq. "Taxta döşəmə toxuması" axtardım və bir neçə gözəl toxuma şəkli tapdım. Bunlardan birini Mac-də saxla və Assets.xcassets-ə sürükləyin.

Buna WoodenFloorTile adını verdim. İstədiyiniz kimi adlandıra bilərsiniz. ViewController.swift sənədinə qayıdın. CreateFloorNode funksiyasında, UIColor.blue-u diffuz məzmun olaraq təyin edə bilməzsiniz, ancaq aktiv qovluğunda şəkli verdiyiniz adla UIImage olaraq təyin edə bilərsiniz.

floorNode.geometry? .birinci material? .diffuse.contents = UIImage (ad: "WoodenFloorTile")

İndi tətbiqi çalıştırın və dünya mənşəli yüklənməsini gözləyin. Torpaq aşkar edildikdən sonra, qovşaq məlumatlarını yeniləmək üçün hərəkət edin.

Vay, həqiqətən gözəl bir döşəmən var! Birdən çox doku yükləyə və ListView-a yerləşdirə bilərsiniz. Bu şəkildə birinci hissədə göstərildiyi kimi seçdiyiniz toxuma əsasən zəmini dəyişdirə bilərsiniz.

GitHub-dan tam layihəni buradan yükləyin.

Artıq gözəl bir döşəməyə sahib olduğunuz üçün otağınıza mükəmməl bir görünüş qatmaq üçün bir neçə gözəl mebeldən məhrum olmalısınız! Bu barədə daha sonra işləyəcəyik.