Creare, controllare e gestire entità

L'SDK Jetpack XR ti consente di utilizzare Jetpack SceneCore per creare, controllare e gestire istanze Entity come modelli 3D, video stereoscopici e PanelEntity utilizzando Jetpack SceneCore.

Jetpack SceneCore adotta due pattern di architettura comuni per supportare lo sviluppo 3D: un grafo della scena e un sistema di componenti-entità (ECS).

Utilizzare la scena di grafo per creare e controllare le entità

Per creare e controllare gli oggetti nello spazio 3D, devi utilizzare l'API Session di Jetpack SceneCore per accedere al grafo della scena. La scena è in linea con il mondo reale dell'utente e ti consente di organizzare entità 3D come pannelli e modelli 3D in una struttura gerarchica e di mantenere lo stato di queste entità.

Dopo aver ottenuto l'accesso al grafo della scena, puoi utilizzare le API di Jetpack Compose per XR per creare un'interfaccia utente spaziale (ad esempio SpatialPanel e Orbiter) all'interno del grafo della scena. Per i contenuti 3D, come i modelli 3D, puoi accedere direttamente alla sessione. Per saperne di più, consulta la sezione Informazioni su ActivitySpace in questa pagina.

Sistema di componenti delle entità

Un sistema di entità e componenti segue il principio della composizione rispetto all'eredità. Puoi espandere il comportamento delle entità collegando componenti che definiscono il comportamento, in modo da applicare lo stesso comportamento a diversi tipi di entità. Per saperne di più, consulta Aggiungere un comportamento comune alle entità in questa pagina.

Informazioni su ActivitySpace

Ogni Session ha un ActivitySpace che viene creato automaticamente con Session. ActivitySpace è il Entity di primo livello nel grafo della scena.

ActivitySpace rappresenta uno spazio tridimensionale con un sistema di coordinate destrorso (l'asse x punta verso destra, l'asse y verso l'alto e l'asse z all'indietro rispetto all'origine) e con metri per le unità corrispondenti al mondo reale. L'origine di ActivitySpace è in qualche modo arbitraria (poiché gli utenti possono reimpostare la posizione di ActivitySpace nel mondo reale), pertanto è consigliabile posizionare i contenuti in base a un punto di riferimento diverso dall'origine.

Lavorare con le entità

Le entità sono fondamentali per SceneCore. Quasi tutto ciò che l'utente vede e con cui interagisce sono entità che rappresentano pannelli, modelli 3D e altro ancora.

Poiché ActivitySpace è il nodo di primo livello del grafo della scena, per impostazione predefinita tutte le nuove entità vengono inserite direttamente in ActivitySpace. Puoi spostare le entità lungo il grafo della scena chiamando setParent o addChild.

Le entità hanno alcuni comportamenti predefiniti per elementi universali per tutte le entità, ad esempio la modifica della posizione, della rotazione o della visibilità. Classi di Entity particolari, come GltfEntity, hanno comportamenti aggiuntivi che supportano la sottoclasse.

Manipolare le entità

Quando apporti una modifica a una proprietà Entity che appartiene alla classe Entity di base, la modifica verrà applicata a cascata a tutti i relativi elementi secondari. Ad esempio, se modifichi Pose di un elemento principale Entity, tutti i suoi elementi secondari avranno lo stesso aggiustamento. La modifica di un Entity secondario non influisce su quello principale.

Un Pose rappresenta la posizione e la rotazione dell'entità nello spazio 3D. La posizione è un Vector3 costituito da posizioni numeriche x, y, z. La rotazione è rappresentata da un Quaternion. La posizione di un Entity è sempre relativa alla sua entità principale. In altre parole, un Entity la cui posizione è (0, 0, 0) verrà posizionato all'origine della sua entità principale.

//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))

Per modificare la visibilità di un Entity, utilizza setHidden.

//hide the entity
entity.setHidden(true)

Per ridimensionare un Entity mantenendone la forma generale, utilizza setScale.

//double the size of the entity
entity.setScale(2f)

Aggiungere un comportamento comune alle entità

Per aggiungere un comportamento comune alle entità, puoi utilizzare i seguenti componenti:

L'inizializzazione dei componenti deve essere eseguita tramite il metodo di creazione appropriato nella classe Session. Ad esempio, per creare un ResizableComponent, chiama session.createResizableComponent().

Per aggiungere il comportamento specifico del componente a un Entity, utilizza il metodo addComponent().

Utilizza MovableComponent per rendere un'entità spostabile dall'utente

MovableComponent consente all'utente di spostare un Entity. Puoi anche specificare se l'entità può essere ancorata a un tipo di superficie, come superfici orizzontali o verticali, o a superfici semantiche specifiche come tavolo, parete o soffitto. Per specificare le opzioni di ancoraggio, specifica un insieme di AnchorPlacement durante la creazione del MovableComponent.

Ecco un esempio di entità che può essere spostata e ancorata a qualsiasi superficie verticale e solo a quelle orizzontali del pavimento e del soffitto.

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)

Utilizza ResizableComponent per rendere un'entità ridimensionabile dall'utente

ResizableComponent consente agli utenti di ridimensionare un Entity. Il ResizableComponent include indicatori di interazione visiva che invitano l'utente a ridimensionare un Entity. Quando crei il ResizeableComponent, puoi specificare una dimensione minima o massima (in metri). Hai anche la possibilità di specificare un formato fisso durante il ridimensionamento in modo che la larghezza e l'altezza vengano ridimensionate proporzionalmente l'una all'altra.

Ecco un esempio di utilizzo di ResizableComponent con un'area immagine fissa:

val resizableComponent = xrSession.createResizableComponent()
resizableComponent.minimumSize = Dimensions(177f, 100f, 1f )
resizableComponent.fixedAspectRatio = 16f / 9f //Specify a 16:9 aspect ratio
entity.addComponent(resizableComponent)

Utilizzare InteractableComponent per acquisire gli eventi di input utente

InteractableComponent ti consente di acquisire gli eventi di input dell'utente, ad esempio quando interagisce con un Entity o passa il mouse sopra un Entity. Quando crei un InteractableComponent, devi specificare un InputEventListener per ricevere gli eventi di input. Quando l'utente esegue un'azione di inserimento, il metodo onInputEvent viene chiamato con le informazioni specifiche sull'input fornite nel parametro InputEvent.

Per un elenco completo di tutte le costanti InputEvent, consulta la documentazione di riferimento.

Il seguente snippet di codice mostra un esempio di utilizzo di un InteractableComponent per aumentare le dimensioni di un'entità con la mano destra e diminuirle con la mano sinistra.

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)