Crea, controla y administra entidades

El SDK de Jetpack XR te permite usar Jetpack SceneCore para crear, controlar y administrar instancias de Entity, como modelos 3D, video estereoscópico y PanelEntity con Jetpack SceneCore.

Jetpack SceneCore adopta dos patrones de arquitectura comunes para admitir el desarrollo en 3D: un grafo de escenas y un sistema de componentes de entidades (ECS).

Usa el grafo de escenas para crear y controlar entidades

Para crear y controlar objetos en el espacio 3D, debes usar la API de Session de Jetpack SceneCore para obtener acceso al grafo de escenas. El grafo de escenas se alinea con el mundo real del usuario y te permite organizar entidades 3D, como paneles y modelos 3D, en una estructura jerárquica y mantener el estado de esas entidades.

Una vez que hayas obtenido acceso al grafo de escenas, puedes usar las APIs de Jetpack Compose para XR para crear una IU espacial (por ejemplo, SpatialPanel y Orbiter) dentro del grafo de escenas. En el caso del contenido 3D, como los modelos 3D, puedes acceder directamente a la sesión. Para obtener más información, consulta Acerca de ActivitySpace en esta página.

Sistema de componentes de entidades

Un sistema de componentes de entidad sigue el principio de composición en lugar de la herencia. Puedes expandir el comportamiento de las entidades si adjuntas componentes que definen el comportamiento, lo que te permite aplicar el mismo comportamiento a diferentes tipos de entidades. Para obtener más información, consulta Cómo agregar comportamiento común a las entidades en esta página.

Información acerca de ActivitySpace

Cada Session tiene un ActivitySpace que se crea automáticamente con el Session. El ActivitySpace es el Entity de nivel superior en el gráfico de escena.

ActivitySpace representa un espacio tridimensional con un sistema de coordenadas de mano derecha (el eje x apunta a la derecha, el eje y apunta hacia arriba y el eje z hacia atrás en relación con el origen) y con metros para unidades que coinciden con el mundo real. El origen de ActivitySpace es algo arbitrario (ya que los usuarios pueden restablecer la posición de ActivitySpace en el mundo real), por lo que se recomienda posicionar el contenido en relación con los demás en lugar de hacerlo en relación con el origen.

Cómo trabajar con entidades

Las entidades son fundamentales para SceneCore. Casi todo lo que el usuario ve y con lo que interactúa son entidades que representan paneles, modelos 3D y mucho más.

Como ActivitySpace es el nodo de nivel superior del grafo de escena, de forma predeterminada, todas las entidades nuevas se colocan directamente en ActivitySpace. Para reubicar entidades a lo largo del grafo de escenas, llama a setParent o addChild.

Las entidades tienen algunos comportamientos predeterminados para elementos que son universales para todas las entidades, como cambiar la posición, la rotación o la visibilidad. Las subclases específicas de Entity, como GltfEntity, tienen comportamientos adicionales que admiten la subclase.

Cómo manipular entidades

Cuando realices un cambio en una propiedad Entity que pertenezca a la clase Entity base, el cambio se aplicará en cascada a todos sus elementos secundarios. Por ejemplo, ajustar el Pose de un Entity superior hace que todos sus elementos secundarios tengan el mismo ajuste. Hacer un cambio en un Entity secundario no afecta a su elemento superior.

Un Pose representa la ubicación y la rotación de la entidad en el espacio 3D. La ubicación es un Vector3 que consta de posiciones numéricas x, y, z. La rotación se representa con un elemento Quaternion. La posición de un Entity siempre es relativa a su entidad superior. En otras palabras, un Entity cuya posición es (0, 0, 0) se colocará en el origen de su entidad superior.

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

Para cambiar la visibilidad de un Entity, usa setHidden.

//hide the entity
entity.setHidden(true)

Para cambiar el tamaño de un Entity y mantener su forma general, usa setScale.

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

Agrega un comportamiento común a las entidades

Puedes usar los siguientes componentes para agregar un comportamiento común a las entidades:

La creación de instancias de componentes debe realizarse a través del método de creación apropiado en la clase Session. Por ejemplo, para crear un ResizableComponent, llama a session.createResizableComponent().

Para agregar el comportamiento específico del componente a un Entity, usa el método addComponent().

Usa MovableComponent para que el usuario pueda mover una entidad

El MovableComponent permite que el usuario mueva un Entity. También puedes especificar si la entidad se puede fijar a un tipo de superficie, como superficies horizontales o verticales, o superficies semánticas específicas, como una mesa, una pared o un techo. Para especificar opciones de ancla, especifica un conjunto de AnchorPlacement cuando crees el MovableComponent.

Este es un ejemplo de una entidad que se puede mover y fijar a cualquier superficie vertical y solo a las superficies horizontales del piso y el techo.

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)

Usa ResizableComponent para que el usuario pueda cambiar el tamaño de una entidad

ResizableComponent permite a los usuarios cambiar el tamaño de un Entity. El ResizableComponent incluye indicadores de interacción visual que invitan al usuario a cambiar el tamaño de un Entity. Cuando creas el ResizeableComponent, puedes especificar un tamaño mínimo o máximo (en metros). También tienes la opción de especificar una relación de aspecto fija cuando cambias el tamaño para que el ancho y la altura cambien de tamaño de forma proporcional entre sí.

Este es un ejemplo del uso de ResizableComponent con una relación de aspecto fija:

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

Usa InteractableComponent para capturar eventos de entrada del usuario

InteractableComponent te permite capturar eventos de entrada del usuario, como cuando interactúa con un Entity o coloca el cursor sobre él. Cuando creas un InteractableComponent, debes especificar un InputEventListener para recibir los eventos de entrada. Cuando el usuario realice cualquier acción de entrada, se llamará al método onInputEvent con la información de entrada específica proporcionada en el parámetro InputEvent.

Para obtener una lista completa de todas las constantes InputEvent, consulta la documentación de referencia.

En el siguiente fragmento de código, se muestra un ejemplo del uso de un InteractableComponent para aumentar el tamaño de una entidad con la mano derecha y disminuirlo con la izquierda.

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)