Esta página contiene sugerencias comunes para compilar un Scene
e interactuar con él.
Cómo renderizar una escena sin RA
La clase SceneView
te permite renderizar una escena en 3D sin necesidad de usar la cámara del dispositivo ni de una sesión de RA. Esto es útil para obtener una vista previa de objetos 3D en tu app sin RA o proporcionar funcionalidades alternativas en dispositivos que no admiten RA.
De forma predeterminada, SceneView
no muestra la imagen de la cámara de RA y usa un fondo negro. Para cambiar el color del fondo, puedes llamar a view.setBackgroundColor()
o definir un color de fondo en el diseño, como se muestra a continuación:
<com.google.ar.sceneform.SceneView
android:id="@+id/scene_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/deep_teal"/>
El nodo Camera
de la escena se ubica en el origen (posición 0,0,0) y hacia adelante (dirección 0,0-1). Debido a que la posición y la rotación de la cámara no están vinculadas al seguimiento de movimiento de RA, puedes cambiar su posición o animación como en cualquier otro nodo.
Camera camera = sceneView.getScene().getCamera();
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f));
Interacciones
Cómo controlar la función táctil del usuario
Cuando el usuario toca la pantalla, Sceneform propaga el evento táctil a los controladores de eventos y los objetos de escucha adjuntos a los nodos y a la escena. Este comportamiento es similar al modo en que los eventos táctiles se propagan a las vistas y los grupos de vistas en Android. Este es el orden de propagación:
El evento se envía a cualquier objeto de escucha que se agregue en
scene.addOnPeekTouchListener()
.Esto es similar a
viewGroup.intercept()
, excepto que la escena en el objeto de escucha táctil no puede consumir el evento.El evento se pasa al primer nodo con el que el rayo se cruza.
- El nodo puede consumir el evento mediante la definición de un conjunto de métodos
onTouchEvent()
que muestretrue
. - Si el método
onTouchEvent()
muestrafalse
o no se define ningún objeto de escucha, el evento se propaga al elemento superior del nodo. Este proceso continúa hasta que se consume el evento o se alcanza la escena.
- El nodo puede consumir el evento mediante la definición de un conjunto de métodos
Por último, si ningún objeto de escucha ha consumido el evento, este se pasa a
scene.onTouchListener()
.
Cómo detectar gestos
ArFragment
tiene compatibilidad integrada con gestos de presionar (seleccionar), arrastrar (mover), pellizcar (escalar) y girar (girar).
Por ejemplo, consulta HelloSceneformActivity.java
en la app de muestra HelloSceneform.
Crear nodos personalizados
Al igual que con la creación de vistas personalizadas de Android, puedes crear nodos personalizados creando una subclase de Node
. Estas son algunas situaciones en las que se recomienda crear un nodo personalizado:
- Deseas acceder a eventos en el ciclo de vida del nodo, como
onUpdate()
,onActivate
yonDeactivate()
. - Desea crear un nodo compuesto por un grupo de nodos.
- Está duplicando mucho código y puede incluirlo en una subclase.
Para ver un ejemplo, consulta Planet.java
en la app de ejemplo de Sistema solar.
Animar nodos
Hay dos maneras de animar nodos:
- Usa
ObjectAnimator
de la API de animación de Android estándar. - Crea una clase de nodo personalizado y anula
onUpdate()
.
Cómo animar con ObjectAnimator
A continuación, te mostramos un ejemplo que anima la intensidad de un foco:
final int durationInMilliseconds = 1000;
final float minimumIntensity = 1000.0f;
final float maximumIntensity = 3000.0f;
ValueAnimator intensityAnimator =
ObjectAnimator.ofFloat(
spotlightNode.getLight(), "intensity", minimumIntensity, maximumIntensity);
intensityAnimator.setDuration(durationInMilliseconds);
intensityAnimator.setRepeatCount(ValueAnimator.INFINITE);
intensityAnimator.setRepeatMode(ValueAnimator.REVERSE);
intensityAnimator.start();
Para obtener más información, consulta Cómo animar con ObjectAnimator.
Animar en onUpdate
Anula el nodo onUpdate()
del nodo para animarlo de fotograma a fotograma. En el siguiente ejemplo, de Planet.java
en la app de ejemplo Sistema solar, se ajusta la tarjeta de información de cada fotograma para que apunte al usuario, incluso cuando el planeta gira.
@Override
public void onUpdate(FrameTime frameTime) {
Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
Vector3 cardPosition = infoCard.getWorldPosition();
Vector3 direction = Vector3.subtract(cameraPosition, cardPosition);
Quaternion lookRotation = Quaternion.lookRotation(direction, Vector3.up());
infoCard.setWorldRotation(lookRotation);
}
Agregar luces
Lights
se puede adjuntar a cualquier nodo de la escena. De forma predeterminada, cada escena de Sceneform incluye un nodo Sun
, que tiene una luz direccional adjunta.
Puedes modificar el sol o agregar tus propias luces a una escena. En el siguiente ejemplo, se agrega un Spotlight:
Light spotLightYellow =
Light.builder(this, Light.Type.FOCUSED_SPOTLIGHT)
.setColor(new Color(android.graphics.Color.YELLOW))
.setShadowCastingEnabled(true)
.build();
Luego, llama a setLight()
para adjuntarla a un nodo.
Cómo personalizar la visualización del plano
De forma predeterminada, la escena tiene un elemento PlaneRenderer
que destaca Planes
cuando ARCore los detecta. El aspecto resultante será el siguiente:
Puedes modificar el material y la textura predeterminados que se usan para renderizar los planos detectados. Para cambiar la textura, sigue estos pasos:
Texture.Sampler sampler =
Texture.Sampler.builder()
.setMinFilter(Texture.Sampler.MinFilter.LINEAR)
.setWrapMode(Texture.Sampler.WrapMode.REPEAT)
.build();
// R.drawable.custom_texture is a .png file in src/main/res/drawable
Texture.builder()
.setSource(this, R.drawable.custom_texture)
.setSampler(sampler)
.build()
.thenAccept(texture -> {
arSceneView.getPlaneRenderer()
.getMaterial().thenAccept(material ->
material.setTexture(PlaneRenderer.MATERIAL_TEXTURE, texture));
});
Sombras
Las sombras hacen que los elementos renderizados parezcan basados en el mundo y ofrecen a los usuarios una sensación de profundidad y espacio.
En Sceneform, hay objetos que pueden lanzar sombras y objetos que pueden recibir sombras.
Lights
yRenderables
pueden proyectar sombrasDe manera predeterminada, la proyección de sombras está habilitada en el sol, pero no para las luces. Llama a
setShadowCastingEnabled()
para activarla.Renderables
yPlaneRenderer
pueden recibir sombras.De forma predeterminada, la recepción de sombras está habilitada. Llama a
setShadowReceiver()
para desactivarla.
Si un renderizado se proyecta y recibe sombras, puede proyectar sombras sobre sí mismo.