Eine Szene erstellen und mit ihr interagieren

Auf dieser Seite finden Sie allgemeine Tipps zum Erstellen eines Scene und zu seiner Interaktion.

Szene ohne AR rendern

Mit der Klasse SceneView können Sie eine 3D-Szene rendern, ohne die Kamera des Geräts oder eine AR-Sitzung nutzen zu müssen. Das ist nützlich, um eine Vorschau von 3D-Objekten in Ihrer App ohne AR anzusehen oder alternative Funktionen auf Geräten bereitzustellen, die AR nicht unterstützen.

Standardmäßig zeigt SceneView das Bild der AR-Kamera nicht an und verwendet einen schwarzen Hintergrund. Wenn Sie die Hintergrundfarbe ändern möchten, können Sie entweder view.setBackgroundColor() aufrufen oder eine Hintergrundfarbe wie unten dargestellt im Layout festlegen:

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

Der Camera-Knoten der Szene wird am Ursprung platziert (Position 0,0,0) und nach vorne (Richtung 0,0,-1). Da die Position und die Drehung der Kamera nicht mit dem AR-Bewegungstracker verknüpft ist, können Sie sie wie jeden anderen Knoten neu positionieren oder animieren.

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

Interaktionen

Umgang mit Nutzerberührung

Wenn der Nutzer den Bildschirm berührt, wird das Touch-Ereignis von Sceneform an die Ereignis-Handler und Listener weitergegeben, die an Knoten und die Szene angehängt sind. Dieses Verhalten ähnelt dem Vorgang von Touch-Ereignissen für Aufrufe und Aufrufgruppen in Android. Hier ist die Verbreitungsreihenfolge:

  1. Das Ereignis wird an einen beliebigen Listener gesendet, der in scene.addOnPeekTouchListener() hinzugefügt wird.

    Das ist ähnlich wie viewGroup.intercept(), nur dass die Szene im Peek-Touch-Listener das Ereignis nicht verarbeiten kann.

  2. Das Ereignis wird an den ersten Knoten übergeben, mit dem sich der Strahl schneidet.

    • Der Knoten kann das Ereignis nutzen, indem er einen onTouchEvent()-Methodensatz definiert, der true zurückgibt.
    • Wenn die Methode onTouchEvent() false zurückgibt oder kein Listener definiert ist, wird das Ereignis an den übergeordneten Knoten weitergegeben. Dieser Vorgang wird fortgesetzt, bis das Ereignis verarbeitet oder die Szene erreicht wird.
  3. Wenn kein Listener das Ereignis verarbeitet hat, wird es an scene.onTouchListener() übergeben.

Bewegungen erkennen

ArFragment unterstützt Gesten zum Tippen (Auswählen), Ziehen (Verschieben), Auseinander- und Zusammenziehen (Skalieren) und Drehen (Drehen).

Beispiel: HelloSceneformActivity.java in der Beispielanwendung HelloSceneform.

Benutzerdefinierte Knoten erstellen

Ähnlich wie bei benutzerdefinierten Android-Ansichten können Sie zum Erstellen benutzerdefinierter Knoten eine Unterklasse von Node erstellen. In den folgenden Situationen können Sie einen benutzerdefinierten Knoten erstellen:

  • Sie möchten auf Ereignisse im Knotenlebenszyklus zugreifen, z. B. onUpdate(), onActivate und onDeactivate().
  • Sie möchten einen Knoten erstellen, der aus einer Gruppe von Knoten besteht.
  • Sie duplizieren viel Code und können ihn in eine Unterklasse umwandeln.

Ein Beispiel findest du in der Beispiel-App für das Sonnensystem unter Planet.java.

Knoten animieren

Es gibt zwei Möglichkeiten, Knoten zu animieren:

Mit ObjectAnimator animieren

Beispiel für die Animation einer Spotlight-Intensität:

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

Weitere Informationen finden Sie unter Animation mit ObjectAnimator.

In Update aktualisieren

Überschreiben Sie den onUpdate() des Knotens, um ihn Frame für Frame zu animieren. Im folgenden Beispiel wird von Planet.java in der Beispiel-App Solar System die Infocard in jedem Frame an den Nutzer angepasst, auch wenn der Planet sich dreht.

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

Lampen hinzufügen

Lights kann an jeden Knoten im Ambiente angehängt werden. Standardmäßig enthält jede Sceneform-Szene einen Sun-Knoten, an dem ein gerichtetes Licht angehängt ist.

Sie können die Sonne ändern oder es selbst zu einer Szene hinzufügen. Im folgenden Beispiel wird ein Spotlight hinzugefügt:

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

Rufen Sie dann setLight() auf, um es an einen Knoten anzuhängen.

Visualisierung des Flugzeugs anpassen

Standardmäßig hat die Szene einen PlaneRenderer, der Planes markiert, wenn sie von ARCore erkannt wurden. Sie sieht so aus:

Sie können das Standardmaterial und die Textur ändern, die zum Rendern erkannter Ebenen verwendet werden. So änderst du die Textur:

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

Schatten

Schatten wirken in der Welt zu sehen und geben den Nutzern ein Gefühl von Tiefe und Raum.

In Sceneform gibt es Objekte, die Schatten werfen und Schatten empfangen können.

  • Lights und Renderables können Schatten werfen

    Standardmäßig ist das Schatten-Streaming auf der Sonne aktiviert, aber nicht für die Beleuchtung. Rufe setShadowCastingEnabled() auf, um ihn zu aktivieren.

  • Renderables und PlaneRenderer können Schatten erhalten.

    Der Empfang von Schatten ist standardmäßig aktiviert. Rufe setShadowReceiver() an, um die Funktion zu deaktivieren.

Wenn ein renderbares Objekt sowohl Schatten wirft als auch empfangen kann, kann es selbst Schatten werfen.