1. ภาพรวม
ARCore เป็นแพลตฟอร์มสำหรับสร้างแอป Augmented Reality ใน Android Augmented Images ช่วยให้คุณสร้างแอป AR ที่จดจำรูปภาพ 2 มิติที่ลงทะเบียนไว้ล่วงหน้าจากในชีวิตจริงได้ และยึดเนื้อหาเสมือนไว้ด้านบน
Codelab นี้จะแนะนำคุณตลอดการแก้ไขแอปตัวอย่าง ARCore ที่มีอยู่เพื่อรวม Augmented Images ที่เคลื่อนไหวหรืออยู่กับที่
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะสร้างขึ้นจากแอปตัวอย่าง ARCore ที่มีอยู่ก่อนแล้ว เมื่อสิ้นสุด Codelab แล้ว แอปจะทำสิ่งต่อไปนี้ได้
- ตรวจหาเป้าหมายรูปภาพและแนบเขาวงกตเสมือนบนเป้าหมาย
- ติดตามเป้าหมายเคลื่อนที่ตราบใดที่ยังอยู่ในมุมมองกล้อง
นี่เป็นการสร้างแอป ARCore เป็นครั้งแรกใช่ไหม
คุณวางแผนจะเขียนโค้ดตัวอย่างใน Codelab นี้หรือแค่อยากอ่านหน้าเหล่านี้
สิ่งที่คุณจะได้เรียนรู้
- วิธีใช้ Augmented Images ใน ARCore ใน Java
- วิธีวัดความสามารถของรูปภาพที่ ARCore จะจดจำได้
- วิธีแนบเนื้อหาเสมือนจริงในรูปภาพและติดตามการเคลื่อนไหว
ข้อกำหนดเบื้องต้น
คุณจะต้องใช้ฮาร์ดแวร์และซอฟต์แวร์เฉพาะเพื่อทำงาน Codelab นี้ให้เสร็จสมบูรณ์
ข้อกำหนดเกี่ยวกับฮาร์ดแวร์
- อุปกรณ์ที่รองรับ ARCore ที่เชื่อมต่อผ่านสาย USB กับเครื่องพัฒนา
ข้อกำหนดของซอฟต์แวร์
- ARCore APK 1.9.0 ขึ้นไป โดยปกติแล้ว APK นี้จะได้รับการติดตั้งโดยอัตโนมัติบนอุปกรณ์ผ่าน Play Store
- เครื่องสำหรับการพัฒนาที่มี Android Studio (เวอร์ชัน 3.1 ขึ้นไป)
- การเข้าถึงอินเทอร์เน็ต เนื่องจากคุณจะต้องดาวน์โหลดไลบรารีระหว่างการพัฒนา
ในตอนนี้คุณมีทุกอย่างพร้อมแล้ว มาเริ่มกันเลย
2. ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์
ดาวน์โหลด SDK
เราจะเริ่มด้วยการดาวน์โหลด ARCore Android SDK เวอร์ชันล่าสุดจาก GitHub แตกไฟล์ซิปไปยังตำแหน่งที่คุณต้องการ SDK เวอร์ชันแรกสุดคือ 1.18.1 สำหรับ Codelab นี้ เราจะเรียกโฟลเดอร์นี้ว่า arcore-android-sdk-x.xx.x
ค่าที่แน่นอนจะเป็นเวอร์ชันของ SDK ที่คุณใช้
เปิด Android Studio แล้วคลิกเปิดโปรเจ็กต์ Android Studio ที่มีอยู่
ไปยังโฟลเดอร์ที่แตกไฟล์แล้วนี้
arcore-android-sdk-x.xx.x/samples/augmented_image_java
คลิกเปิด
โปรดรอให้ Android Studio ซิงค์โปรเจ็กต์ให้เสร็จ หาก Android Studio ของคุณไม่มีคอมโพเนนต์ที่จำเป็น อาจดำเนินการไม่สำเร็จเมื่อมีข้อความว่า Install missing platform and sync project
ทำตามวิธีการเพื่อแก้ไขปัญหา
เรียกใช้แอปตัวอย่าง
ตอนนี้คุณมีโปรเจ็กต์แอป ARCore ที่ใช้งานได้ มาลองทดสอบกัน
เชื่อมต่ออุปกรณ์ ARCore กับเครื่องพัฒนาแล้วใช้เมนู Run > เรียกใช้ "แอป" เพื่อเรียกใช้เวอร์ชันแก้ไขข้อบกพร่องในอุปกรณ์ ในกล่องโต้ตอบที่แจ้งให้เลือกอุปกรณ์ที่จะเรียกใช้ ให้เลือกอุปกรณ์ที่เชื่อมต่อแล้วคลิกตกลง
โปรเจ็กต์ตัวอย่างนี้ใช้ targetSdkVersion 28
หากคุณมีข้อผิดพลาดของบิลด์ เช่น Failed to find Build Tools revision 28.0.3
ให้ทำตามวิธีการที่อธิบายไว้ใน Android Studio เพื่อดาวน์โหลดและติดตั้งเครื่องมือสร้าง Android เวอร์ชันที่จำเป็น
หากทุกอย่างสำเร็จ แอปตัวอย่างจะเปิดขึ้นในอุปกรณ์และให้คุณขออนุญาตอนุญาตให้ Augmented Image ถ่ายภาพและวิดีโอ แตะอนุญาตเพื่อให้สิทธิ์
ทดสอบกับรูปภาพตัวอย่าง
เมื่อตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์แล้ว คุณจะทดสอบแอปได้โดยใส่รูปภาพให้ดู
กลับไปที่ Android Studio ในหน้าต่างโปรเจ็กต์ จากนั้นไปที่แอป > เนื้อหา แล้วดับเบิลคลิกไฟล์ default.jpg
เพื่อเปิด
เล็งกล้องของอุปกรณ์ไปที่ภาพของโลกบนหน้าจอ แล้วทำตามคำแนะนำเพื่อจัดภาพที่กำลังสแกนอยู่ในรูปกากบาท
กรอบรูปภาพจะวางซ้อนอยู่ด้านบนรูปภาพดังนี้
ต่อไป เราจะทำการปรับปรุงเล็กๆ น้อยๆ กับแอปตัวอย่าง
3. แสดงโมเดลเขาวงกตในรูปภาพ 2 มิติ
คุณสามารถเริ่มใช้งาน Augmented Images ด้วยการแสดงโมเดล 3 มิติอยู่ด้านบน
ดาวน์โหลดโมเดล 3 มิติ
สำหรับ Codelab นี้ เราจะใช้ "Circle Maze - Green" โดย Evol และได้รับอนุญาตภายใต้ CC-BY 3.0 เราเก็บสำเนาของโมเดล 3 มิตินี้ในที่เก็บ Git สำหรับ Codelab แล้ว ซึ่งดูได้ที่นี่
ทำตามขั้นตอนต่อไปนี้เพื่อดาวน์โหลดโมเดลและรวมไว้ใน Android Studio
- ไปที่ที่เก็บ GitHub ของ Codelab นี้หรือไดเรกทอรีของบุคคลที่สาม
- คลิก GreenMaze_obj.zip แล้วคลิกปุ่มดาวน์โหลด
การดำเนินการนี้จะดาวน์โหลดไฟล์ชื่อ GreenMaze_obj.zip
- ใน Android Studio ให้สร้างไดเรกทอรี
green-maze
ในส่วนแอป > เนื้อหา > รุ่น - แตกไฟล์ ZIP
GreenMaze_obj.zip
และคัดลอกเนื้อหาไปยังตำแหน่งนี้:arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/assets/models/green-maze
- ใน Android Studio ให้ไปที่แอป > เนื้อหา > รุ่น > เขาวงกตสีเขียว
โฟลเดอร์นี้ควรมี 2 ไฟล์: GreenMaze.obj
และ GreenMaze.mtl
แสดงภาพโมเดลเขาวงกต
ทำตามขั้นตอนต่อไปนี้เพื่อแสดงโมเดล 3 มิติ GreenMaze.obj
บนรูปภาพ 2 มิติที่มีอยู่
ใน AugmentedImageRenderer.java
ให้เพิ่มตัวแปรสมาชิกที่ชื่อว่า mazeRenderer
เพื่อแสดงผลโมเดลเขาวงกต เนื่องจากเขาวงกตควรแนบไปกับรูปภาพ จึงควรใส่ mazeRenderer
ไว้ในคลาส AugmentedImageRenderer
AugmentedImageRenderer.java
// Add a member variable to hold the maze model.
private final ObjectRenderer mazeRenderer = new ObjectRenderer();
ในฟังก์ชัน createOnGlThread()
ให้โหลด GreenMaze.obj
เพื่อความเรียบง่าย ให้ใช้พื้นผิวกรอบเดียวกันกับพื้นผิว
AugmentedImageRenderer.java
// Replace the definition of the createOnGlThread() function with the
// following code, which loads GreenMaze.obj.
public void createOnGlThread(Context context) throws IOException {
mazeRenderer.createOnGlThread(
context, "models/green-maze/GreenMaze.obj", "models/frame_base.png");
mazeRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
}
แทนที่คำจำกัดความของฟังก์ชัน draw()
ด้วยข้อมูลต่อไปนี้ ซึ่งจะปรับขนาดของเขาวงกตตามขนาดของรูปภาพที่ตรวจพบและแสดงผลบนหน้าจอ
AugmentedImageRenderer.java
// Adjust size of detected image and render it on-screen
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
float[] tintColor =
convertHexToColor(TINT_COLORS_HEX[augmentedImage.getIndex() % TINT_COLORS_HEX.length]);
final float mazeEdgeSize = 492.65f; // Magic number of maze size
final float maxImageEdgeSize = Math.max(augmentedImage.getExtentX(), augmentedImage.getExtentZ()); // Get largest detected image edge size
Pose anchorPose = centerAnchor.getPose();
float mazeScaleFactor = maxImageEdgeSize / mazeEdgeSize; // scale to set Maze to image size
float[] modelMatrix = new float[16];
// OpenGL Matrix operation is in the order: Scale, rotation and Translation
// So the manual adjustment is after scale
// The 251.3f and 129.0f is magic number from the maze obj file
// You mustWe need to do this adjustment because the maze obj file
// is not centered around origin. Normally when you
// work with your own model, you don't have this problem.
Pose mazeModelLocalOffset = Pose.makeTranslation(
-251.3f * mazeScaleFactor,
0.0f,
129.0f * mazeScaleFactor);
anchorPose.compose(mazeModelLocalOffset).toMatrix(modelMatrix, 0);
mazeRenderer.updateModelMatrix(modelMatrix, mazeScaleFactor, mazeScaleFactor/10.0f, mazeScaleFactor); // This line relies on a change in ObjectRenderer.updateModelMatrix later in this codelab.
mazeRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
ตอนนี้เขาวงกตควรจะปรากฏที่ด้านบนของภาพ default.jpg
ของโลก
หมายเหตุ: เนื่องจากคุณไม่มีสิทธิ์ควบคุมตัวอย่างนี้อย่างสมบูรณ์แบบ 3 มิติ โค้ดด้านบนจึงใช้ "ความมหัศจรรย์" บางอย่าง ตัวเลข ขนาดของโมเดลเขาวงกตคือ 492.65 x 120 x 492.65 โดยมีจุดศูนย์กลางอยู่ที่ (251.3, 60, -129.0) ช่วงของจุดยอด ค่าพิกัด X, Y และ Z คือ [5.02, 497.67], [0, 120] และ [-375.17, 117.25] ตามลำดับ ดังนั้น ขนาดของโมเดลเขาวงกตจะต้องเป็น image_size / 492.65
มีการใช้ mazeModelLocalOffset
เนื่องจากโมเดล 3 มิติของเขาวงกตไม่ได้อยู่ตรงกลางของต้นทาง (0, 0, 0)
ผนังของเขาวงกตยังคงสูงเกินไปเล็กน้อยที่จะอยู่ด้านบนของภาพ สร้างฟังก์ชันตัวช่วย updateModelMatrix()
ที่สามารถปรับขนาด X, Y, Z อย่างไม่สม่ำเสมอเพื่อปรับความสูงของเขาวงกตเป็น 0.1 โปรดทราบว่าคุณต้องใช้ updateModelMatrix(float[] modelMatrix, float scaleFactor)
ที่มีอยู่ต่อไปและเพิ่มฟังก์ชันโอเวอร์โหลด updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ)
เป็นฟังก์ชันใหม่
common/rendering/ObjectRenderer.java
// Scale X, Y, Z coordinates unevenly
public void updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) {
float[] scaleMatrix = new float[16];
Matrix.setIdentityM(scaleMatrix, 0);
scaleMatrix[0] = scaleFactorX;
scaleMatrix[5] = scaleFactorY;
scaleMatrix[10] = scaleFactorZ;
Matrix.multiplyMM(this.modelMatrix, 0, modelMatrix, 0, scaleMatrix, 0);
}
เรียกใช้โค้ด ตอนนี้เขาวงกตควรจะพอดีกับด้านบนรูปภาพพอดี
4. เพิ่ม Andy เข้าไปในเขาวงกต
เมื่อคุณมีเขาวงกตแล้ว ให้เพิ่มตัวละครเพื่อย้ายไปด้านใน ใช้ไฟล์ andy.obj
ที่รวมอยู่ใน ARCore Android SDK รักษาพื้นผิวของเฟรมรูปภาพตามพื้นผิว เพราะดูแตกต่างจากเขาวงกตสีเขียวที่แสดงอยู่ด้านบนรูปภาพ
ใน AugmentedImageRenderer.java
ให้เพิ่ม ObjectRenderer
ส่วนตัวเพื่อแสดงผล Andy
AugmentedImageRenderer.java
// Render for Andy
private final ObjectRenderer andyRenderer = new ObjectRenderer();
ถัดไป ให้เริ่มต้น andyRenderer
เมื่อสิ้นเดือน createOnGlThread()
AugmentedImageRenderer.java
public void createOnGlThread(Context context) throws IOException {
// Initialize andyRenderer
andyRenderer.createOnGlThread(
context, "models/andy.obj", "models/andy.png");
andyRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
}
สุดท้าย แสดงภาพแอนดี้ที่ยืนอยู่บนเขาวงกตที่ตอนท้ายของฟังก์ชัน draw()
AugmentedImageRenderer.java
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
// Render Andy, standing on top of the maze
Pose andyModelLocalOffset = Pose.makeTranslation(
0.0f,
0.1f,
0.0f);
anchorPose.compose(andyModelLocalOffset).toMatrix(modelMatrix, 0);
andyRenderer.updateModelMatrix(modelMatrix, 0.05f); // 0.05f is a Magic number to scale
andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
เรียกใช้โค้ดของคุณ คุณจะเห็นแอนดี้ยืนอยู่บนเขาวงกต
ระบุคุณภาพของรูปภาพเป้าหมาย
ARCore ใช้ฟีเจอร์ด้านภาพเพื่อจดจำรูปภาพ เนื่องจากคุณภาพที่แตกต่างกัน รูปภาพบางรูปอาจจดจำได้ยาก
arcoreimg
เป็นเครื่องมือบรรทัดคำสั่งที่ช่วยให้คุณกำหนดได้ว่ารูปภาพจะเป็นที่รู้จักมากน้อยเพียงใดใน ARCore ซึ่งจะแสดงตัวเลขระหว่าง 0 ถึง 100 โดย 100 คือตัวเลขที่จำได้ง่ายที่สุด
ที่ใช้เวลาเพียง 2 นาที มีตัวอย่างดังต่อไปนี้
arcore-android-sdk-x.xx.x/tools/arcoreimg/macos$
$ ./arcoreimg eval-img --input_image_path=/Users/username/maze.jpg
100
maze.jpg
มีค่า 100 เพื่อให้ ARCore จดจำได้ง่าย
5. ไม่บังคับ: ให้แอนดี้เคลื่อนที่ไปในเขาวงกต
ขั้นตอนสุดท้าย คุณสามารถเพิ่มโค้ดบางอย่างเพื่อทำให้ Andy เคลื่อนที่ไปในเขาวงกตได้ เช่น ใช้เครื่องมือฟิสิกส์แบบโอเพนซอร์ส jBullet เพื่อจัดการการจำลองทางฟิสิกส์ ข้ามส่วนนี้ไปได้เลย
ดาวน์โหลด PhysicsController.java
และเพิ่มลงในโปรเจ็กต์ในไดเรกทอรี
arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/java/com/google/ar/core/examples/java/augmentedimage/
ใน Android Studio ให้เพิ่ม GreenMaze.obj ลงในไดเรกทอรีชิ้นงานของโปรเจ็กต์ เพื่อให้โหลดขณะรันไทม์ได้ คัดลอก GreenMaze.obj
จากแอป > เนื้อหา > รุ่น > green-maze ไปยัง แอป > เนื้อหา
เพิ่มทรัพยากร Dependency ต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
app/build.gradle
// jbullet library
implementation 'cz.advel.jbullet:jbullet:20101010-1'
กำหนดตัวแปร andyPose
เพื่อเก็บตำแหน่งท่าทางของอนุทิน
AugmentedImageRenderer.java
// Create a new pose for the Andy
private Pose andyPose = Pose.IDENTITY;
แก้ไข AugmentedImageRenderer.java
เพื่อแสดงผลแอนดี้โดยใช้ตัวแปร andyPose
ใหม่
AugmentedImageRenderer.java
public void draw(
float[] viewMatrix,
float[] projectionMatrix,
AugmentedImage augmentedImage,
Anchor centerAnchor,
float[] colorCorrectionRgba) {
// Use these code to replace previous code for rendering the Andy object
//
// Adjust the Andy's rendering position
// The Andy's pose is at the maze's vertex's coordinate
Pose andyPoseInImageSpace = Pose.makeTranslation(
andyPose.tx() * mazeScaleFactor,
andyPose.ty() * mazeScaleFactor,
andyPose.tz() * mazeScaleFactor);
anchorPose.compose(andyPoseInImageSpace).toMatrix(modelMatrix, 0);
andyRenderer.updateModelMatrix(modelMatrix, 0.05f);
andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
}
เพิ่มฟังก์ชันยูทิลิตีใหม่ updateAndyPose()
เพื่อรับการอัปเดตท่าทางของ Andy
AugmentedImageRenderer.java
// Receive Andy pose updates
public void updateAndyPose(Pose pose) {
andyPose = pose;
}
ใน AugmentedImageActivity.java
ให้สร้างออบเจ็กต์ PhysicsController
ที่ใช้กลไกทางฟิสิกส์ JBullet เพื่อจัดการฟังก์ชันที่เกี่ยวข้องกับฟิสิกส์ทั้งหมด
AugmentedImageActivity.java
import com.google.ar.core.Pose;
// Declare the PhysicsController object
private PhysicsController physicsController;
ในเครื่องมือฟิสิกส์ เราใช้ลูกบอลแข็งเพื่อเป็นตัวแทนของแอนดี้และอัปเดตท่าของแอนดี้โดยใช้ท่าของลูกบอล โทรหา PhysicsController
เพื่ออัปเดตหลักการทางฟิสิกส์ทุกครั้งที่แอปจดจำรูปภาพได้ ในการเคลื่อนที่ลูกบอลให้เหมือนกับในชีวิตจริง ให้ใช้แรงโน้มถ่วงในชีวิตจริงเพื่อย้ายลูกบอลในเขาวงกต
AugmentedImageActivity.java
// Update the case clause for TRACKING to call PhysicsController
// whenever the app recognizes an image
private void drawAugmentedImages(
...
case TRACKING:
// Switch to UI Thread to update View
this.runOnUiThread(
new Runnable() {
@Override
public void run() {
fitToScanView.setVisibility(View.GONE);
}
});
// Create a new anchor for newly found images
if (!augmentedImageMap.containsKey(augmentedImage.getIndex())) {
Anchor centerPoseAnchor = augmentedImage.createAnchor(augmentedImage.getCenterPose());
augmentedImageMap.put(
augmentedImage.getIndex(), Pair.create(augmentedImage, centerPoseAnchor));
physicsController = new PhysicsController(this);
} else {
Pose ballPose = physicsController.getBallPose();
augmentedImageRenderer.updateAndyPose(ballPose);
// Use real world gravity, (0, -10, 0), as gravity
// Convert to Physics world coordinate(maze mesh has to be static)
// Use the converted coordinate as a force to move the ball
Pose worldGravityPose = Pose.makeTranslation(0, -10f, 0);
Pose mazeGravityPose = augmentedImage.getCenterPose().inverse().compose(worldGravityPose);
float mazeGravity[] = mazeGravityPose.getTranslation();
physicsController.applyGravityToBall(mazeGravity);
physicsController.updatePhysics();
}
break;
เรียกใช้แอป ตอนนี้แอนดี้ควรเคลื่อนไปรอบๆ ได้อย่างสมจริงเมื่อคุณเอียงภาพ
ตัวอย่างด้านล่างใช้โทรศัพท์เครื่องอื่นในการแสดงภาพ คุณสามารถใช้เครื่องมือใดก็ได้ที่สะดวกสำหรับคุณ เช่น แท็บเล็ต ปกหนังสือปกแข็ง หรือใช้เพียงกระดาษพิมพ์ที่ติดอยู่บนวัตถุแบนราบ
เท่านี้ก็เรียบร้อย ขอให้สนุกกับการพา Andy เข้าไปในเขาวงกตให้สนุกนะ คำแนะนำ: คุณจะหาทางออกได้ง่ายขึ้นเมื่อคว่ำรูปภาพเป้าหมายคว่ำหน้าลง
6. ขอแสดงความยินดี
ขอแสดงความยินดี คุณมาถึงส่วนสุดท้ายของ Codelab แล้ว และนี่คือ:
- สร้างและเรียกใช้ตัวอย่าง ARCore AugmentedImage Java
- อัปเดตตัวอย่างเพื่อแสดงโมเดลเขาวงกตในขนาดที่เหมาะสม
- ใช้ท่าถ่ายรูปเพื่อทำกิจกรรมสนุกๆ
ดูโค้ดทั้งหมดได้โดยดาวน์โหลดที่นี่