Pakiet SDK Jetpack XR umożliwia korzystanie z Jetpack SceneCore do tworzenia, kontrolowania i zarządzania instancjami Entity
, takimi jak modele 3D, filmy stereoskopowe i PanelEntity
za pomocą Jetpack SceneCore.
Jetpack SceneCore korzysta z 2 popularnych wzorów architektonicznych, aby obsługiwać tworzenie aplikacji 3D: graf sceny i system obiektów i komponentów (ECS).
Tworzenie i sterowanie elementami za pomocą grafu sceny
Aby tworzyć obiekty w przestrzeni 3D i nimi zarządzać, musisz użyć interfejsu Session API pakietu Jetpack SceneCore, aby uzyskać dostęp do grafu sceny. Graf scen jest zgodny ze światem rzeczywistym użytkownika i umożliwia grupowanie obiektów 3D, takich jak panele i modele 3D, w strukturze hierarchicznej oraz przechowywanie stanu tych obiektów.
Po uzyskaniu dostępu do grafu sceny możesz używać interfejsów API w Jetpack Compose for XR do tworzenia interfejsu 3D (np. SpatialPanel
i Orbiter
) w grafie sceny. W przypadku treści 3D, takich jak modele 3D, możesz uzyskać dostęp do sesji bezpośrednio. Więcej informacji znajdziesz na tej stronie w sekcji Informacje o ActivitySpace.
System komponentów encji
System obiektów i komponentów stosuje zasadę kompozycji zamiast dziedziczenia. Możesz rozszerzyć działanie elementów, dołączając komponenty definiujące zachowanie, co pozwala stosować to samo zachowanie do różnych typów elementów. Więcej informacji znajdziesz na tej stronie w sekcji Dodawanie typowych zachowań do jednostek.
Informacje o ActivitySpace
Każdy Session
ma ActivitySpace
, który jest automatycznie tworzony wraz z Session
. ActivitySpace
jest najwyższym Entity
w grafice sceny.
ActivitySpace reprezentuje trójwymiarną przestrzeń z prawoskrętnym układem współrzędnych (oś X skierowana jest w prawo, oś Y w górę, a oś Z do tyłu względem punktu wyjścia) i jednostkami w metrach odpowiadającymi rzeczywistemu światu. Początek ActivitySpace
jest nieco arbitralny (użytkownicy mogą zresetować pozycję ActivitySpace
w rzeczywistym świecie), dlatego zalecamy, aby umieszczać treści względem siebie, a nie względem początku.
Praca z entytami
Elementy są kluczowe dla SceneCore. Większość elementów, które użytkownik widzi i z którymi wchodzi w interakcje, to elementy reprezentujące panele, modele 3D itp.
Ponieważ węzeł ActivitySpace
jest węzłem najwyższego poziomu w grafu sceny, domyślnie wszystkie nowe elementy są umieszczane bezpośrednio w węźle ActivitySpace
. Możesz przenosić elementy w grafice sceny, wywołując metodę setParent
lub addChild
.
Elementy mają pewne domyślne zachowania, które są uniwersalne dla wszystkich elementów, takie jak zmiana pozycji, obrotu lub widoczności. Niektóre podklasy Entity
, np. GltfEntity
, mają dodatkowe zachowania, które obsługują tę podklasę.
Manipulowanie elementami
Gdy wprowadzisz zmianę w usłudze Entity
należącej do podstawowej klasy Entity
, zmiana zostanie zastosowana do wszystkich jej podrzędnych usług. Na przykład zmiana Pose
w elemencie nadrzędnym Entity
powoduje zmianę wszystkich jego elementów podrzędnych. Wprowadzenie zmiany w elementach podrzędnych Entity
nie ma wpływu na element nadrzędny.
Pose
reprezentuje lokalizację i obrot elementu w przestrzeni 3D. Lokalizacja jest Vector3
, która składa się z wartości liczbowych x, y, z. Obrót jest reprezentowany przez Quaternion
. Pozycja Entity
jest zawsze określana względem jego nadrzędnego elementu. Innymi słowy, Entity
o pozycji (0,
0, 0) zostanie umieszczony w początku układu współrzędnych elementu nadrzędnego.
//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))
Aby zmienić widoczność Entity
, użyj setHidden
.
//hide the entity
entity.setHidden(true)
Aby zmienić rozmiar Entity
, zachowując ogólny kształt, użyj setScale
.
//double the size of the entity
entity.setScale(2f)
Dodawanie typowych zachowań do elementów
Aby dodać do elementów wspólne zachowanie, możesz użyć tych komponentów:
MovableComponent
: umożliwia użytkownikowi przenoszenie elementówResizableComponent
: umożliwia użytkownikowi zmianę rozmiaru elementów za pomocą spójnych wzorów interfejsu.InteractableComponent
: umożliwia rejestrowanie zdarzeń wejściowych w przypadku niestandardowych interakcji.
Tworzenie wystąpienia komponentów musi odbywać się za pomocą odpowiedniej metody tworzenia w klasie Session
. Na przykład, aby utworzyć element ResizableComponent
, wywołaj funkcję ResizableComponent.create()
.
Aby dodać do elementu Entity
określone zachowanie komponentu, użyj metody addComponent()
.
Użycie komponentu MovableComponent, aby umożliwić użytkownikom przenoszenie elementu.
MovableComponent
pozwala użytkownikowi przenosić Entity
. Możesz też określić, czy element może być zakotwiczony do typu powierzchni, np. poziomej lub pionowej, albo do konkretnych powierzchni semantycznych, takich jak stół, ściana czy sufit. Aby określić opcje kotwicy, podczas tworzenia MovableComponent
podaj zestaw AnchorPlacement
.
Oto przykład obiektu, który można przesuwać i kotwić na dowolnej powierzchni pionowej oraz na poziomych powierzchniach podłogi i sufitu.
val anchorPlacement = AnchorPlacement.createForPlanes(
planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE),
planeSemanticFilter = setOf(PlaneType.VERTICAL))
val movableComponent = MoveableComponent.create(
systemMovable = false,
scaleInZ = false,
anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)
Użyj komponentu ResizableComponent, aby umożliwić użytkownikom zmianę rozmiaru elementu.
ResizableComponent
pozwala użytkownikom zmieniać rozmiar elementu Entity
. ResizableComponent
zawiera wizualne wskazówki, które zachęcają użytkownika do zmiany rozmiaru Entity
. Podczas tworzenia ResizeableComponent
możesz określić minimalny lub maksymalny rozmiar (w metrach). Możesz też określić stały współczynnik proporcji podczas zmiany rozmiaru, aby szerokość i wysokość zmieniały się proporcjonalnie do siebie.
Oto przykład użycia właściwości ResizableComponent
z ustawionym formatem obrazu:
val resizableComponent = ResizableComponent.create(session)
resizableComponent.minimumSize = Dimensions(177f, 100f, 1f)
resizableComponent.fixedAspectRatio = 16f / 9f //Specify a 16:9 aspect ratio
entity.addComponent(resizableComponent)
Wykorzystanie klasy InteractableComponent do rejestrowania zdarzeń wprowadzania danych przez użytkownika
InteractableComponent
umożliwia rejestrowanie zdarzeń wprowadzania danych przez użytkownika, np. gdy użytkownik klika lub najeżdża kursorem na element Entity
.
Podczas tworzenia InteractableComponent
musisz podać parametr InputEventListener
, aby otrzymywać zdarzenia wejściowe. Gdy użytkownik wykona jakieś działanie związane z wprowadzaniem danych, zostanie wywołana metoda onInputEvent
z określonymi informacjami o danych, które są podawane w parametrze InputEvent
.
InputEvent.action
określa typ danych wejściowych, np. najechanie kursorem lub kliknięcie elementu.InputEvent.source
określa, skąd pochodzą dane wejściowe, np. ręce lub kontroler.InputEvent.pointerType
określa, czy dane wejściowe pochodzą z prawej czy z lewej ręki.
Pełną listę wszystkich stałych InputEvent
znajdziesz w dokumentacji.
Poniższy fragment kodu pokazuje przykład użycia InteractableComponent
do zwiększania rozmiaru elementu za pomocą prawej ręki i zmniejszania go za pomocą lewej ręki.
private val executor by lazy { 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)