Créer une scène et interagir avec elle

Cette page contient des conseils courants pour créer un Scene et interagir avec celui-ci.

Afficher une scène sans RA

La classe SceneView vous permet d'afficher une scène 3D sans avoir à utiliser la caméra de l'appareil ni une session de RA. Cette fonctionnalité est utile pour prévisualiser des objets 3D dans votre application sans la RA, ou pour fournir des fonctionnalités alternatives sur des appareils non compatibles avec la RA.

Par défaut, SceneView n'affiche pas l'image de la caméra de RA et utilise un arrière-plan noir. Pour modifier la couleur de l'arrière-plan, vous pouvez appeler view.setBackgroundColor() ou définir une couleur d'arrière-plan dans la mise en page, comme indiqué ci-dessous:

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

Le nœud Camera de la scène est placé à l'origine (position 0,0,0) et orienté vers l'avant (direction 0,0,-1). La position et la rotation de la caméra ne sont pas liées au suivi du mouvement en RA. Vous pouvez donc la repositionner ou l'animer comme n'importe quel autre nœud.

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

Interactions

Gérer les commandes tactiles de l'utilisateur

Lorsque l'utilisateur touche l'écran, Sceneform propage l'événement tactile aux gestionnaires d'événements et aux écouteurs associés aux nœuds et à la scène. Ce comportement est semblable à la manière dont les événements tactiles se propagent dans les vues et les groupes de vues dans Android. Voici l'ordre de propagation:

  1. L'événement est envoyé à tout écouteur ajouté dans scene.addOnPeekTouchListener().

    Cette méthode est semblable à viewGroup.intercept(), si ce n'est que l'écouteur tactile de la scène n'est pas compatible avec l'événement.

  2. L'événement est transmis au premier nœud avec lequel le rayon se croise.

    • Le nœud peut consommer l'événement en définissant un ensemble de méthodes onTouchEvent() qui renvoie true.
    • Si la méthode onTouchEvent() renvoie false ou qu'aucun écouteur n'est défini, l'événement est propagé au parent du nœud. Ce processus se poursuit jusqu'à ce que l'événement soit consommé ou que la scène soit atteinte.
  3. Enfin, si aucun écouteur n'a consommé l'événement, celui-ci est transmis à scene.onTouchListener().

Détecter des gestes

ArFragment est désormais compatible avec les gestes tactiles (sélection), déplacement (glissement), pincement (mise à l'échelle) et rotation (rotation).

Par exemple, consultez HelloSceneformActivity.java dans l'exemple d'application HelloSceneform.

Créer des nœuds personnalisés

Comme pour la création de vues Android personnalisées, vous pouvez créer des nœuds personnalisés en définissant des sous-classes Node. Vous pouvez être amené à créer un nœud personnalisé dans les cas suivants:

  • Vous souhaitez accéder à des événements du cycle de vie du nœud, tels que onUpdate(), onActivate et onDeactivate().
  • Vous souhaitez créer un nœud composé d'un groupe de nœuds.
  • Vous dupliquez beaucoup de code et pouvez l'intégrer à une sous-classe.

Pour obtenir un exemple, consultez Planet.java dans l'exemple d'application du système solaire.

Animer des nœuds

Il existe deux façons d'animer les nœuds:

Animer des objets avec ObjectAnimator

Voici un exemple qui permet d'animer une intensité d'un effet de projecteur:

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

Pour en savoir plus, consultez la page Animer avec ObjectAnimator.

Animer dans onUpdate

Remplacez l'élément onUpdate() du nœud pour l'animer. L'exemple suivant, qui utilise Planet.java dans l'exemple d'application Solar System, ajuste la carte d'informations à chaque image pour qu'elle fasse face à l'utilisateur, même lorsque la planète tourne.

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

Ajouter des lumières

Lights peut être associé à n'importe quel nœud de la scène. Par défaut, chaque scène Sceneform comprend un nœud Sun auquel une lumière directionnelle est associée.

Vous pouvez modifier le soleil ou ajouter vos propres lumières à une scène. L'exemple suivant ajoute un effet de projecteur:

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

Appelez ensuite setLight() pour l'associer à un nœud.

Personnaliser la visualisation du plan

Par défaut, la scène dispose d'un PlaneRenderer qui met en évidence Planes lorsqu'il a été détecté par ARCore. Elle se présente comme suit :

Vous pouvez modifier la matière et la texture par défaut utilisées pour le rendu des surfaces planes détectées. Voici comment modifier 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));
        });

Ombres

Les ombres donnent l'impression que le rendu s'ancre dans le monde et donne aux utilisateurs un peu de profondeur et d'espace.

Dans Sceneform, les objets peuvent caster des ombres et les objets qui peuvent recevoir des ombres.

  • Lights et Renderables peuvent caster des ombres

    Par défaut, la diffusion des ombres est activée sur le soleil, mais pas pour les lumières. Appelez setShadowCastingEnabled() pour l'activer.

  • Renderables et PlaneRenderer peuvent recevoir des ombres.

    Par défaut, la réception en parallèle est activée. Appelez setShadowReceiver() pour la désactiver.

Si un rendu peut caster et recevoir des ombres, il peut projeter des ombres sur lui-même.