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 Orbiter
s) 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.
InputEvent.action
gibt die Art der Eingabe an, z. B. den Mauszeiger auf eine Entität bewegen oder auf eine Entität tippen(ACTION_DOWN).InputEvent.source
gibt an, woher die Eingabe stammt, z. B. hand oder controllerInputEvent.pointerType
gibt an, ob die Eingabe von der rechten oder linken Hand stammt
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)