Esta página contém dicas comuns para criar uma Scene
e interagir com ela.
Renderizar uma cena sem RA
A classe SceneView
permite renderizar uma cena 3D sem exigir o uso da câmera do dispositivo nem de uma sessão de RA. Isso é útil para visualizar objetos 3D no seu app sem RA ou para oferecer funcionalidades alternativas em dispositivos incompatíveis com RA.
Por padrão, SceneView
não exibe a imagem da câmera de RA e usa um plano de fundo preto. Para mudar a cor de fundo, você pode chamar view.setBackgroundColor()
ou definir uma cor de plano de fundo no layout, conforme mostrado abaixo:
<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"/>
O nó Camera
da cena é posicionado na origem (posição 0,0,0) e voltado para frente (direção 0,0,-1). Como a posição e a rotação da câmera não estão vinculadas ao rastreamento de movimento de RA, você pode reposicionar ou animar esse elemento como qualquer outro nó.
Camera camera = sceneView.getScene().getCamera();
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f));
Interações
Gerenciar o toque do usuário
Quando o usuário toca na tela, o Sceneform propaga o evento de toque para os manipuladores de eventos e listeners anexados aos nós e à cena. Esse comportamento é semelhante à forma como os eventos de toque se propagam para visualizações e grupos de visualização no Android. Esta é a ordem da propagação:
O evento é enviado para qualquer listener adicionado ao
scene.addOnPeekTouchListener()
.Isso é semelhante a
viewGroup.intercept()
, exceto pelo fato de que a cena do listener de toque de visualização não pode consumir o evento.O evento é transmitido para o primeiro nó em que o raio se cruza.
- O nó pode consumir o evento definindo um conjunto de métodos
onTouchEvent()
que retornatrue
. - Se o método
onTouchEvent()
retornarfalse
ou se nenhum listener estiver definido, o evento será propagado para o pai do nó. Esse processo continua até que o evento seja consumido ou a cena seja alcançada.
- O nó pode consumir o evento definindo um conjunto de métodos
Por fim, se nenhum listener tiver consumido o evento, ele será transmitido para
scene.onTouchListener()
.
Detectar gestos
O ArFragment
tem suporte integrado para gestos de toque (seleção), arrastar (mover), fazer gesto de pinça (escala) e torcer (girar).
Por exemplo, veja HelloSceneformActivity.java
no app de exemplo HelloSceneform.
Criar nós personalizados
Assim como na criação de visualizações personalizadas do Android, é possível criar nós personalizados gerando subclasses de Node
. Veja algumas situações em que talvez você queira criar um nó personalizado:
- Você quer acessar eventos no ciclo de vida do nó, como
onUpdate()
,onActivate
eonDeactivate()
. - Você quer criar um nó composto por um grupo de nós.
- Você está duplicando muito código e pode fatorá-lo em uma subclasse.
Para ver um exemplo, consulte Planet.java
no app de exemplo do sistema Solar (em inglês).
Animar nós
Há duas maneiras de animar nós:
- Use
ObjectAnimator
da API Animation padrão do Android. - Crie uma classe de nó personalizado e modifique
onUpdate()
Animar com o ObjectAnimator
Veja um exemplo que anima a intensidade do destaque:
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 ver mais informações, consulte Animar com o ObjectAnimator.
Animar em onUpdate
Substitua o onUpdate()
do nó
para animá-lo frame a frame. O exemplo a seguir, do Planet.java
no app de exemplo Sistema Solar (link em inglês), ajusta o card de informação a cada frame para o usuário, mesmo quando o 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);
}
Adicionar luzes
Lights
pode ser anexado a qualquer nó no cenário. Por padrão, cada cena do Sceneform inclui um nó Sun
, que tem uma luz direcional anexada.
Você pode modificar o sol ou adicionar suas luzes a uma cena. O exemplo a seguir adiciona um destaque:
Light spotLightYellow =
Light.builder(this, Light.Type.FOCUSED_SPOTLIGHT)
.setColor(new Color(android.graphics.Color.YELLOW))
.setShadowCastingEnabled(true)
.build();
Em seguida, chame setLight()
para anexar a um nó.
Personalizar a visualização do plano
Por padrão, a cena tem um PlaneRenderer
que destaca Planes
quando eles são detectados pelo ARCore. Ela é assim:
É possível modificar o material e a textura padrão usados para renderizar os planos detectados. Veja como alterar a textura:
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
As sombras fazem com que os renderable pareçam aterrissados no mundo e dão aos usuários uma sensação de profundidade e espaço.
No Sceneform, há objetos que podem mostrar sombras e objetos que podem receber sombras.
Lights
eRenderables
podem projetar sombras.Por padrão, o recurso de iluminação de sombra é ativado no sol, mas não em luzes. Ligue para
setShadowCastingEnabled()
e ative.Renderables
ePlaneRenderer
podem receber sombras.Por padrão, o recebimento de sombra está ativado. Chame
setShadowReceiver()
para desativá-la.
Se um elemento renderizável gera e recebe sombras, ele pode lançar sombras em si mesmo.