Creare e interagire con una scena

Questa pagina contiene suggerimenti comuni per creare una Scene e interagirvi.

Rendering di una scena senza AR

Il corso SceneView ti consente di eseguire il rendering di una scena 3D senza richiedere l'utilizzo della fotocamera del dispositivo o di una sessione AR. È utile per visualizzare l'anteprima degli oggetti 3D nell'app senza AR o per fornire funzionalità alternative sui dispositivi che non supportano l'AR.

Per impostazione predefinita, SceneView non mostra l'immagine dalla fotocamera AR e utilizza uno sfondo nero. Per cambiare il colore dello sfondo, puoi chiamare view.setBackgroundColor() o definire un colore di sfondo nel layout come mostrato di seguito:

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

Il nodo Camera della scena viene posizionato nell'origine (posizione 0,0,0) e rivolto in avanti (direzione 0,0,-1). Poiché la posizione e la rotazione della videocamera non sono collegate al rilevamento del movimento AR, puoi riposizionarla o animarla come qualsiasi altro nodo.

Camera camera = sceneView.getScene().getCamera();
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f));

Interazioni

Gestire il tocco degli utenti

Quando l'utente tocca lo schermo, Sceneform propaga l'evento touch ai gestori di eventi e ai listener collegati ai nodi e alla scena. Questo comportamento è simile alla propagazione degli eventi touch nelle visualizzazioni e nei gruppi di visualizzazioni in Android. Ecco l'ordine di propagazione:

  1. L'evento viene inviato a qualsiasi ascoltatore aggiunto in scene.addOnPeekTouchListener().

    È simile a viewGroup.intercept(), ad eccezione del fatto che l'ascoltatore della scena in anteprima non può consumare l'evento.

  2. L'evento viene passato al primo nodo con cui si incrocia il raggio.

    • Il nodo può consumare l'evento definendo un set di metodi onTouchEvent() che restituisce true.
    • Se il metodo onTouchEvent() restituisce false o non viene definito alcun listener, l'evento viene propagato al genitore del nodo. Questo processo continua fino al consumo dell'evento o fino al raggiungimento della scena.
  3. Infine, se nessun listener ha utilizzato l'evento, questo viene trasmesso a scene.onTouchListener().

Rilevamento dei gesti

ArFragment ha un supporto integrato per gesti di tocco (selezione), trascinamento (spostamento), pizzico (scala) e rotazione (rotazione).

Ad esempio, vedi HelloSceneformActivity.java nell'app di esempio HelloSceneform.

Crea nodi personalizzati

Analogamente alla creazione di viste Android personalizzate, puoi creare nodi personalizzati con la sottoclasse Node. Ecco alcune situazioni in cui potresti voler creare un nodo personalizzato:

  • Vuoi accedere agli eventi nel ciclo di vita dei nodi, ad esempio onUpdate(), onActivate e onDeactivate().
  • Vuoi creare un nodo composto da un gruppo di nodi.
  • Stai duplicando molto codice e puoi includerlo in una sottoclasse.

Per un esempio, vedi Planet.java nell'app di esempio Solar System.

Animazione dei nodi

Esistono due modi per animare i nodi:

Animazione con ObjectAnimator

Ecco un esempio che anima un'intensità di Spotlight:

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();

Per ulteriori informazioni, consulta la sezione Animazione con ObjectAnimator.

Animazione in onUpdate

Sostituisci l'onUpdate() del nodo per animarlo da un frame all'altro. L'esempio seguente, a partire da Planet.java nell'app di esempio Solar System, regola la scheda informativa ogni frame per inquadrare l'utente, anche quando il pianeta ruota.

@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);
}

Aggiungi luci

Lights può essere collegato a qualsiasi nodo nella scena. Per impostazione predefinita, ogni scena Sceneform include un nodo Sun, a cui è collegata una luce direzionale.

Puoi modificare il sole o aggiungere le tue luci a una scena. L'esempio seguente aggiunge un riflettore:

Light spotLightYellow =
    Light.builder(this, Light.Type.FOCUSED_SPOTLIGHT)
        .setColor(new Color(android.graphics.Color.YELLOW))
        .setShadowCastingEnabled(true)
        .build();

Quindi chiama setLight() per collegarlo a un nodo.

Personalizzare la visualizzazione del piano

Per impostazione predefinita, la scena contiene un elemento PlaneRenderer che evidenzia Planes quando sono stati rilevati da ARCore. Ha questo aspetto:

Puoi modificare il materiale e la texture predefiniti utilizzati per visualizzare i piani rilevati. Ecco come modificare la texture:

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));
        });

Ombre

Le ombre fanno apparire i rendering di terra nel mondo e danno agli utenti un senso di profondità e di spazio.

In Sceneform, esistono oggetti che possono castare ombre e oggetti che possono ricevere ombreggiature.

  • Lights e Renderables possono proiettare ombre

    Per impostazione predefinita, la trasmissione delle ombre è attivata sul sole, ma non sulle luci. Chiama il numero setShadowCastingEnabled() per attivarla.

  • Renderables e PlaneRenderer possono ricevere ombre.

    Per impostazione predefinita, è attiva la ricezione shadow. Chiama setShadowReceiver() per disattivarla.

Se un rendering può trasmettere e ricevere ombre, può trasmettere ombra su se stessa.