แสดงสถานที่ใกล้เคียงใน AR บน Android (Kotlin)

1. ข้อควรทราบก่อนที่จะเริ่มต้น

นามธรรม

Codelab นี้จะสอนวิธีใช้ข้อมูลจาก Google Maps Platform เพื่อแสดงสถานที่ใกล้เคียงใน Augmented Reality (AR) บน Android

2344909dd9a52c60.png

สิ่งที่ต้องมีก่อน

  • ความเข้าใจเบื้องต้นเกี่ยวกับการพัฒนา Android โดยใช้ Android Studio
  • ทําความคุ้นเคยกับ Kotlin

สิ่งที่จะได้เรียนรู้

  • ขออนุญาตจากผู้ใช้ให้เข้าถึงกล้องและตําแหน่งของอุปกรณ์
  • ผสานรวมกับ Places API เพื่อดึงข้อมูลสถานที่ใกล้เคียงรอบๆ ตําแหน่งของอุปกรณ์
  • ผสานรวมกับ ARCore เพื่อค้นหาพื้นผิวของระนาบแนวนอนเพื่อให้วัตถุเสมือนสามารถยึดติดและวางไว้ในพื้นที่ 3 มิติได้โดยใช้ Sceneform
  • รวบรวมข้อมูลเกี่ยวกับตําแหน่งของอุปกรณ์ในพื้นที่โดยใช้ SensorManager และใช้ Maps SDK สําหรับไลบรารียูทิลิตีของ Android เพื่อวางออบเจ็กต์เสมือนในส่วนหัวที่ถูกต้อง

สิ่งที่ต้องมี

2. ตั้งค่า

Android Studio

Codelab นี้ใช้ Android 10.0 (API ระดับ 29) และกําหนดให้คุณต้องติดตั้งบริการ Google Play ใน Android Studio หากต้องการติดตั้งทรัพยากร Dependency ทั้ง 2 รายการนี้ ให้ทําตามขั้นตอนต่อไปนี้

  1. ไปที่ SDK Manager ซึ่งเข้าถึงได้โดยคลิกเครื่องมือ &gt SDK SDK

6c44a9cb9cf6c236.png

  1. ตรวจสอบว่าติดตั้ง Android 10.0 หรือไม่ หากไม่ ให้ติดตั้งโดยเลือกช่องทําเครื่องหมายถัดจาก Android 10.0 (Q) แล้วคลิกตกลง และสุดท้าย ให้คลิกตกลงอีกครั้งในกล่องโต้ตอบที่ปรากฏ

368f17a974c75c73.png

  1. สุดท้าย ติดตั้งบริการ Google Play โดยไปที่แท็บเครื่องมือ SDK เลือกช่องทําเครื่องหมายถัดจากบริการ Google Play คลิกตกลง จากนั้นเลือกตกลงอีกครั้งในกล่องโต้ตอบที่ปรากฏ****

497a954b82242f4b.png

API ที่จําเป็น

ในขั้นตอนที่ 3 ของส่วนต่อไปนี้ ให้เปิดใช้ Maps SDK สําหรับ Android และ Places API สําหรับ Codelab นี้

เริ่มต้นใช้งาน Google Maps Platform

หากคุณไม่เคยใช้ Google Maps Platform มาก่อน ให้ทําตามคู่มือเริ่มต้นใช้งาน Google Maps Platform หรือดูเพลย์ลิสต์การเริ่มต้นใช้งาน Google Maps Platform เพื่อทําตามขั้นตอนต่อไปนี้

  1. สร้างบัญชีสําหรับการเรียกเก็บเงิน
  2. สร้างโปรเจ็กต์
  3. เปิดใช้ Google Maps Platform API และ SDK (แสดงอยู่ในส่วนก่อนหน้า)
  4. สร้างคีย์ API

ไม่บังคับ: โปรแกรมจําลองของ Android

หากคุณไม่มีอุปกรณ์ที่รองรับ ARCore อีกทางเลือกหนึ่งคือใช้โปรแกรมจําลอง Android เพื่อจําลองโหมด AR รวมถึงปลอมแปลงตําแหน่งของอุปกรณ์ก็ได้ เนื่องจากคุณจะใช้ Sceneform ในการออกกําลังกายนี้ด้วย จึงต้องทําตามขั้นตอนต่างๆ ใน &quot และกําหนดค่าโปรแกรมจําลองให้รองรับ Sceneform &&tt

3. การเริ่มใช้งานอย่างง่าย

ในการเริ่มต้น ให้ใช้โค้ดต่อไปนี้เป็นโค้ดเริ่มต้นเพื่อช่วยคุณติดตาม Codelab นี้ได้อย่างรวดเร็ว คุณข้ามไปที่โซลูชันนี้ได้ แต่หากต้องการดูทุกขั้นตอน โปรดอ่านต่อไป

คุณโคลนที่เก็บได้หากติดตั้ง git ไว้

git clone https://github.com/googlecodelabs/display-nearby-places-ar-android.git

หรือคุณจะคลิกปุ่มด้านล่างเพื่อดาวน์โหลดซอร์สโค้ดก็ได้

เมื่อได้รับรหัสแล้ว ให้เปิดโปรเจ็กต์ที่พบในไดเรกทอรี starter

4. ภาพรวมโครงการ

สํารวจโค้ดที่คุณดาวน์โหลดจากขั้นตอนก่อนหน้า ในที่เก็บนี้ คุณจะเห็นโมดูลเดี่ยวที่ชื่อ app ซึ่งมีแพ็กเกจ com.google.codelabs.findnearbyplacesar

AndroidManifest.xml

มีการประกาศแอตทริบิวต์ต่อไปนี้ในไฟล์ AndroidManifest.xml เพื่อให้คุณใช้ฟีเจอร์ที่จําเป็นใน Codelab นี้ได้

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Sceneform requires OpenGL ES 3.0 or later. -->
<uses-feature
   android:glEsVersion="0x00030000"
   android:required="true" />

<!-- Indicates that app requires ARCore ("AR Required"). Ensures the app is visible only in the Google Play Store on devices that support ARCore. For "AR Optional" apps remove this line. -->
<uses-feature android:name="android.hardware.camera.ar" />

สําหรับ uses-permission ซึ่งจะระบุว่าต้องให้สิทธิ์ใดแก่ผู้ใช้ก่อน ผู้ใช้ดังกล่าวจึงจะใช้สิทธิ์เหล่านี้ได้

  • android.permission.INTERNET การกําหนดเป้าหมายนี้จะทําให้แอปสามารถดําเนินการเกี่ยวกับเครือข่ายและดึงข้อมูลผ่านอินเทอร์เน็ตได้ เช่น ข้อมูลสถานที่ผ่าน Places API
  • android.permission.CAMERA - ต้องมีสิทธิ์เข้าถึงกล้องเพื่อให้คุณใช้กล้องของอุปกรณ์เพื่อแสดงวัตถุใน Augmented Reality ได้
  • android.permission.ACCESS_FINE_LOCATION - ต้องใช้การเข้าถึงตําแหน่ง คุณสามารถดึงข้อมูลสถานที่ใกล้เคียงซึ่งสัมพันธ์กับตําแหน่งของอุปกรณ์ได้

สําหรับ uses-feature ซึ่งระบุฟีเจอร์ฮาร์ดแวร์ที่แอปนี้ต้องใช้ ระบบจะประกาศข้อมูลต่อไปนี้

  • ต้องใช้ OpenGL ES เวอร์ชัน 3.0
  • ต้องใช้อุปกรณ์ที่รองรับ ARCore

นอกจากนี้ ระบบจะเพิ่มแท็กข้อมูลเมตาต่อไปนี้ใต้ออบเจ็กต์แอปพลิเคชัน

<application
  android:allowBackup="true"
  android:icon="@mipmap/ic_launcher"
  android:label="@string/app_name"
  android:roundIcon="@mipmap/ic_launcher_round"
  android:supportsRtl="true"
  android:theme="@style/AppTheme">
  
  <!-- 
     Indicates that this app requires Google Play Services for AR ("AR Required") and causes
     the Google Play Store to download and install Google Play Services for AR along with
     the app. For an "AR Optional" app, specify "optional" instead of "required". 
  -->

  <meta-data
     android:name="com.google.ar.core"
     android:value="required" />

  <meta-data
     android:name="com.google.android.geo.API_KEY"
     android:value="@string/google_maps_key" />

  <!-- Additional elements here --> 

</application>

รายการข้อมูลเมตารายการแรกเป็นการระบุว่า ARCore เป็นข้อกําหนดเพื่อให้แอปนี้ทํางานได้ และรายการที่สองคือวิธีที่คุณระบุคีย์ API ของ Google Maps Platform แก่ Maps SDK สําหรับ Android

build.gradle

ใน build.gradle จะมีการระบุทรัพยากร Dependency เพิ่มเติมต่อไปนี้

dependencies {
    // Maps & Location
    implementation 'com.google.android.gms:play-services-location:17.0.0'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    implementation 'com.google.maps.android:maps-utils-ktx:1.7.0'

    // ARCore
    implementation "com.google.ar.sceneform.ux:sceneform-ux:1.15.0"

    // Retrofit
    implementation "com.squareup.retrofit2:retrofit:2.7.1"
    implementation "com.squareup.retrofit2:converter-gson:2.7.1"
}

ต่อไปนี้คือคําอธิบายโดยย่อของทรัพยากร Dependency แต่ละรายการ

  • ไลบรารีที่ใช้รหัสกลุ่ม com.google.android.gms เช่น play-services-location และ play-services-maps จะใช้เพื่อเข้าถึงข้อมูลตําแหน่งของอุปกรณ์และฟังก์ชันการเข้าถึงที่เกี่ยวข้องกับ Google Maps
  • com.google.maps.android:maps-utils-ktx คือไลบรารี Kootlin (KTX) สําหรับ Maps SDK สําหรับไลบรารี Utility Android ระบบจะใช้ฟังก์ชันนี้ในไลบรารีนี้เพื่อจัดตําแหน่งวัตถุเสมือนจริงในภายหลังแบบเรียลไทม์
  • com.google.ar.sceneform.ux:sceneform-ux เป็นไลบรารี Sceneform ซึ่งช่วยให้คุณแสดงผลฉาก 3 มิติสมจริงได้โดยไม่ต้องเรียนรู้ OpenGL
  • การขึ้นต่อกันในรหัสกลุ่ม com.squareup.retrofit2 เป็นทรัพยากร Dependency การนํามาใช้ซ้ํา ซึ่งให้คุณเขียนไคลเอ็นต์ HTTP เพื่อโต้ตอบกับ Places API ได้อย่างรวดเร็ว

โครงสร้างโปรเจ็กต์

ที่นี่คุณจะพบแพ็กเกจและไฟล์ต่อไปนี้

  • **api—**แพ็กเกจนี้มีคลาสที่ใช้โต้ตอบกับ Places API โดยใช้ Retrofit
  • **ar—**แพ็กเกจนี้มีไฟล์ทั้งหมดที่เกี่ยวข้องกับ ARCore
  • **model—**แพ็กเกจนี้มี Data Place คลาสเดียวซึ่งใช้เพื่อรวมสถานที่แห่งเดียวตามที่ Places API ส่งคืน
  • MainActivity.kt - Activity นี้จะอยู่ภายในแอป ซึ่งจะแสดงแผนที่และมุมมองกล้อง

5. การตั้งค่าฉาก

เจาะลึกองค์ประกอบสําคัญของแอปโดยเริ่มจากส่วน Augmented Reality

MainActivity มี SupportMapFragment ซึ่งจะจัดการการแสดงออบเจ็กต์แผนที่ และคลาสย่อยของ ArFragmentPlacesArFragment ซึ่งจะจัดการการแสดง Augmented Reality

การตั้งค่า Augmented Reality

นอกเหนือจากการแสดงฉาก Augmented Reality แล้ว PlacesArFragment ยังจะดําเนินการขอสิทธิ์ในการใช้กล้องจากผู้ใช้หากยังไม่ได้ทํา คุณยังขอสิทธิ์เพิ่มเติมได้โดยลบล้างเมธอด getAdditionalPermissions เนื่องจากคุณต้องขอสิทธิ์เข้าถึงตําแหน่งด้วย จากนั้นให้ระบุและลบล้างเมธอด getAdditionalPermissions ดังนี้

class PlacesArFragment : ArFragment() {

   override fun getAdditionalPermissions(): Array<String> =
       listOf(Manifest.permission.ACCESS_FINE_LOCATION)
           .toTypedArray()
}

เรียกใช้

ดําเนินการต่อและเปิดรหัสโครงกระดูกในไดเรกทอรี starter ใน Android Studio ได้ หากคลิกเรียกใช้ &gt เรียกใช้ "แอป&#39 จากแถบเครื่องมือและทําให้แอปใช้งานได้ในอุปกรณ์หรือโปรแกรมจําลอง คุณควรได้รับแจ้งให้เปิดใช้สิทธิ์เข้าถึงตําแหน่งและกล้องก่อน หลังจากนั้นให้คลิกอนุญาต และขณะเดียวกัน คุณจะเห็นมุมมองกล้องและมุมมองแผนที่เทียบกันดังนี้

e3e3073d5c86f427.png

การตรวจจับเครื่องบิน

เมื่อมองดูสภาพแวดล้อมรอบตัวคุณด้วยกล้อง คุณอาจสังเกตเห็นจุดสีขาว 2-3 จุดที่วางซ้อนบนพื้นผิวในแนวนอน เช่น จุดสีขาวบนพรมในรูปภาพนี้

ไฟล์ 2a9b6ea7dcb2e249.png

จุดสีขาวเหล่านี้เป็นหลักเกณฑ์จาก ARCore ที่บ่งชี้ว่าระนาบแนวนอนที่ตรวจพบ เครื่องบินที่ตรวจพบเหล่านี้ช่วยให้คุณสร้างสิ่งที่เรียกว่า #quot;anchor" เพื่อที่คุณจะได้จัดตําแหน่งวัตถุเสมือนจริงในแบบเรียลไทม์ได้

โปรดอ่านแนวคิดพื้นฐานเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับ ARCore และทําความเข้าใจสภาพแวดล้อมรอบตัว

6. รับข้อมูลสถานที่ใกล้เคียง

จากนั้น คุณจะต้องเข้าถึงและแสดงตําแหน่งปัจจุบันของอุปกรณ์ตามด้วยการดึงข้อมูลสถานที่ใกล้เคียงโดยใช้ Places API

การตั้งค่า Maps

คีย์ API ของ Google Maps Platform

ก่อนหน้านี้คุณได้สร้างคีย์ Google Maps Platform API เพื่อเปิดใช้การค้นหา Places API และสามารถใช้ Maps SDK สําหรับ Android ได้ ดําเนินการต่อและเปิดไฟล์ gradle.properties และแทนที่สตริง "YOUR API KEY HERE" ด้วยคีย์ API ที่คุณสร้าง

แสดงตําแหน่งของอุปกรณ์บนแผนที่

เมื่อเพิ่มคีย์ API แล้ว ให้เพิ่มโปรแกรมช่วยเหลือบนแผนที่เพื่อช่วยจัดตําแหน่งผู้ใช้ให้สัมพันธ์กับแผนที่ หากต้องการทําเช่นนั้น ให้ไปที่เมธอด setUpMaps และภายในการโทร mapFragment.getMapAsync ให้ตั้งค่า googleMap.isMyLocationEnabled เป็น true. เพื่อแสดงจุดสีน้ําเงินบนแผนที่

private fun setUpMaps() {
   mapFragment.getMapAsync { googleMap ->
       googleMap.isMyLocationEnabled = true
       // ...
   }
}

ดูตําแหน่งปัจจุบัน

หากต้องการดูตําแหน่งของอุปกรณ์ คุณจะต้องใช้ประโยชน์จากชั้นเรียน FusedLocationProviderClient การรับอินสแตนซ์นี้ทําได้แล้วในเมธอด onCreate ของ MainActivity หากต้องการใช้ออบเจ็กต์นี้ โปรดกรอกข้อมูลในเมธอด getCurrentLocation ซึ่งยอมรับอาร์กิวเมนต์แลมบ์ดา เพื่อให้ระบบส่งตําแหน่งไปยังผู้โทรของเมธอดนี้ได้

ในการใช้วิธีนี้ คุณสามารถเข้าถึงพร็อพเพอร์ตี้ lastLocation ของออบเจ็กต์ FusedLocationProviderClient ได้ด้วยการเพิ่มใน addOnSuccessListener ดังนี้

fusedLocationClient.lastLocation.addOnSuccessListener { location ->
    currentLocation = location
    onSuccess(location)
}.addOnFailureListener {
    Log.e(TAG, "Could not get location")
}

ระบบจะเรียกเมธอด getCurrentLocation จากแลมบ์ดาที่ให้ไว้ใน getMapAsync ในเมธอด setUpMaps ที่ดึงข้อมูลสถานที่ใกล้เคียง

เริ่มต้นการโทรในเครือข่ายสถานที่

ในการเรียกใช้เมธอด getNearbyPlaces โปรดทราบว่าพารามิเตอร์ต่อไปนี้จะส่งผ่านเมธอด placesServices.nearbyPlaces เช่น คีย์ API, ตําแหน่งของอุปกรณ์, รัศมีเป็นเมตร (ซึ่งตั้งค่าเป็น 2 กม.) และประเภทสถานที่ (ขณะนี้ตั้งค่าเป็น park)

val apiKey = "YOUR API KEY"
placesService.nearbyPlaces(
   apiKey = apiKey,
   location = "${location.latitude},${location.longitude}",
   radiusInMeters = 2000,
   placeType = "park"
)

หากต้องการเรียกใช้เครือข่ายให้เสร็จสิ้น โปรดส่งต่อคีย์ API ที่คุณกําหนดไว้ในไฟล์ gradle.properties ระบบจะกําหนดข้อมูลโค้ดต่อไปนี้ในไฟล์ build.gradle ภายใต้การกําหนดค่า android > defaultConfig

android {
   defaultConfig {
       resValue "string", "google_maps_key", (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "")
   }
}

ซึ่งจะทําให้ค่าทรัพยากรสตริง google_maps_key พร้อมใช้งานในเวลาบิลด์

หากต้องการเรียกเครือข่ายให้เสร็จสมบูรณ์ คุณเพียงแค่อ่านทรัพยากรสตริงนี้ผ่าน getString ในออบเจ็กต์ Context

val apiKey = this.getString(R.string.google_maps_key)

7. สถานที่ใน AR

จนถึงตอนนี้ คุณทําสิ่งต่อไปนี้แล้ว

  1. ขอสิทธิ์เข้าถึงกล้องและตําแหน่งจากผู้ใช้เมื่อเรียกใช้แอปครั้งแรก
  2. ตั้งค่า ARCore เพื่อเริ่มติดตามเครื่องบินแนวนอน
  3. ตั้งค่า Maps SDK ด้วยคีย์ API
  4. รับตําแหน่งปัจจุบันของอุปกรณ์
  5. ดึงสถานที่ใกล้เคียง (โดยเฉพาะสวนสาธารณะ) โดยใช้ Places API

ที่เหลือให้ทําแบบฝึกหัดนี้ก็คือการวางตําแหน่งที่จะดึงข้อมูลผ่าน Augmented Reality

ทําความเข้าใจสถานการณ์

ARCore เข้าใจฉากในโลกแห่งความเป็นจริงผ่านกล้องของอุปกรณ์ได้โดยการตรวจจับจุดที่น่าสนใจและโดดเด่นที่เรียกว่า "ฟีเจอร์โฟน" ในแต่ละเฟรมรูปภาพ เมื่อมีการรวมจุดเด่นเหล่านี้เข้าด้วยกันและอยู่บนระนาบแนวนอนทั่วไป เช่น ตารางและพื้น ARCore จะทําให้ฟีเจอร์นี้พร้อมใช้งานเป็นแอปแนวนอน

ดังที่คุณเห็นก่อนหน้านี้ ARCore จะช่วยแนะนําผู้ใช้เมื่อตรวจพบเครื่องบินโดยแสดงจุดสีขาว

ไฟล์ 2a9b6ea7dcb2e249.png

การเพิ่มโฆษณา Anchor

เมื่อระบบตรวจพบเครื่องบินแล้ว คุณจะแนบวัตถุที่เรียกว่าแท็ก Anchor ได้ คุณจะวางวัตถุเสมือนจริงไว้ได้ด้วย Anchor และรับประกันว่าวัตถุเหล่านั้นจะปรากฏในตําแหน่งเดียวกันในพื้นที่ทํางาน แล้วแก้ไขโค้ดเพื่อแนบรหัสเมื่อตรวจพบเครื่องบิน

ใน setUpAr OnTapArPlaneListener จะแนบกับ PlacesArFragment Listener นี้จะถูกเรียกใช้ทุกครั้งที่แตะเครื่องบินในโหมด AR ภายในการเรียกนี้ คุณสามารถสร้าง Anchor และ AnchorNode จาก HitResult ที่ระบุไว้ใน Listener ดังนี้

arFragment.setOnTapArPlaneListener { hitResult, _, _ ->
   val anchor = hitResult.createAnchor()
   anchorNode = AnchorNode(anchor)
   anchorNode?.setParent(arFragment.arSceneView.scene)
   addPlaces(anchorNode!!)
}

AnchorNode คือที่ที่คุณจะแนบออบเจ็กต์โหนดย่อย (เช่น PlaceNode) ในฉากที่จัดการในการเรียกใช้เมธอด addPlaces

เรียกใช้

หากคุณเรียกใช้แอปโดยแก้ไขตามข้างต้น ให้มองรอบตัวคุณจนกว่าจะตรวจพบเครื่องบิน ไปต่อที่จุดสีขาวซึ่งแสดงเครื่องบิน ซึ่งเมื่อทําเช่นนั้น คุณจะเห็นเครื่องหมายบนแผนที่แสดงสวนสาธารณะที่ใกล้ที่สุดรอบตัวคุณ อย่างไรก็ตาม หากสังเกตเห็นว่า วัตถุเสมือนติดอยู่บนตัวยึด โดยไม่ได้วางไว้ข้างที่ของสวนสาธารณะเหล่านั้น

f93eb87c98a0098d.png

สําหรับขั้นตอนสุดท้าย คุณจะแก้ไขได้โดยใช้ Maps SDK สําหรับไลบรารียูทิลิตีของ Android และ SensorManager ในอุปกรณ์

8. การกําหนดตําแหน่ง

หากต้องการจัดตําแหน่งไอคอนสถานที่เสมือนจริงใน Augmented Reality เป็นส่วนหัวที่ถูกต้อง คุณจะต้องมีข้อมูลต่อไปนี้ 2 ส่วน

  • ทิศเหนือที่เป็นจริง
  • มุมระหว่างทิศเหนือกับสถานที่แต่ละแห่ง

หันไปทางทิศเหนือ

ทิศเหนือกําหนดได้โดยใช้เซ็นเซอร์ตําแหน่ง (แม่เหล็กและตัวตรวจวัดความเร่ง) ที่มีในอุปกรณ์ การใช้เซ็นเซอร์ 2 ตัวนี้จะทําให้คุณรวบรวมข้อมูลแบบเรียลไทม์เกี่ยวกับตําแหน่งของอุปกรณ์ในอวกาศได้ สําหรับข้อมูลเพิ่มเติมเกี่ยวกับเซ็นเซอร์ตําแหน่ง โปรดอ่านคํานวณการวางแนวของอุปกรณ์

หากต้องการเข้าถึงเซ็นเซอร์เหล่านี้ คุณจะต้องได้รับ SensorManager ตามด้วยการลงทะเบียน SensorEventListener ในเซ็นเซอร์เหล่านั้น มีขั้นตอนเหล่านี้ให้คุณได้แล้วในวิธีวงจรของ MainActivity&#39

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   // ...
   sensorManager = getSystemService()!!
   // ...
}

override fun onResume() {
   super.onResume()
   sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also {
       sensorManager.registerListener(
           this,
           it,
           SensorManager.SENSOR_DELAY_NORMAL
       )
   }
   sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also {
       sensorManager.registerListener(
           this,
           it,
           SensorManager.SENSOR_DELAY_NORMAL
       )
   }
}

override fun onPause() {
   super.onPause()
   sensorManager.unregisterListener(this)
}

ในเมธอด onSensorChanged จะมีการระบุออบเจ็กต์ SensorEvent ซึ่งมีรายละเอียดเกี่ยวกับเซ็นเซอร์ที่ให้ไว้และมีการเปลี่ยนแปลงเมื่อมีการเปลี่ยนแปลงเมื่อเวลาผ่านไป เพิ่มโค้ดต่อไปนี้ลงในเมธอดนั้น

override fun onSensorChanged(event: SensorEvent?) {
   if (event == null) {
       return
   }
   if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
       System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size)
   } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
       System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size)
   }

   // Update rotation matrix, which is needed to update orientation angles.
   SensorManager.getRotationMatrix(
       rotationMatrix,
       null,
       accelerometerReading,
       magnetometerReading
   )
   SensorManager.getOrientation(rotationMatrix, orientationAngles)
}

โค้ดข้างต้นจะตรวจสอบประเภทของเซ็นเซอร์และจะอัปเดตการอ่านเซ็นเซอร์ที่เหมาะสม (ไม่ว่าจะเป็นตัวตรวจวัดความเร่งหรือเครื่องวัดค่าความเข้มข้นของสนามแม่เหล็ก) ทั้งนี้ขึ้นอยู่กับประเภท เมื่อใช้ค่าที่อ่านได้จากเซ็นเซอร์เหล่านี้ เราจะถือว่าค่ากี่องศาจากทิศเหนือที่สัมพันธ์กับอุปกรณ์ (เช่น ค่าของ orientationAngles[0])

ส่วนหัวแบบ 360 องศา

เมื่อระบุทิศเหนือแล้ว ขั้นตอนถัดไปคือการกําหนดมุมระหว่างทิศเหนือและแต่ละสถานที่ ตามด้วยข้อมูลนั้นเพื่อวางสถานที่ในส่วนหัวที่ถูกต้องใน Augmented Reality

ในการคํานวณส่วนหัว คุณจะต้องใช้ SDK ของ Maps สําหรับไลบรารียูทิลิตีของ Android ซึ่งมีฟังก์ชันช่วยมากมายสําหรับระยะทางในการประมวลผลและส่วนหัวผ่านเรขาคณิตทรงกลม โปรดอ่านข้อมูลเพิ่มเติมที่หัวข้อภาพรวมของไลบรารีนี้

ถัดไปคุณจะต้องใช้วิธีการของ sphericalHeading ในไลบรารียูทิลิตี ซึ่งคํานวณส่วนหัว/ทิศทางระหว่างออบเจ็กต์ LatLng ทั้ง 2 รายการ ต้องป้อนข้อมูลนี้ภายในเมธอด getPositionVector ที่กําหนดไว้ใน Place.kt ในที่สุดเมธอดนี้จะแสดงออบเจ็กต์ Vector3 ซึ่ง PlaceNode แต่ละรายการจะใช้ตําแหน่งดังกล่าวเป็นตําแหน่งในพื้นที่ AR

ดําเนินการต่อและแทนที่การกําหนดส่วนหัวในวิธีการนั้นด้วยข้อมูลต่อไปนี้

val heading = latLng.sphericalHeading(placeLatLng)

ซึ่งควรส่งผลให้เกิดคําจํากัดความของวิธีการต่อไปนี้

fun Place.getPositionVector(azimuth: Float, latLng: LatLng): Vector3 {
   val placeLatLng = this.geometry.location.latLng
   val heading = latLng.sphericalHeading(placeLatLng)
   val r = -2f
   val x = r * sin(azimuth + heading).toFloat()
   val y = 1f
   val z = r * cos(azimuth + heading).toFloat()
   return Vector3(x, y, z)
}

ตําแหน่งในเครื่อง

ขั้นตอนสุดท้ายในการดูแลสถานที่อย่างถูกต้องใน AR คือการใช้ผลลัพธ์ของ getPositionVector เมื่อมีการเพิ่มออบเจ็กต์ PlaceNode ลงในฉาก ดําเนินการต่อและไปที่ addPlaces ใน MainActivity ด้านขวาใต้บรรทัดที่กําหนดผู้ปกครองใน placeNode แต่ละรายการ (ใต้ placeNode.setParent(anchorNode)) ตั้งค่า localPosition ของ placeNode ตามผลลัพธ์ของการเรียกใช้ getPositionVector ดังนี้

val placeNode = PlaceNode(this, place)
placeNode.setParent(anchorNode)
placeNode.localPosition = place.getPositionVector(orientationAngles[0], currentLocation.latLng)

โดยค่าเริ่มต้น เมธอด getPositionVector จะตั้งค่าระยะทาง y ของโหนดเป็น 1 เมตรดังที่ระบุโดยค่า y ในเมธอด getPositionVector หากต้องการปรับระยะทางนี้ ให้พูดว่า 2 เมตร แล้วแก้ไขค่านั้นตามต้องการ

การเปลี่ยนแปลงนี้ทําให้ออบเจ็กต์ PlaceNode ที่เพิ่มเข้ามาควรอยู่ในทิศทางที่ถูกต้อง เริ่มต้นใช้งานแล้วเรียกใช้แอปเพื่อดูผลลัพธ์

9. ยินดีด้วย

ขอแสดงความยินดีกับการก้าวไปอีกขั้น

ดูข้อมูลเพิ่มเติม