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: einen Szenengraphen und ein Entity-Component-System (ECS).
Szenengraph zum Erstellen und Steuern von Entitäten verwenden
Wenn Sie Objekte im 3D-Raum erstellen und steuern möchten, können Sie mit der Session API von Jetpack SceneCore auf den Szenengraphen zugreifen. Der Szenengraph entspricht der realen Welt des Nutzers und ermöglicht es Ihnen, 3D-Objekte wie Panels und 3D-Modelle in einer hierarchischen Struktur zu organisieren und den Status dieser Objekte zu speichern.
Sobald Sie Zugriff auf den Szenengraphen haben, können Sie die APIs in Jetpack Compose für XR verwenden, um räumliche Benutzeroberflächen zu erstellen, z. B. SpatialPanel
- und Orbiter
-Instanzen im Szenengraphen. 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 Entity-Component-System folgt dem Prinzip der Komposition über 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 Gemeinsames Verhalten für Entitäten hinzufügen.
Informationen zum ActivitySpace
Jede Session
hat eine ActivitySpace
, die automatisch mit der Session
erstellt wird. Die ActivitySpace
ist die Entity
der obersten Ebene im Szenengraphen.
Der ActivitySpace ist ein dreidimensionaler Raum mit einem rechtshändigen Koordinatensystem (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 von ActivitySpace
in der realen Welt zurücksetzen können. Daher empfiehlt es sich, Inhalte relativ zueinander statt relativ zum Ursprung zu positionieren.
Mit Entitäten arbeiten
Entitäten sind ein zentraler Bestandteil von SceneCore. Fast alles, was der Nutzer sieht und mit dem er interagiert, sind Einheiten, die Bereiche, 3D-Modelle und mehr darstellen.
Da ActivitySpace
der Knoten der obersten Ebene des Szenengraphen ist, werden standardmäßig alle neuen Entitäten direkt in ActivitySpace
platziert. Sie können Objekte im Szenengraphen verschieben, indem Sie setParent()
oder addChild()
aufrufen.
Für Entitäten gibt es einige Standardverhalten für Dinge, die für alle Entitäten universell sind, z. B. das Ändern von Position, Drehung oder Sichtbarkeit. Bestimmte Entity
-Unterklassen wie GltfModelEntity
haben zusätzliches Verhalten, das die Unterklasse unterstützt.
Entitäten bearbeiten
Wenn Sie eine Änderung an einer Entity
-Property vornehmen, die zur Basisklasse Entity
gehört, wird die Änderung auf alle untergeordneten Elemente übertragen. Wenn Sie beispielsweise die Pose
eines übergeordneten Entity
anpassen, wird die Anpassung auf alle untergeordneten Elemente angewendet. Wenn Sie eine Änderung in einem untergeordneten Entity
vornehmen, hat das keine Auswirkungen auf das übergeordnete Entity
.
Ein Pose
-Element stellt die Position und Rotation der Entität im 3D-Raum dar. Der Ort ist ein Vector3
, der aus numerischen X-, Y- und Z-Positionen besteht. Die Rotation wird durch eine Quaternion
dargestellt. Die Position eines Entity
ist immer relativ zur übergeordneten Entität. Ein Entity
mit der Position (0, 0, 0) wird also am Ursprung seiner übergeordneten Entität platziert.
// Place the entity forward 2 meters val newPosition = 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))
Wenn Sie die Sichtbarkeit eines Entity
ändern möchten, verwenden Sie setHidden()
.
// 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 gemeinsames Verhalten hinzufügen
Mit den folgenden Komponenten können Sie Entitäten häufig verwendete Verhaltensweisen hinzufügen:
MovableComponent
: Ermöglicht dem Nutzer, Einheiten zu verschieben.ResizableComponent
: Ermöglicht dem Nutzer, die Größe von Einheiten mit einheitlichen UI-Mustern zu ändern.InteractableComponent
: Ermöglicht das Erfassen von Eingabeereignissen für benutzerdefinierte Interaktionen.
Das Instanziieren von Komponenten muss über die entsprechende Erstellungsmethode in der Klasse Session
erfolgen. Wenn Sie beispielsweise ein ResizableComponent
erstellen möchten, rufen Sie ResizableComponent.create()
auf.
Verwenden Sie die Methode addComponent()
, um einem Entity
das spezifische Komponentenverhalten hinzuzufügen.
MovableComponent
verwenden, um eine Entität für Nutzer verschiebbar zu machen
Mit dem MovableComponent
kann der Nutzer das Entity
verschieben. 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 von MovableComponent
eine Reihe von AnchorPlacement
an.
Hier ist ein Beispiel für ein Objekt, das verschoben und an einer beliebigen vertikalen Oberfläche sowie nur an horizontalen Oberflächen von Boden und Decke verankert werden kann.
val anchorPlacement = AnchorPlacement.createForPlanes( planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE), planeSemanticFilter = setOf(PlaneType.VERTICAL) ) val movableComponent = MovableComponent.create( session = session, systemMovable = false, scaleInZ = false, anchorPlacement = setOf(anchorPlacement) ) entity.addComponent(movableComponent)
Wenn der Nutzer das Objekt bewegt, wird der scaleInZ
-Parameter automatisch an die Größe des Objekts angepasst, wenn es sich vom Nutzer entfernt. Das ist ähnlich wie bei der Skalierung von Feldern durch das System im Home-Bereich. Aufgrund der „kaskadierenden“ Natur des Entity-Komponentensystems wirkt sich die Skalierung des übergeordneten Elements auf alle untergeordneten Elemente aus.
ResizableComponent
verwenden, um die Größe einer Entität durch Nutzer anpassen zu lassen
Mit dem ResizableComponent
können Nutzer die Größe eines Entity
ändern. Die ResizableComponent
enthält visuelle Hinweise, die den Nutzer auffordern, die Größe einer Entity
zu ändern. Beim Erstellen der ResizableComponent
können Sie eine Mindest- oder Maximalgröße (in Metern) angeben. Sie haben auch die Möglichkeit, beim Ändern der Größe ein festes Seitenverhältnis anzugeben, sodass Breite und Höhe proportional zueinander angepasst werden.
Wenn Sie die ResizableComponent
verwenden, müssen Sie eine ResizeListener
angeben, um auf bestimmte Größenänderungsereignisse wie onResizeUpdate
oder onResizeEnd
zu reagieren.
Hier ein Beispiel für die Verwendung von ResizableComponent
mit einem festen Seitenverhältnis auf einem SurfaceEntity
:
val resizableComponent = ResizableComponent.create(session) resizableComponent.minimumSize = Dimensions(177f, 100f, 1f) resizableComponent.fixedAspectRatio = 16f / 9f // Specify a 16:9 aspect ratio resizableComponent.addResizeListener( executor, object : ResizeListener { override fun onResizeEnd(entity: Entity, finalSize: Dimensions) { // update the size in the component resizableComponent.size = finalSize // update the Entity to reflect the new size (entity as SurfaceEntity).canvasShape = SurfaceEntity.CanvasShape.Quad(finalSize.width, finalSize.height) } }, ) entity.addComponent(resizableComponent)
InteractableComponent
verwenden, um Nutzer-Eingabeereignisse zu erfassen
Mit InteractableComponent
können Sie Eingabeereignisse vom Nutzer erfassen, z. B. wenn er mit einem Entity
interagiert oder den Mauszeiger darauf bewegt. Wenn Sie ein InteractableComponent
erstellen, müssen Sie ein 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 den Eingabetyp an, z. B. Hovering oder Tapping auf eine Entität.InputEvent.source
gibt an, woher die Eingabe stammt, z. B. Hand oder Controller.InputEvent.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.
Das folgende Code-Snippet zeigt ein Beispiel für die Verwendung eines InteractableComponent
-Objekts, um die Größe eines Objekts mit der rechten Hand zu erhöhen und mit der linken Hand zu verringern.
val executor = Executors.newSingleThreadExecutor() val interactableComponent = InteractableComponent.create(session, 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)