Entitäten erstellen, steuern und verwalten

Mit dem Jetpack XR SDK können Sie mit Jetpack SceneCore Entity-Instanzen wie 3D-Modelle, stereoskopische Videos und PanelEntity erstellen, steuern und verwalten.

Jetpack SceneCore verwendet zwei gängige Architekturmuster zur Unterstützung der 3D-Entwicklung: eine Szenengraphik und ein Entity-Component-System (ECS).

Mit der Szenengraphik Entitäten erstellen und steuern

Wenn Sie Objekte im 3D-Raum erstellen und steuern möchten, müssen Sie die Session API von Jetpack SceneCore verwenden, um Zugriff auf die Szenengraphik zu erhalten. Die Szenengraphik entspricht der realen Welt des Nutzers und ermöglicht es, 3D-Entitäten wie Steuerfelder und 3D-Modelle in einer hierarchischen Struktur zu organisieren und den Status dieser Entitäten zu speichern.

Sobald Sie Zugriff auf die Szenengraphik haben, können Sie mit den APIs in Jetpack Compose for XR eine räumliche Benutzeroberfläche (z. B. SpatialPanel und Orbiters) innerhalb der Szenengraphik erstellen. Bei 3D-Inhalten wie 3D-Modellen können Sie direkt auf die Sitzung zugreifen. Weitere Informationen finden Sie auf dieser Seite unter ActivitySpace.

Entitätskomponentensystem

Ein Entitäts-Komponenten-System folgt dem Prinzip der Komposition anstelle der Vererbung. Sie können das Verhalten von Entitäten erweitern, indem Sie verhaltensdefinierende Komponenten anhängen. So können Sie dasselbe Verhalten auf verschiedene Arten von Entitäten anwenden. Weitere Informationen finden Sie auf dieser Seite unter Entitäten gängiges Verhalten hinzufügen.

ActivitySpace

Jede Session hat eine ActivitySpace, die automatisch mit der Session erstellt wird. Die ActivitySpace ist die oberste Entity in der Szenengraphik.

Der ActivitySpace stellt einen dreidimensionalen Raum mit einem rechtshändigen Koordinatensystem dar (die X-Achse zeigt nach rechts, die Y-Achse nach oben und die Z-Achse nach hinten relativ zum Ursprung) und mit Metern als Einheiten, die der realen Welt entsprechen. Der Ursprung für ActivitySpace ist etwas willkürlich, da Nutzer die Position der ActivitySpace in der realen Welt zurücksetzen können. Daher wird empfohlen, Inhalte relativ zueinander und nicht relativ zum Ursprung zu positionieren.

Mit Entitäten arbeiten

Entitäten sind für SceneCore von zentraler Bedeutung. Fast alles, was der Nutzer sieht und mit dem er interagiert, sind Entitäten, die Bereiche, 3D-Modelle und mehr darstellen.

Da ActivitySpace der Knoten der obersten Ebene der Szenengraphik ist, werden alle neuen Entitäten standardmäßig direkt in ActivitySpace platziert. Sie können Entitäten in der Szenengraphik verschieben, indem Sie setParent oder addChild aufrufen.

Für alle Entitäten gelten einige Standardverhaltensweisen, z. B. das Ändern der Position, der Drehung oder der Sichtbarkeit. Bestimmte Entity-Unterklassen wie GltfEntity haben zusätzliche Verhaltensweisen, die die Unterklasse unterstützen.

Entitäten bearbeiten

Wenn Sie eine Änderung an einer Entity-Property vornehmen, die zur Basisklasse Entity gehört, wird die Änderung kaskadierend auf alle untergeordneten Elemente angewendet. Wenn Sie beispielsweise die Pose eines übergeordneten Elements Entity anpassen, wird die Änderung auf alle untergeordneten Elemente angewendet. Änderungen an einer untergeordneten Entity wirken sich nicht auf die übergeordnete aus.

Ein Pose steht für die Position und Drehung der Entität im 3D-Raum. Der Standort ist ein Vector3, der aus den numerischen Positionen X, Y und Z besteht. Die Drehung wird durch ein Quaternion dargestellt. Die Position eines Entity ist immer relativ zur übergeordneten Entität. Mit anderen Worten: Ein Entity mit der Position (0, 0, 0) wird am Ursprung seiner übergeordneten Entität platziert.

//place the entity forward 2 meters
val modelPosition = Vector3(0f, 0f, -2f)
//rotate the entity by 180 degrees on the up axis (upside-down)
val newOrientation = Quaternion.fromEulerAngles(0f, 0f, 180f)
//update the position and rotation on the entity
entity.setPose(Pose(newPosition, newOrientation))

Mit setHidden können Sie die Sichtbarkeit einer Entity ändern.

//hide the entity
entity.setHidden(true)

Wenn Sie die Größe eines Entity ändern möchten, ohne die Gesamtform zu verändern, verwenden Sie setScale.

//double the size of the entity
entity.setScale(2f)

Entitäten ein gängiges Verhalten hinzufügen

Mit den folgenden Komponenten können Sie Entitäten gängiges Verhalten hinzufügen:

  • MovableComponent: Ermöglicht es Nutzern, Entitäten zu verschieben.
  • ResizableComponent: Ermöglicht es Nutzern, Entitäten mit einheitlichen UI-Mustern zu ändern.
  • InteractableComponent: Hiermit können Sie Eingabeereignisse für benutzerdefinierte Interaktionen erfassen.

Komponenten müssen über die entsprechende Erstellungsmethode in der Session-Klasse instanziiert werden. Wenn Sie beispielsweise einen ResizableComponent erstellen möchten, rufen Sie session.createResizableComponent() auf.

Verwenden Sie die Methode addComponent(), um einem Entity das spezifische Komponentenverhalten hinzuzufügen.

Mit MovableComponent eine Entität vom Nutzer verschiebbar machen

Mit dem MovableComponent kann ein Entity vom Nutzer verschoben werden. Sie können auch angeben, ob das Objekt an einem Oberflächentyp wie horizontalen oder vertikalen Oberflächen oder an bestimmten semantischen Oberflächen wie Tisch, Wand oder Decke verankert werden kann. Wenn Sie Ankeroptionen angeben möchten, geben Sie beim Erstellen des MovableComponent eine Reihe von AnchorPlacement an.

Hier ein Beispiel für ein Element, das an jede vertikale Oberfläche und nur an horizontale Oberflächen von Fußboden und Decke verschoben und verankert werden kann.

val anchorPlacement = AnchorPlacement.createForPlanes(
    planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE),
    planeSemanticFilter = setOf(PlaneType.VERTICAL))

val movableComponent = xrSession.createMovableComponent(
    systemMovable = false,
    scaleInZ = false,
    anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)

Mit ResizableComponent eine Entität für Nutzer veränderbar machen

Mit dem ResizableComponent können Nutzer die Größe eines Entity ändern. Die ResizableComponent enthält visuelle Interaktionshinweise, die den Nutzer dazu auffordern, die Größe einer Entity zu ändern. Beim Erstellen der ResizeableComponent können Sie eine Mindest- oder Maximalgröße (in Metern) angeben. Sie können auch ein festes Seitenverhältnis festlegen, damit sich Breite und Höhe proportional zueinander ändern.

Hier ein Beispiel für die Verwendung von ResizableComponent mit einem festen Seitenverhältnis:

val resizableComponent = xrSession.createResizableComponent()
resizableComponent.minimumSize = Dimensions(177f, 100f, 1f )
resizableComponent.fixedAspectRatio = 16f / 9f //Specify a 16:9 aspect ratio
entity.addComponent(resizableComponent)

InteractableComponent verwenden, um Nutzereingabeereignisse zu erfassen

Mit dem InteractableComponent können Sie Eingabeereignisse des Nutzers erfassen, z. B. wenn er mit einem Entity interagiert oder den Mauszeiger darauf bewegt. Wenn Sie ein InteractableComponent erstellen, müssen Sie eine InputEventListener angeben, um die Eingabeereignisse zu empfangen. Wenn der Nutzer eine Eingabeaktion ausführt, wird die Methode onInputEvent mit den spezifischen Eingabeinformationen aufgerufen, die im Parameter InputEvent angegeben sind.

Eine vollständige Liste aller InputEvent-Konstanten finden Sie in der Referenzdokumentation.

Im folgenden Code-Snippet wird ein Beispiel für die Verwendung eines InteractableComponent gezeigt, um die Größe eines Elements mit der rechten Hand zu vergrößern und mit der linken Hand zu verkleinern.

private val executor by lazy { Executors.newSingleThreadExecutor() }
val interactableComponent = xrSession.createInteractableComponent(executor) {
    //when the user disengages with the entity with their hands
    if (it.source == InputEvent.SOURCE_HANDS && it.action == InputEvent.ACTION_UP) {
        // increase size with right hand and decrease with left
        if (it.pointerType == InputEvent.POINTER_TYPE_RIGHT){
            entity.setScale(1.5f)
        } else if (it.pointerType == InputEvent.POINTER_TYPE_LEFT){
            entity.setScale(0.5f)
        }
    }
}
entity.addComponent(interactableComponent)