1. Übersicht
ARCore ist eine Plattform zum Erstellen von Augmented-Reality-Apps für Android. Mit Augmented Images können Sie AR-Apps erstellen, die vorregistrierte 2D-Bilder in der realen Welt erkennen und virtuelle Inhalte darüber verankern können.
In diesem Codelab erfahren Sie, wie Sie eine vorhandene ARCore-Beispiel-App so modifizieren, dass erweiterte Bilder eingebunden werden, die an Ort und Stelle verschoben oder fixiert werden.
Aufgaben
In diesem Codelab bauen Sie auf einer bereits vorhandenen ARCore-Beispiel-App auf. Am Ende des Codelabs kannst du mit deiner App Folgendes tun:
- Bildziel erkennen und virtuelles Labyrinth am Ziel anhängen
- Bewegliches Ziel verfolgen, solange es sich im Sichtfeld der Kamera befindet
Entwickeln Sie zum ersten Mal eine ARCore-App?
<ph type="x-smartling-placeholder">Möchten Sie in diesem Codelab Beispielcode schreiben oder nur diese Seiten lesen?
<ph type="x-smartling-placeholder">Lerninhalte
- Erweiterte Bilder in ARCore in Java verwenden
- Wie kann man beurteilen, ob ein Bild von ARCore erkannt werden kann?
- Wie man virtuelle Inhalte zu einem Bild hinzufügt und seine Bewegung verfolgt
Vorbereitung
Für dieses Codelab benötigst du bestimmte Hardware und Software.
Hardwareanforderungen
- Ein ARCore-kompatibles Gerät, das über ein USB-Kabel mit Ihrem Entwicklungscomputer verbunden ist
Softwareanforderungen
- ARCore APK 1.9.0 oder höher. Dieses APK wird normalerweise automatisch über den Play Store auf dem Gerät installiert.
- Entwicklungsmaschine mit Android Studio (Version 3.1 oder höher)
- Internetzugriff, da Sie während der Entwicklung Bibliotheken herunterladen müssen
Jetzt, da du alles vorbereitet hast, kann es losgehen!
2. Entwicklungsumgebung einrichten
SDK herunterladen
Zuerst laden wir das neueste ARCore Android SDK von GitHub herunter. Entpacken Sie sie in den gewünschten Speicherort. In diesem Codelab ist die früheste SDK-Version 1.18.1. Der Ordner wird als arcore-android-sdk-x.xx.x
bezeichnet. Der genaue Wert entspricht der SDK-Version, die Sie verwenden.
Starten Sie Android Studio und klicken Sie auf Open an bestehendes Android Studio project (Vorhandenes Android Studio-Projekt öffnen).
Gehen Sie zu diesem entpackten Ordner:
arcore-android-sdk-x.xx.x/samples/augmented_image_java
Klicken Sie auf Öffnen.
Warten Sie, bis Android Studio die Synchronisierung des Projekts abgeschlossen hat. Wenn Android Studio nicht über die erforderlichen Komponenten verfügt, schlägt möglicherweise ein Fehler mit der Meldung Install missing platform and sync project
vor. Folgen Sie der Anleitung, um das Problem zu beheben.
Beispiel-App ausführen
Da du jetzt ein funktionierendes ARCore-App-Projekt hast, kannst du es ausprobieren.
Verbinden Sie Ihr ARCore-Gerät mit der Entwicklungsmaschine und verwenden Sie das Menü Ausführen > Führen Sie „app“ aus, um die Debug-Version auf dem Gerät auszuführen. Wählen Sie im Dialogfeld das gewünschte Gerät aus und klicken Sie auf OK.
In diesem Beispielprojekt wird targetSdkVersion 28
verwendet. Wenn ein Build-Fehler wie Failed to find Build Tools revision 28.0.3
auftritt, folgen Sie der Anleitung in Android Studio, um die erforderliche Version der Android Build Tools herunterzuladen und zu installieren.
Wenn alles erfolgreich war, wird die Beispiel-App auf dem Gerät gestartet und Sie werden aufgefordert, der Verwendung von „Augmented Image“ das Aufnehmen von Bildern und Videos zu erlauben. Tippen Sie auf ZULASSEN, um die Berechtigung zu erteilen.
Mit einem Beispielbild testen
Nachdem Sie Ihre Entwicklungsumgebung eingerichtet haben, können Sie die Anwendung testen, indem Sie ihr ein Bild zum Anschauen bereitstellen.
Gehen Sie in Android Studio im Fenster Project (Projekt) zu app > Assets und klicken Sie doppelt auf die Datei default.jpg
, um sie zu öffnen.
Richten Sie die Kamera Ihres Geräts auf das Bild der Erde auf dem Bildschirm und folgen Sie der Anleitung, um das Bild, das Sie scannen, in das Fadenkreuz zu passen.
Ein Bildrahmen überlagert das Bild wie folgt:
Als Nächstes nehmen wir kleine Verbesserungen an der Beispiel-App vor.
3. Labyrinthmodell auf dem 2D-Bild präsentieren
Sie können erweiterte Bilder ausprobieren, indem Sie darüber ein 3D-Modell einblenden.
3D-Modell herunterladen
Für dieses Codelab verwenden wir Circle Maze – Green von Evol und lizenziert unter CC-BY 3.0. Ich habe eine Kopie dieses 3D-Modells im GitHub-Repository dieses Codelabs gespeichert, das Sie hier finden.
Führen Sie die folgenden Schritte aus, um das Modell herunterzuladen und in Android Studio einzubinden.
- Gehen Sie zum GitHub-Repository dieses Codelab, Drittanbieterverzeichnis.
- Klicken Sie auf GreenMaze_obj.zip und dann auf Herunterladen.
Dadurch wird eine Datei mit dem Namen GreenMaze_obj.zip
heruntergeladen.
- Erstellen Sie in Android Studio das Verzeichnis
green-maze
unter app > Assets > Modelle - Entpacken Sie
GreenMaze_obj.zip
und kopieren Sie den Inhalt an diesen Speicherort:arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/assets/models/green-maze
- Navigiere in Android Studio zu App > Assets > Modelle > Green-Labyrinth.
In diesem Ordner sollten sich zwei Dateien befinden: GreenMaze.obj
und GreenMaze.mtl
.
Labyrinth-Modell rendern
Führen Sie die folgenden Schritte aus, um das 3D-Modell GreenMaze.obj
über dem vorhandenen 2D-Bild anzuzeigen.
Fügen Sie in AugmentedImageRenderer.java
eine Member-Variable namens mazeRenderer
hinzu, um das Labyrinth-Modell zu rendern. Da das Labyrinth an das Bild angehängt werden sollte, ist es sinnvoll, das mazeRenderer
innerhalb der AugmentedImageRenderer
-Klasse zu platzieren.
AugmentedImageRenderer.java
// Add a member variable to hold the maze model.
private final ObjectRenderer mazeRenderer = new ObjectRenderer();
Laden Sie in der Funktion createOnGlThread()
die GreenMaze.obj
. Der Einfachheit halber verwenden Sie dieselbe Rahmentextur wie seine Textur.
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);
}
Ersetzen Sie die Definition der draw()
-Funktion durch Folgendes. Dadurch wird die Größe des Labyrinths an die Größe des erkannten Bildes angepasst und auf dem Bildschirm gerendert.
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);
}
Jetzt sollte das Labyrinth über dem default.jpg
-Bild der Erde angezeigt werden.
Hinweis: Da Sie keine vollständige Kontrolle über dieses 3D-Beispielmodell haben, verwendet der obige Code ein paar magische Elemente. Zahlen. Die Abmessungen des Labyrinthmodells betragen 492,65 x 120 x 492,65, mit der Mitte (251,3, 60, -129,0). Der Bereich seiner Eckpunkte Die Werte für die X-, Y- und Z-Koordinaten sind [5,02, 497,67], [0, 120] bzw. [-375,17, 117,25]. Daher muss die Größe des Labyrinthmodells image_size / 492.65
sein. mazeModelLocalOffset
wird eingeführt, weil das 3D-Modell des Labyrinths nicht um den Ursprung (0, 0, 0) zentriert ist.
Die Wand des Labyrinths ist immer noch etwas zu hoch, um auf das Bild zu passen. Erstelle eine Hilfsfunktion updateModelMatrix()
, die X, Y und Z ungleichmäßig skalieren kann, um die Höhe des Labyrinths um 0,1 zu skalieren. Beachten Sie, dass Sie die vorhandene updateModelMatrix(float[] modelMatrix, float scaleFactor)
beibehalten und die Funktionsüberlastung updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ)
als neue Funktion hinzufügen.
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);
}
Führen Sie den Code aus. Das Labyrinth sollte nun perfekt über das Bild passen.
4. Andy zum Labyrinth hinzufügen
Nun, da du ein Labyrinth hast, füge einen Charakter hinzu, der dich darin bewegen kann. Verwende die Datei andy.obj
, die im ARCore Android SDK enthalten ist. Behalten Sie die Bildrahmentextur als Textur bei, da sie sich von dem grünen Labyrinth über dem Bild unterscheidet.
Füge in AugmentedImageRenderer.java
eine private ObjectRenderer
hinzu, um Andy zu rendern.
AugmentedImageRenderer.java
// Render for Andy
private final ObjectRenderer andyRenderer = new ObjectRenderer();
Als Nächstes initialisieren Sie andyRenderer
am Ende von 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);
}
Rendere schließlich Andy im Labyrinth am Ende der Funktion 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);
}
Führen Sie den Code aus. Du solltest Andy über dem Labyrinth sehen.
Zielbildqualität bestimmen
ARCore nutzt visuelle Funktionen, um Bilder zu erkennen. Aufgrund von Qualitätsunterschieden sind nicht alle Bilder leicht zu erkennen.
arcoreimg
ist ein Befehlszeilentool, mit dem Sie festlegen können, wie erkennbar ein Bild für ARCore ist. Es wird eine Zahl zwischen 0 und 100 ausgegeben, wobei 100 am einfachsten zu erkennen ist.
. Hier ein Beispiel:
arcore-android-sdk-x.xx.x/tools/arcoreimg/macos$
$ ./arcoreimg eval-img --input_image_path=/Users/username/maze.jpg
100
maze.jpg
hat einen Wert von 100, sodass er von ARCore leicht erkannt wird.
5. Optional: Andy im Labyrinth bewegen
Schließlich können Sie Code hinzufügen, damit sich das andy im Labyrinth bewegt. Verwenden Sie zum Beispiel die Open-Source-Engine Physics jBullet, um die Physiksimulation durchzuführen. Es ist völlig in Ordnung, wenn Sie diesen Teil überspringen.
Laden Sie PhysicsController.java
herunter und fügen Sie es Ihrem Projekt im Verzeichnis hinzu
arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/java/com/google/ar/core/examples/java/augmentedimage/
Fügen Sie in Android Studio GreenMaze.obj zum Verzeichnis Projekt-Assets hinzu, damit es zur Laufzeit geladen werden kann. GreenMaze.obj
aus App kopieren > Assets > models > Von green-maze zu app > Assets.
Fügen Sie der Datei build.gradle
der Anwendung die folgenden Abhängigkeiten hinzu.
app/build.gradle
// jbullet library
implementation 'cz.advel.jbullet:jbullet:20101010-1'
Definieren Sie die Variable andyPose
, um die Position von Andys aktuellen Pose zu speichern.
AugmentedImageRenderer.java
// Create a new pose for the Andy
private Pose andyPose = Pose.IDENTITY;
Ändern Sie AugmentedImageRenderer.java
, um Andy mit der neuen Variablen andyPose
zu rendern.
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);
}
Fügen Sie die neue Dienstprogrammfunktion „updateAndyPose()
“ hinzu, um Updates zu Andy-Pose zu erhalten.
AugmentedImageRenderer.java
// Receive Andy pose updates
public void updateAndyPose(Pose pose) {
andyPose = pose;
}
Erstellen Sie in AugmentedImageActivity.java
ein PhysicsController
-Objekt, das die Physik-Engine JBullet zur Verwaltung aller physikbezogenen Funktionen verwendet.
AugmentedImageActivity.java
import com.google.ar.core.Pose;
// Declare the PhysicsController object
private PhysicsController physicsController;
In der Physik-Engine verwenden wir einen starren Ball, um Andy zu repräsentieren, und aktualisieren Andys Position mit der Ballposition. Rufe PhysicsController
auf, um die Physik zu aktualisieren, sobald die App ein Bild erkennt. Um den Ball wie in der realen Welt zu bewegen, wenden Sie die Schwerkraft aus der realen Welt an, um ihn im Labyrinth zu bewegen.
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;
Führen Sie die App aus. Andy sollte sich nun realistisch bewegen, wenn Sie das Bild neigen.
Im folgenden Beispiel wird das Bild auf einem anderen Smartphone angezeigt. Sie können ein beliebiges Tablet verwenden, den Umschlag eines gedruckten Buchs verwenden oder einfach ein bedrucktes Papier, das auf einem flachen Gegenstand befestigt ist.
Fertig! Viel Spaß dabei, Andy durch das Labyrinth zu bringen. Hinweis: Der Exit ist einfacher zu finden, wenn du das Zielbild auf dem Kopf stehend hältst.
6. Glückwunsch
Glückwunsch! Sie sind am Ende dieses Codelab angelangt und somit:
- Es wurde ein AugmentedImage Java-Beispiel für ARCore erstellt und ausgeführt.
- Das Beispiel wurde aktualisiert, um ein Labyrinthmodell im Bild im richtigen Maßstab anzuzeigen.
- Die Pose des Bildes wurde verwendet, um etwas Lustiges zu tun.
Den vollständigen Code können Sie hier herunterladen.