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:
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.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 restituiscetrue
. - Se il metodo
onTouchEvent()
restituiscefalse
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.
- Il nodo può consumare l'evento definendo un set di metodi
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
eonDeactivate()
. - 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:
- Utilizza
ObjectAnimator
dall'API Android Animation standard. - Crea una classe di nodo personalizzato ed esegui l'override di
onUpdate()
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
eRenderables
possono proiettare ombrePer impostazione predefinita, la trasmissione delle ombre è attivata sul sole, ma non sulle luci. Chiama il numero
setShadowCastingEnabled()
per attivarla.Renderables
ePlaneRenderer
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.