Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Augmented Reality

Codieren Sie eine Mess-App mit ARKit: Platzieren von Objekten in der Szene

by
Read Time:11 minsLanguages:

German (Deutsch) translation by Tatsiana Bochkareva (you can also view the original English article)

Zusammen mit vielen anderen Dingen, die schnell durch unsere moderne Technologie ersetzt wurden, sieht es so aus, als ob das übliche Maßband das nächste sein könnte. In dieser zweiteiligen Lernserie lernen wir, wie Sie mithilfe von der erweiterten Realität und der Kamera auf Ihrem iOS-Gerät eine App erstellen, die den Abstand zwischen zwei Punkten angibt.

Im ersten Beitrag haben wir das App-Projekt erstellt und die wichtigsten Elemente der Benutzeroberfläche codiert. In diesem Beitrag beenden wir den Vorgang, indem wir zwischen zwei Punkten in der AR-Szene messen. Wenn Sie es noch nicht getan haben, folgen Sie dem ersten Beitrag, um Ihr ARKit-Projekt einzurichten.

Handhabung von Wasserhähnen

Hier ist einer der größten Teile dieses Tutorials: Handhabung, wenn der Benutzer auf seine Welt tippt, damit eine Kugel genau dort erscheint, wo er getippt hat. Später berechnen wir den Abstand zwischen diesen Kugeln, um dem Benutzer schließlich den Abstand anzuzeigen.

Tippen Sie auf Gestenerkennung

Der erste Schritt bei der Suche nach Taps besteht darin, beim Starten der App eine Tap-Gestenerkennung zu erstellen. Erstellen Sie dazu einen Tap-Handler, wie gezeigt wird:

Die erste Zeile erstellt eine Instanz der UITapGestureRecognizer() -Klasse und übergibt bei der Initialisierung zwei Parameter: das Ziel und die Aktion. Das Ziel ist der Empfänger der Benachrichtigungen, die dieser Erkenner sendet, und wir möchten, dass unsere ViewController-Klasse das Ziel ist. Die Aktion ist einfach eine Methode, die bei jedem Tippen aufgerufen werden sollte.

Fügen Sie Folgendes hinzu, um die Anzahl der Taps festzulegen:

Als nächstes muss die Instanz der Klasse, die wir zuvor erstellt haben, wissen, wie viele Taps tatsächlich benötigt werden, um den Erkenner zu aktivieren. In unserem Fall benötigen wir nur einen Tipp, in anderen Apps benötigen Sie in einigen Fällen möglicherweise mehr (z. B. einen doppelten Tipp).

Fügen Sie den Handler zur Szenenansicht hinzu:

Schließlich fügt diese einzelne Codezeile der Szenenansicht nur den Gestenerkenner hinzu, in dem wir alles tun werden. Hier befindet sich die Vorschau der Kamera sowie das, auf das der Benutzer direkt tippt, damit eine Kugel auf dem Bildschirm angezeigt wird. Daher ist es sinnvoll, den Erkenner zu der Ansicht hinzuzufügen, mit der der Benutzer interagieren wird.

Griff-Tap-Methode

Beim Erstellen von UITapGestureRecognizer() können Sie sich daran erinnern, dass wir für die Aktion eine handleTap-Methode festgelegt haben. Jetzt können wir diese Methode deklarieren. Fügen Sie dazu einfach Folgendes zu Ihrer App hinzu:

Obwohl die Funktionsdeklaration ziemlich selbsterklärend sein mag, fragen Sie sich vielleicht, warum sich ein @objc-Tag davor befindet. Ab der aktuellen Version von Swift benötigen Sie dieses Tag, um Methoden für Objective-C verfügbar zu machen. Sie müssen lediglich wissen, dass #selector die angegebene Methode benötigt, um Objective-C zur Verfügung zu stehen. Zuletzt können wir mit dem Methodenparameter die genaue Position ermitteln, die auf dem Bildschirm angetippt wurde.

Standorterkennung

Der nächste Schritt, um unsere Kugeln dort erscheinen zu lassen, wo der Benutzer getippt hat, besteht darin, die genaue Position zu ermitteln, auf die er getippt hat. Das ist nicht so einfach wie den Ort zu finden und eine Kugel zu platzieren, aber ich bin sicher, dass Sie es in kürzester Zeit meistern werden.

Fügen Sie Ihrer handleTap() -Methode zunächst die folgenden drei Codezeilen hinzu:

Wenn Sie sich an den Parameter erinnern, den wir in der handleTap() -Methode verwendet haben, können Sie sich daran erinnern, dass er als sender bezeichnet wurde und vom Typ UITapGestureRecognizer war. Nun, diese erste Codezeile nimmt einfach die Position des Tippens auf dem Bildschirm (relativ zur Szenenansicht) und setzt sie auf eine Konstante mit dem Namen location.

Als nächstes führen wir einen sogenannten Hit-Test in der SceneView selbst durch. In einfachen Worten bedeutet dies, die Szene auf reale Objekte wie Tische, Oberflächen, Wände, Böden usw. zu überprüfen. Dies ermöglicht es uns, ein Gefühl für die Tiefe zu bekommen und ziemlich genaue Messungen zwischen zwei Punkten zu erhalten. Darüber hinaus geben wir die zu erkennenden Objekttypen an. Wie Sie sehen können, wird empfohlen, nach featurePoints zu suchen, bei denen es sich im Wesentlichen um flache Oberflächen handelt. Dies ist für eine Mess-App sinnvoll.

Schließlich nimmt die Codezeile das genaueste Ergebnis, das im Fall von hitTest das letzte Ergebnis ist, und prüft, ob es nicht nil ist. Wenn dies der Fall ist, werden die restlichen Zeilen dieser Methode ignoriert. Wenn jedoch tatsächlich ein Ergebnis vorliegt, wird es einer Konstante zugewiesen, die als result bezeichnet wird.

Matrizen

Wenn Sie an Ihre High-School-Algebra-Klasse zurückdenken, erinnern Sie sich vielleicht an Matrizen, die damals vielleicht nicht so wichtig waren wie heute. Sie werden häufig für Aufgaben im Zusammenhang mit Computergrafiken verwendet, und wir werden sie in dieser App sehen.

Fügen Sie Ihrer handleTap() -Methode die folgenden Zeilen hinzu, und wir werden sie im Detail behandeln:

Bevor Sie in die erste Codezeile einsteigen, ist es wichtig zu verstehen, dass der zuvor durchgeführte Treffer-Test einen Typ von matrix_float4x4 zurückgibt, bei dem es sich im Wesentlichen um eine Vier-mal-Vier-Matrix von Float-Werten handelt. Da wir uns jedoch in SceneKit befinden, müssen wir es in etwas konvertieren, das SceneKit verstehen kann - in diesem Fall in eine SCNMatrix4.

Dann werden wir diese Matrix verwenden, um einen SCNVector3 zu erstellen, der, wie der Name schon sagt, ein Vektor mit drei Komponenten ist. Wie Sie vielleicht erraten haben, sind diese Komponenten x, y und z, um uns eine Position im Raum zu geben. transform.m41, transform.m42 und transform.m43 sind die relevanten Koordinatenwerte für die drei Komponentenvektoren.

Zuletzt verwenden wir die zuvor erstellte newSphere() -Methode zusammen mit den Standortinformationen, die wir aus dem Berührungsereignis analysiert haben, um eine Kugel zu erstellen und sie einer Konstanten namens sphere zuzuweisen.

Beheben des Double-Tap-Fehlers

Jetzt haben Sie möglicherweise einen kleinen Fehler in unserem Code festgestellt. Wenn der Benutzer weiter tippt, wird immer wieder eine neue Kugel erstellt. Wir wollen das nicht, weil es schwierig ist zu bestimmen, welche Kugeln gemessen werden müssen. Außerdem ist es für den Benutzer schwierig, alle Bereiche im Auge zu behalten!

Lösen mit Arrays

Der erste Schritt, um dies zu lösen, besteht darin, ein Array am Anfang der Klasse zu erstellen.

Dies ist ein Array von SCNNodes, da dies der Typ ist, den wir von unserer newSphere() -Methode zurückgegeben haben, die wir zu Beginn dieses Lernprogramms erstellt haben. Später werden wir die Kugeln in dieses Array einfügen und überprüfen, wie viele es gibt. Auf dieser Grundlage können wir ihre Zahlen manipulieren, indem wir sie entfernen und hinzufügen.

Optionale Bindung

Als Nächstes verwenden wir eine Reihe von if-else-Anweisungen und for-Schleifen, um herauszufinden, ob das Array Kugeln enthält oder nicht. Fügen Sie Ihrer App zunächst die folgende optionale Bindung hinzu:

Zuerst prüfen wir, ob das spheres-Array Elemente enthält, und führen den Code in der else-Klausel aus, wenn nicht.

Prüfung der Sphären

Fügen Sie danach dem ersten Teil (dem if-Zweig) Ihrer if-else-Anweisung Folgendes hinzu:

Da wir uns bereits in einem Tap-Event befinden, wissen wir, dass wir eine andere Kugel erschaffen. Wenn es also bereits eine Kugel gibt, müssen wir die Entfernung ermitteln und dem Benutzer anzeigen. Sie können die distance() -Methode für die Kugel aufrufen, da wir später eine Erweiterung von SCNNode erstellen.

Als nächstes müssen wir wissen, ob es bereits mehr als das Maximum von zwei Kugeln gibt. Dazu verwenden wir nur die count-Eigenschaft unseres spheres-Arrays und eine if-Anweisung. Wir durchlaufen alle Kugeln im Array und entfernen sie aus der Szene. (Keine Sorge, wir werden einige später wieder sehen.)

Da wir uns bereits in der if-Anweisung befinden, die besagt, dass mehr als zwei Kugeln vorhanden sind, können wir die dritte im Array entfernen, um sicherzustellen, dass immer nur zwei im Array verbleiben.

Hinzufügen der Kugeln

Schließlich wissen wir in der else-Klausel, dass das spheres-Array leer ist. Wir müssen also nur die Sphäre hinzufügen, die wir zum Zeitpunkt des Methodenaufrufs erstellt haben. Fügen Sie in Ihrer else-Klausel Folgendes hinzu:

Yay! Wir haben gerade die Kugel zu unserem spheres array hinzugefügt, und unser Array ist bereit für das nächste Tippen. Wir haben unser Array jetzt mit den Kugeln vorbereitet, die auf dem Bildschirm angezeigt werden sollen. Fügen wir diese nun einfach dem Array hinzu.

Fügen Sie diesen Code hinzu, um die Kugeln zu durchlaufen und hinzuzufügen:

Dies ist nur eine einfache for-Schleife, und wir fügen die Kugeln(SCNNode) als untergeordnetes Element des Wurzelknotens der Szene hinzu. In SceneKit ist dies die bevorzugte Methode zum Hinzufügen von Elementen.

Vollständige Methode

So sollte die endgültige handleTap() -Methode aussehen:

Entfernungen berechnen

Wenn Sie sich erinnern, haben wir auf unserem SCNNode, der Kugel, eine distance(to:) methode aufgerufen, und ich bin sicher, dass Xcode Sie anschreit, weil Sie eine nicht deklarierte Methode verwendet haben. Beenden wir das jetzt, indem wir eine Erweiterung der SCNNode-Klasse erstellen.

Führen Sie zum Erstellen einer Erweiterung außerhalb Ihrer ViewController-Klasse einfach die folgenden Schritte aus:

Auf diese Weise können Sie einfach die Klasse ändern (es ist, als würden Sie die eigentliche Klasse bearbeiten). Dann fügen wir eine Methode hinzu, die den Abstand zwischen zwei Knoten berechnet.

Hier ist die Funktionsdeklaration, um das zu tun:

Wenn Sie sehen, gibt es einen Parameter, der ein anderer SCNNode ist, und der als Ergebnis einen CGFloat zurückgibt. Fügen Sie dies für die eigentliche Berechnung Ihrer Funktion distance() hinzu:

Die ersten drei Codezeilen subtrahieren die x-, y- und z-Positionen des aktuellen SCNNode von den Koordinaten des als Parameter übergebenen Knotens. Wir werden diese Werte später in die Entfernungsformel einfügen, um ihre Entfernung zu erhalten. Da ich das Ergebnis in Zoll erhalten möchte, habe ich eine Konstante für die Konvertierungsrate zwischen Metern und Zoll erstellt, um sie später einfach konvertieren zu können.

Um die Entfernung zwischen den beiden Knoten zu ermitteln, denken Sie an Ihre Mathematikklasse in der Mittelschule zurück: Sie können sich an die Entfernungsformel für die kartesische Ebene erinnern. Hier wenden wir es auf Punkte im dreidimensionalen Raum an.

Schließlich geben wir den Wert multipliziert mit dem Zollumrechnungsverhältnis zurück, um die entsprechende Maßeinheit zu erhalten. Wenn Sie außerhalb der USA leben, können Sie es in Metern belassen oder auf Wunsch in Zentimeter umrechnen.

Abschluss

Nun, das ist ein Wrap! So sollte Ihr endgültiges Projekt aussehen:

Final result showing the measuring app in actionFinal result showing the measuring app in actionFinal result showing the measuring app in action

Wie Sie sehen können, sind die Maße nicht perfekt, aber es wird angenommen, dass ein 15-Zoll-Computer etwa 14,998 Zoll groß ist, also ist es nicht schlecht!

Sie wissen jetzt, wie Sie Entfernungen mit Apples neuer Bibliothek ARKit messen können. Diese App kann für viele Dinge verwendet werden, und ich fordere Sie auf, über verschiedene Möglichkeiten nachzudenken, wie dies in der realen Welt verwendet werden kann, und Ihre Gedanken in den Kommentaren unten zu hinterlassen.

Schauen Sie sich auch das GitHub-Repo für diese App an. Und während Sie noch hier sind, lesen Sie unsere anderen iOS-Entwicklungs-Tutorials hier auf Envato Tuts+!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.