Tworzenie, kontrolowanie i zarządzanie elementami

Pakiet Jetpack XR SDK umożliwia korzystanie z Jetpack SceneCore do tworzenia, kontrolowania i zarządzania instancjami Entity, takimi jak modele 3D, filmy stereoskopowePanelEntity za pomocą Jetpack SceneCore.

Jetpack SceneCore korzysta z 2 popularnych wzorów architektonicznych, aby obsługiwać tworzenie grafiki 3D: graficzne przedstawienie scenysystem 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. SpatialPanelOrbiter) 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 Entitynie 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ów
  • ResizableComponent: 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.

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)