Pakiet Jetpack XR SDK 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 grafiki 3D: graficzne przedstawienie sceny i system obiektów i elementó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 encjami
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 grafice 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, orientacji lub widoczności. Niektóre podklasy Entity
, np. GltfEntity
, mają dodatkowe zachowania, które je obsługują.
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, że wszystkie jego elementy podrzędne zostaną zmienione w taki sam sposób. 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 obiektem Vector3
, który składa się z wartości liczbowych x, y i 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 swojego nadrzędnego obiektu.
//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ę session.createResizableComponent()
.
Aby dodać do Entity
określone zachowanie komponentu, użyj metody addComponent()
.
Użycie komponentu MovableComponent, aby umożliwić użytkownikom przenoszenie elementu Entity
MovableComponent
pozwala użytkownikowi przenosić Entity
. Możesz też określić, czy element może być zakotwiczony do typu powierzchni, np. poziomej lub pionowej, czy też 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 mocować 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 = xrSession.createMovableComponent(
systemMovable = false,
scaleInZ = false,
anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)
Użycie komponentu ResizableComponent, aby umożliwić użytkownikom zmianę rozmiaru elementu.
ResizableComponent
pozwala użytkownikom zmieniać rozmiar elementu Entity
. ResizableComponent
zawiera wizualne wskazówki dotyczące interakcji, 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 = xrSession.createResizableComponent()
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ń związanych z danymi wejściowymi użytkownika
InteractableComponent
pozwala rejestrować zdarzenia 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 podawaniem danych, zostanie wywołana metoda onInputEvent
z określonymi informacjami podanymi w parametrze InputEvent
.
InputEvent.action
określa typ danych wejściowych, np. najechanie kursorem lub kliknięcie(ACTION_DOWN) encji.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 prawą ręką i zmniejszania lewą ręką.
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)