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 architetturali comuni per supportare lo sviluppo 3D: un grafo della scena e un sistema entità-componente (ECS).
Utilizzare il grafico della scena per creare e controllare le entità
Per creare e controllare gli oggetti nello spazio 3D, puoi utilizzare l'API Session di Jetpack SceneCore per accedere al grafico della scena. Il grafico della scena si allinea al mondo reale dell'utente e ti consente di organizzare entità 3D come pannelli e modelli 3D in una struttura gerarchica e di conservare lo stato di queste entità.
Una volta ottenuto l'accesso al grafico della scena, puoi utilizzare le API in Jetpack Compose per XR per creare un'interfaccia utente spaziale (ad esempio, istanze SpatialPanel
e Orbiter
) all'interno del grafico 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 a componenti di entità
Un sistema di componenti di entità segue il principio della composizione rispetto all'ereditarietà. Puoi espandere il comportamento delle entità collegando componenti che definiscono il comportamento, il che ti consente di applicare lo stesso comportamento a diversi tipi di entità. Per saperne di più, consulta la sezione Aggiungere un comportamento comune alle entità in questa pagina.
Informazioni su ActivitySpace
Ogni Session
ha un ActivitySpace
creato automaticamente
con il Session
. ActivitySpace
è il Entity
di primo livello nel grafico
della scena.
ActivitySpace rappresenta uno spazio tridimensionale con un sistema di coordinate destrorso (l'asse x punta a destra, l'asse y punta verso l'alto e l'asse z punta all'indietro rispetto all'origine) e con unità di misura in metri che corrispondono al mondo reale. L'origine di ActivitySpace
è in qualche modo arbitraria (in quanto gli utenti possono
reimpostare la posizione di ActivitySpace
nel mondo reale), pertanto è
consigliabile posizionare i contenuti in relazione tra loro anziché in relazione
all'origine.
Utilizzare 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 grafico della scena, per impostazione predefinita,
tutte le nuove entità vengono inserite direttamente in ActivitySpace
. Puoi riposizionare
le entità lungo il grafico della scena chiamando setParent()
o
addChild()
.
Le entità hanno alcuni comportamenti predefiniti per elementi universali per tutte le entità, come la modifica di posizione, rotazione o visibilità. Sottoclassi Entity
specifiche, come GltfModelEntity
, 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 viene applicata a tutti i relativi elementi secondari. Ad esempio,
se modifichi il Pose
di un Entity
principale, tutti i relativi elementi secondari
avranno lo stesso aggiustamento. Una modifica apportata a 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 e 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 relativa entità principale.
// 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))
Per modificare la visibilità di un Entity
, utilizza setHidden()
.
// Hide the entity entity.setHidden(true)
Per ridimensionare un Entity
mantenendone la forma complessiva, utilizza setScale()
.
// Double the size of the entity entity.setScale(2f)
Aggiungere un comportamento comune alle entità
Puoi utilizzare i seguenti componenti per aggiungere un comportamento comune alle entità:
MovableComponent
: consente all'utente di spostare le entitàResizableComponent
: consente all'utente di ridimensionare le entità con pattern UI coerentiInteractableComponent
: consente di acquisire eventi di input per interazioni personalizzate
L'istanza dei componenti deve essere creata tramite il metodo di creazione appropriato nella classe Session
. Ad esempio, per creare un ResizableComponent
, chiama
ResizableComponent.create()
.
Per aggiungere il comportamento specifico del componente a un Entity
, utilizza il metodo
addComponent()
.
Utilizzare MovableComponent
per rendere un'entità spostabile dall'utente
Il 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 oppure a superfici semantiche specifiche come tavolo, parete
o soffitto. Per specificare le opzioni di ancoraggio, specifica un insieme di AnchorPlacement
quando crei MovableComponent
.
Ecco un esempio di entità che può essere spostata e ancorata a qualsiasi superficie verticale e solo alle superfici orizzontali del pavimento e del soffitto.
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)
Man mano che l'utente sposta l'entità, il parametro scaleInZ
regola automaticamente la
scala dell'entità man mano che si allontana dall'utente in modo simile a come
i pannelli vengono scalati dal sistema nello spazio della casa. A causa della natura "a cascata"
del sistema di componenti delle entità, la scala dell'elemento principale influirà su tutti i relativi
elementi secondari.
Utilizza ResizableComponent
per rendere ridimensionabile un'entità
Il ResizableComponent
consente agli utenti di ridimensionare un Entity
. ResizableComponent
include segnali visivi di interazione che invitano l'utente a ridimensionare un Entity
. Quando crei il ResizableComponent
, puoi specificare una
dimensione minima o massima (in metri). Hai anche la possibilità di specificare proporzioni fisse durante il ridimensionamento, in modo che la larghezza e l'altezza vengano ridimensionate in modo proporzionale tra loro.
Quando utilizzi ResizableComponent
, devi specificare un ResizeListener
per rispondere a eventi di ridimensionamento specifici come onResizeUpdate
o
onResizeEnd
.
Ecco un esempio di utilizzo di ResizableComponent
con proporzioni fisse su
un 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)
Utilizzare InteractableComponent
per acquisire gli eventi di input dell'utente
InteractableComponent
consente di acquisire gli eventi di input dell'utente,
ad esempio quando l'utente interagisce 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 input, viene chiamato il metodo
onInputEvent
con le informazioni di input specifiche
fornite nel parametro InputEvent
.
InputEvent.action
specifica il tipo di input, ad esempio passaggio del mouse o tocco su un'entitàInputEvent.source
specifica la provenienza dell'input, ad esempio input manuale o controllerInputEvent.pointerType
specifica se l'input proviene dalla mano destra o dalla mano sinistra
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.
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)