Page d'accueilFindIt !ContactEclairage 3DLes notions de base

Les extensions JavaTM

Table des matièresHierarchie des classes

CJava

 Animation 3D

Interaction
Animation
Un exemple complet : Du soleil à la lune
Plus loin avec Java 3D...

 

Ce dernier chapitre présente comment animer une scène 3D, suite aux interactions avec l'utilisateur ou en définissant le mouvement des objets.

Interaction

Comportement et stimulus

Java 3D permet d'afficher des images statiques mais fournit aussi un ensemble de mécanismes d'interaction simples à mettre en oeuvre pour permettre d'animer une scène 3D. Toutes les classes gérant les interactions dérivent de la classe Behavior qui décrit un comportement en réponse à un ou plusieurs stimuli de classe WakeupCriterion. Une fois paramétré un noeud de comportement, il suffit de l'ajouter à l'arbre d'une scène 3D pour le rendre actif.
Pour votre information, voici la hiérarchie des classes de stimuli disponibles dans Java 3D :

Les quatre classes WakeupAnd, WakeupAndOfOrs, WakeupOr et WakeupOrOfAnd permettent de combiner entre eux les différents stimuli pour créer des conditions plus complexes.
Pour décrire un comportement particulier, une classe dérivée de Behavior doit implémenter les méthodes suivantes :

  1. Méthode initialize () : dans cette méthode, il faut notamment appeler la méthode wakeupOn (WakeupCondition criteria) en précisant en paramètre quels sont les stimuli auxquels cette classe veut réagir.
    La méthode initialize () est invoquée automatiquement une fois qu'un noeud de classe Behavior est vivant, c'est-à-dire au moment où l'arbre auquel il appartient est rattaché à un univers.
  2. Méthode processStimulus (java.util.Enumeration criteria) : cette méthode est invoquée automatiquement quand survient un stimulus respectant les conditions passées à la méthode wakeupOn (). La méthode processStimulus () décrit les actions à entreprendre suite à la liste de stimuli reçus dans le paramètre criteria.
    Finalement, la méthode wakeupOn () doit être rappelée si la méthode processStimulus () doit être rappelée suite à un nouveau stimulus.
    Le plus souvent cette méthode modifie les propriétés des autres noeuds de l'arbre de la scène : par exemple, en réponse au mouvement de la souris, une classe de comportement peut modifier un groupe de transformation pour déplacer des objets ou en réponse à la collision de deux objets, elle peut modifier la géométrie d'une forme 3D pour simuler une déformation.

Ces deux méthodes n'étant pas invoquées par Java 3D dans des threads séparés, leur traitement ne doit pas être trop long pour ne pas bloquer Java 3D.

!

Comparativement aux sources lumineuses, les comportements définissent une zone limite d'activation (scheduling bounds), null par défaut. Un comportement n'est actif qu'au moment où sa zone d'activation a une intersection avec celle de l'instance courante de la classe ViewPlatform. Il faut obligatoirement déterminer la zone limite du comportement pour l'activer.

Tous les noeuds dont les propriétés sont modifiées par un comportement doivent avoir les capacités adéquats.

Java 3D fournit les classes de comportement prédéfini suivantes :

Les classes du package com.sun.j3d.utils.behaviors.keyboard gèrent les interactions avec le clavier, et celles du package com.sun.j3d.utils.behaviors.mouse et com.sun.j3d.utils.behaviors.picking les interactions avec la souris. Ces classes sont intéressantes à utiliser non seulement pour simplifier la programmation des interactions mais aussi parce qu'elles établissent des comportements standards pour toutes les applications interactives Java 3D :


Figure 21. Interactions avec la souris


Figure 22. Interactions avec le clavier

Ces figures indiquent sur quel type de transformation (translations dans les 3 directions, rotations autour des axes x et y ou Identité) agissent les déplacements de souris ou les touches du clavier.

Voici l'applet MouseApplet3D dérivant de la classe LitApplet3D. Cette applet permet d'interagir sur toutes les scènes 3D décrites par les classes de ce manuel, en ajoutant à la scène illuminée trois comportements de classe MouseRotate, MouseTranslate et MouseZoom. Ceux-ci modifient la transformation du groupe mouseTransform en fonction des mouvements de la souris (bouton enfoncé) pour obtenir un point de vue différent sur la scène.
La classe de l'applet à manipuler est spécifiée grâce au paramètre Applet3DClass. Pour une utilisation avec la commande java, la valeur du paramètre est passée de la manière suivante :
java MouseApplet3D Applet3DClass=AxisShapeDemo

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.mouse.*;
import com.sun.j3d.utils.applet.MainFrame;
 
public class MouseApplet3D extends LitApplet3D
{
  public BranchGroup createSceneTree ()
  {
    // Racine de l'arbre des objets représentés dans la scène 3D
    BranchGroup root = new BranchGroup ();
 
    // Groupe de transformation sur lequel agisse les comportements
    TransformGroup mouseTransform = new TransformGroup ();
    mouseTransform.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    mouseTransform.setCapability (TransformGroup.ALLOW_TRANSFORM_READ);
    
    BoundingSphere schedulingBounds = new BoundingSphere (new Point3d (), 100.0);
    
    // Création des trois comportements réagissant aux mouvements de la souris
    MouseBehavior rotate = new MouseRotate (mouseTransform);
    rotate.setSchedulingBounds (schedulingBounds);
 
    MouseBehavior translate = new MouseTranslate (mouseTransform);
    translate.setSchedulingBounds (schedulingBounds);
 
    MouseBehavior zoom = new MouseZoom (mouseTransform);
    zoom.setSchedulingBounds (schedulingBounds);
    
    // Création de la scène 3D avec les lumières
    // Rappel : La classe d'applet visualisée est passée par le paramètre Applet3DClass
    BranchGroup subTree = super.createSceneTree ();
 
    // Construction de l'arbre   
    root.addChild (rotate);
    root.addChild (translate);
    root.addChild (zoom);
    root.addChild (mouseTransform);
    mouseTransform.addChild (subTree);
    return root;
  }
  
  // Méthode main () pour permettre d'utiliser cette classe 
  // comme applet ou comme application
  public static void main (String [] args) 
  {
    new MainFrame (new MouseApplet3D (), args, 150, 150);
  }  
}

Arbre MouseApplet3D
Figure 23. Arbre de la scène MouseApplet3D avec la scène de la classe AxisShapeDemo

Le symbole B est utilisé pour les feuilles représentant un comportement dans l'arbre d'une scène 3D. Généralement, un noeud de comportement B est un enfant du groupe qu'il modifie ou du groupe parent le plus proche (ici les noeuds B sont des enfants du groupe BG) et désigne par une flèche le noeud qu'il modifie. Vous noterez qu'ici le groupe de transformation TG sur lequel agissent les comportements est un parent de la forme 3D de classe AxisShape mais aussi des trois sources lumineuses. C'est-à-dire que la transformation TG modifie l'orientation et la position de la forme 3D mais aussi des sources lumineuses.

La classe javax.media.j3d.Behavior

Cette classe abstract dérive des classes SceneGraphObject, Node, Leaf. C'est la super classe de toutes les classes de comportement.

Principales méthodes
public abstract void initialize ()

Cette méthode est invoquée automatiquement une fois que ce noeud est vivant. Son implémentation doit notamment appeler la méthode wakeupOn () pour préciser quels sont les stimuli auxquels cette classe veut réagir.

public abstract void processStimulus (java.util.Enumeration criteria)

Cette méthode est invoquée automatiquement quand survient un stimulus respectant les conditions voulues. criteria est une énumération d'instances de classe WakeupCondition.

protected void wakeupOn (WakeupCondition criteria)

Modifie les stimuli auxquels réagit ce comportement. La méthode processStimulus () sera invoquée la prochaine fois que les stimuli de criteria surviendront.

public Bounds getSchedulingBounds ()
public BoundingLeaf getSchedulingBoundingLeaf ()
public void setSchedulingBounds (Bounds region)
public void setSchedulingBoundingLeaf (BoundingLeaf boundingLeaf)

Ces méthodes permettent d'interroger ou de modifier les limites de la zone limite où ce comportement est actif. Par défaut, cette zone est égale à null. Pour que le comportement soit actif, il faut que le noeud boundingLeaf ait été ajouté à l'arbre de la scène.

public void postId (int postId)

Déclenche un stimulus auquel les autres comportements liés peuvent réagir.

public boolean getEnable ()
public void setEnable (boolean state)

Ces méthodes permettent d'interroger ou de modifier l'état actif ou inactif de ce comportement.

La classe javax.media.j3d.WakeupCondition

Cette classe abstract représente un stimulus ou un ensemble de stimuli.

Méthodes
public java.util.Enumeration allElements ()
public java.util.Enumeration triggeredElements ()

Ces méthodes renvoient une énumération des stimuli de classe WakeupCriterion de cet ensemble. La seconde méthode ne renvoie que la liste des stimuli qui ont provoqué l'appel à la méthode processStimulus () de la classe Behavior.

La classe javax.media.j3d.WakeupCriterion

Cette classe abstract dérive de la classe WakeupCondition. C'est la super classe des classes de stimuli.

Méthode
public boolean hasTriggered ()

Renvoie true si ce stimulus a provoqué l'appel à la méthode processStimulus () de la classe Behavior.

La classe com.sun.j3d.utils.behaviors.mouse.MouseBehavior

Cette classe abstract dérive des classes SceneGraphObject, Node, Leaf, Behavior. C'est la super classe des classes MouseRotate, MouseTranslate et MouseZoom qui définissent les interactions avec les mouvements de la souris. Ces classes permettent de modifier le point de vue sur une scène 3D en appliquant une rotation (avec la classe MouseRotate) ou une translation (en x et y pour la classe MouseTranslate et en z pour la classe MouseZoom) sur un groupe de transformation parent de cette scène. Il est possible de cumuler ces trois comportements sur un même groupe de transformation, comme dans l'applet MouseApplet3D.

Principales méthodes
public TransformGroup getTransformGroup ()
public void setTransformGroup (TransformGroup transformGroup)

Ces méthodes permettent d'interroger ou de modifier le groupe de transformation sur lequel agit ce comportement.

La classe com.sun.j3d.utils.behaviors.mouse.MouseRotate

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, MouseBehavior. Elle permet de créer un comportement de rotation en réponse à un déplacement de la souris, bouton (gauche) enfoncé. La rotation est appliquée au groupe de transformation associé, qui doit avoir les capacités ALLOW_TRANSFORM_READ et ALLOW_TRANSFORM_WRITE. Une rotation autour de l'axe y est appliquée en réponse à un déplacement de la souris vers la gauche ou la droite, et une rotation autour de l'axe x est appliquée en réponse à un déplacement dans l'autre direction.

Principaux constructeurs
public MouseRotate ()
public MouseRotate (TransformGroup transformGroup)

Ces constructeurs permettent de créer un comportement agissant sur le groupe de transformation transformGroup (null par défaut).

Principales méthodes
public double getXFactor ()
public double getYFactor ()
public void setFactor (double factor)
public void setFactor (double xFactor, double yFactor)

Ces méthodes permettent d'interroger ou de modifier les facteurs de multiplication appliqués à chaque déplacement de la souris, pour augmenter ou diminuer le pas de rotation autour des axes x et y. xFactor s'applique à la rotation autour de l'axe y et yFactor à la rotation autour de l'axe x.

public void transformChanged (Transform3D transform)

Cette méthode peut être outrepassée dans une classe dérivée pour réagir aux transformations successives. transform contient la transformation actuellement appliquée.

Exemple

Applet MouseApplet3D.

La classe com.sun.j3d.utils.behaviors.mouse.MouseTranslate

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, MouseBehavior. Elle permet de créer un comportement de translation en x et y en réponse à un déplacement de la souris, bouton droit enfoncé (ou bouton de la souris et touche pomme enfoncés sous Mac OS). La translation est appliquée au groupe de transformation associé, qui doit avoir les capacités ALLOW_TRANSFORM_READ et ALLOW_TRANSFORM_WRITE.

Principaux constructeurs
public MouseTranslate ()
public MouseTranslate (TransformGroup transformGroup)

Ces constructeurs permettent de créer un comportement agissant sur le groupe de transformation transformGroup (null par défaut).

Principales méthodes
public double getXFactor ()
public double getYFactor ()
public void setFactor (double factor)
public void setFactor (double xFactor, double yFactor)

Ces méthodes permettent d'interroger ou de modifier les facteurs de multiplication appliqués à chaque déplacement de la souris, pour augmenter ou diminuer le pas de translation le long des axes x et y.

public void transformChanged (Transform3D transform)

Cette méthode peut être outrepassée dans une classe dérivée pour réagir aux transformations successives. transform contient la transformation actuellement appliquée.

Exemple

Applet MouseApplet3D.

La classe com.sun.j3d.utils.behaviors.mouse.MouseZoom

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, MouseBehavior. Elle permet de créer un comportement de translation en z en réponse à un déplacement de la souris vers le haut ou le bas, bouton (gauche) et touche ALT enfoncés, ce qui rapproche ou éloigne une scène 3D. La translation est appliquée au groupe de transformation associé, qui doit avoir les capacités ALLOW_TRANSFORM_READ et ALLOW_TRANSFORM_WRITE.

Principaux constructeurs
public MouseZoom ()
public MouseZoom (TransformGroup transformGroup)

Ces constructeurs permettent de créer un comportement agissant sur le groupe de transformation transformGroup (null par défaut).

Principales méthodes
public double getFactor ()
public void setFactor (double factor)

Ces méthodes permettent d'interroger ou de modifier le facteur de multiplication appliquée à chaque déplacement de la souris, pour augmenter ou diminuer le pas de translation le long de l'axe z.

public void transformChanged (Transform3D transform)

Cette méthode peut être outrepassée dans une classe dérivée pour réagir aux transformations successives. transform contient la transformation actuellement appliquée.

Exemple

Applet MouseApplet3D.

La classe com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior. Elle permet de créer un comportement qui répond aux touches du clavier en modifiant la transformation du groupe de transformation associé, qui doit avoir les capacités ALLOW_TRANSFORM_READ et ALLOW_TRANSFORM_WRITE.

Constructeur
public KeyNavigatorBehavior (TransformGroup transformGroup)

Crée un comportement agissant sur le groupe de transformation transformGroup.

Animation

Comportement d'animation et opérateur alpha

Une animation est un type de comportement qui modifie une scène 3D de manière prédéterminée en fonction du temps écoulé. Bien que la classe WakeupOnElapsedTime puisse être utilisée comme stimulus pour réaliser une animation, Java 3D fournit un ensemble de classes qui permettent de réaliser la plupart des animations beaucoup plus facilement. Les classes dérivées de la classe d'animation Interpolator permettent d'effectuer des animations qui modifient la couleur d'une forme 3D ou un groupe de transformation pour déplacer ou faire tourner des formes 3D. Un comportement d'animation utilise un opérateur alpha de classe Alpha pour déterminer comment doit évoluer dans le temps l'animation. Un opérateur alpha utilise la courbe suivante alpha = f (t) comme base, modifiée par les paramètres de la classe Alpha :

alpha
Figure 24. Opérateur alpha

La valeur alpha est comprise entre 0 et 1 et respectent les phases suivantes :

Suivant le choix et la valeur des différentes phases, vous pouvez obtenir un grand choix de courbes, comme par exemple :


Figure 25. Exemples d'opérateur alpha

Paramètres utilisés par les 3 courbes (les paramètres non cités sont égaux à 0) :

  • Courbe 1 (obtenue avec le constructeur par défaut, new Alpha ()) :
    • mode=INCREASING_ENABLE
    • increasingAlphaDuration=1000 (1 s)
    • loopCount=-1 (cycles indéterminés)
  • Courbe 2 :
    • mode=DECREASING_ENABLE
    • decreasingAlphaDuration=1000
    • alphaAtZeroDuration=500
    • loopCount=2 (2 cycles)
  • Courbe 3 (mouvement oscillatoire) :
    • mode=INCREASING_ENABLE | DECREASING_ENABLE
    • increasingAlphaDuration=1000
    • increasingAlphaRampDuration=500
    • decreasingAlphaDuration=1000
    • decreasingAlphaRampDuration=500
    • loopCount=-1 (cycles indéterminés)

 

La valeur de l'opérateur alpha est utilisée par les classes d'animation comme facteur d'interpolation entre deux valeurs initiale et finale, 0 correspondant à la valeur initiale et 1 à la valeur finale. Par exemple :

Pour tester l'effet des différentes paramètres utilisés pour construire la courbe d'un opérateur alpha, vous pouvez tester l'applet AlphaTest décrite avec la classe Alpha.

Java 3D fournit un ensemble de classes d'animation appartenant aux packages javax.media.j3d et com.sun.j3d.utils.behaviors.interpolators dont voici la hiérarchie :

Les formes 3D dépendant d'un comportement d'animation sont mises à jour régulièrement par Java 3D pour donner l'effet d'animation. Vous n'avez pas à vous soucier du taux de rafraîchissement des animations : celui-ci peut varier en fonction de la puissance de calcul disponible sur votre machine à un moment donné.

Voici l'applet TextTranslation dérivant de la classe Applet3D : cet exemple utilise un comportement d'animation de classe PositionInterpolator pour faire défiler un texte de plusieurs lignes à l'écran. Une rotation finale autour de l'axe x est ensuite appliquée pour obtenir un effet de perspective. Le texte affiché est un ensemble de formes 3D utilisant une construction géométrique de classe Text3D avec le texte de chaque ligne.

TextTranslation

import java.util.StringTokenizer;
import java.awt.Font;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.applet.MainFrame;
 
public class TextTranslation extends Applet3D
{
  public BranchGroup createSceneTree ()
  {
    Group  textGroup = new Group ();
    Font3D font = new Font3D (new Font ("Helvetica", Font.PLAIN, 2), 
                              new FontExtrusion ());
    Point3f     position = new Point3f ();
    BoundingBox bounds   = new BoundingBox ();
    Point3d     lower    = new Point3d ();
    Point3d     upper    = new Point3d ();
    double      maxWidth = 0;
    // Enumération des lignes du texte
    for (StringTokenizer tokens = new StringTokenizer (getText (), "\n");
         tokens.hasMoreTokens (); 
         position.y -= 3f)
    {  
      String currentText = tokens.nextToken ();
      // Ajout des lignes qui ont autre chose que des blancs
      if (currentText.trim ().length () > 0)
      {
        Text3D textGeometry = new Text3D (font, currentText, position, 
                                          Text3D.ALIGN_CENTER, Text3D.PATH_RIGHT);
        // Calcul du texte le plus large pour l'afficher entièrement à l'écran
        textGeometry.getBoundingBox (bounds);
        bounds.getLower (lower);
        bounds.getUpper (upper);
        if (maxWidth < upper.x - lower.x)
          maxWidth = upper.x - lower.x;
        // Ajout du texte au groupe
        textGroup.addChild (new Shape3D (textGeometry));
      }
    }
 
    // Animation du texte en translation le long de l'axe y
    TransformGroup textAnimationGroup = new TransformGroup ();
    textAnimationGroup.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    // Transformation de l'axe x en l'axe y => rotation autour de z
    Transform3D axisTransformation = new Transform3D ();
    axisTransformation.rotZ (-Math.PI / 2);    
    // alpha de durée variable suivant la longueur du texte
    Alpha alpha = new Alpha (-1, (int)-position.y / 2 * 1000);
    PositionInterpolator animation = new PositionInterpolator (alpha, textAnimationGroup,
                                                 axisTransformation, 3, position.y - 20);
    animation.setSchedulingBounds (new BoundingSphere (new Point3d (), 10000));
   
    // Rotation de -PI / 3 autour de l'axe x pour obtenir un effet de perspective
    Transform3D finalTransformation = new Transform3D ();
    finalTransformation.rotX  (-Math.PI / 3);
    // Mise à l'échelle en fonction du texte le plus large
    finalTransformation.setScale (1.5 / maxWidth);
    TransformGroup finalTransformationGroup = new TransformGroup (finalTransformation);
 
    // Construction de l'animation utilisant le texte
    BranchGroup root = new BranchGroup ();
    root.addChild (finalTransformationGroup);
    finalTransformationGroup.addChild (textAnimationGroup);
    textAnimationGroup.addChild (animation);
    textAnimationGroup.addChild (textGroup);   
    return root;
  }
  
  public String getText ()
  {
    // Construction du texte avec la table des matières du manuel
    // (mettre un blanc dans les lignes vides pour qu'elles soient prises en compte)
    return   "JAVA 3D\n \n"
           + "D\u00e9marrer en Java 3D\n"
           + "Un premier exemple\n"
           + "Principes 3D\n"
           + "Les classes de bases\n__\n \n"
           + "OBJETS 3D\n \n"
           + "Les formes de base\n"
           + "Les constructions g\u00e9om\u00e9triques\n"
           + "Les fonds d'\u00e9cran\n"
           + "L'importation de sc\u00e8nes 3D\n__\n \n"
           + "LES ATTRIBUTS D'APPARENCE\n \n"
           + "Les diff\u00e9rents attributs\n"
           + "Les attributs de couleur\n"
           + "Les attributs d'affichage des facettes\n"
           + "Les attributs de transparence et de rendu\n"
           + "Les attributs de texture\n__\n \n"
           + "ECLAIRAGE 3D\n \n"
           + "Activation\n"
           + "Les diff\u00e9rentes sources lumineuses\n"
           + "Combinaison des sources lumineuses\n"
           + "Les classes d'\u00e9clairage\n__\n \n"
           + "ANIMATION 3D\n \n"
           + "Interaction\n"
           + "Animation\n"
           + "L'importation de sc\u00e8nes 3D\n"
           + "Un exemple complet : Du soleil \u00e0 la lune\n"
           + "Plus loin avec Java 3D...\n__\n";
  }
  
  // Méthode main () pour permettre d'utiliser cette classe 
  // comme applet ou comme application
  public static void main (String [] args) 
  {
    new MainFrame (new TextTranslation (), args, 300, 150);
  }  
}


Figure 26. Arbre de la scène TextTranslation

Le symbole I est utilisé pour les feuilles représentant un comportement d'animation dans l'arbre d'une scène 3D. Comme pour un noeud de comportement , un noeud d'animation I est généralement un enfant du groupe qu'il modifie ou du groupe parent le plus proche (ici le noeud I est un enfant du groupe TG qu'il modifie). A partir de la version 1.2 de Java 3D, il est possible de n'utiliser qu'une seule forme 3D pour tout le texte en utilisant la méthode addGeometry () de la classe Shape3D.

!

Le groupe de transformation modifié par un comportement d'animation doit être indépendant et dédié uniquement à ce comportement. Une nouvelle transformation est calculée à chaque mise à jour de l'animation sans tenir compte de l'ancienne transformation. Dans l'exemple TextTranslation, si vous associez une animation à l'autre groupe de transformation TG enfant du groupe BG (sans créer un second groupe TG dédié au comportement d'animation), sa rotation initiale sera perdue dès la première mise à jour de l'animation pour être remplacée par la translation calculée.

La classe javax.media.j3d.Interpolator

Cette classe abstract dérive des classes SceneGraphObject, Node, Leaf, Behavior. C'est la super classe de toutes les classes d'animation notamment PositionInterpolator, RotationInterpolator, ScaleInterpolator, ColorInterpolator et TransparencyInterpolator et aussi de la classe javax.media.j3d.PathInterpolator et des classes du package com.sun.j3d.utils.behaviors.interpolators qui permettent de créer des comportements d'animation pour parcourir un chemin (path) constitué d'un ensemble de points.
La classe Interpolator mémorise l'opérateur alpha utilisé pour les animations.

!

N'oubliez pas de déterminer la zone limite sur laquelle l'animation est active avec la méthode setSchedulingBounds (), héritée de la classe Behavior.

Principales méthodes
public Alpha getAlpha ()
public void setAlpha (Alpha alpha)

Ces méthodes permettent d'interroger ou de modifier l'opérateur alpha. setAlpha (null) provoque l'arrêt de l'animation.

La classe javax.media.j3d.Alpha

Cette classe dérive des classes SceneGraphObject, NodeComponent et représente un opérateur alpha qui décrit comment évolue dans le temps la valeur renvoyée par la méthode value (). Cette valeur comprise entre 0 et 1 est utilisée pour faire varier les comportements d'animation.
Toutes les méthodes qui permettent de modifier les paramètres d'un opérateur alpha ne sont pas citées, car les différents constructeurs suffisent généralement pour programmer un opérateur.

Champs
public static final int INCREASING_ENABLE
public static final int DECREASING_ENABLE

Ces constantes déterminent quelles phases montante et/ou descendante doit utiliser cet opérateur.

Constructeurs
public Alpha ()
public Alpha (int loopCount, int mode,
              long triggerTime, long phaseDelayDuration,
              long increasingAlphaDuration, long increasingAlphaRampDuration,
              long alphaAtOneDuration,
              long decreasingAlphaDuration, long decreasingAlphaRampDuration,
              long alphaAtZeroDuration)
public Alpha (int loopCount, long triggerTime,
              long phaseDelayDuration,
              long increasingAlphaDuration, long increasingAlphaRampDuration,
              long alphaAtOneDuration)
public Alpha (int loopCount, long increasingAlphaDuration)

Ces constructeurs permettent de créer une instance d'opérateur alpha. mode peut être égal à INCREASING_ENABLE ou DECREASING_ENABLE ou une combinaison de ces deux constantes avec l'opérateur |. loopCount est égal au nombre de cycles à appliquer ou -1 pour une infinité. Les différentes phases ont une durée mesurée en milliseconde et permettent de paramétrer la courbe de l'opérateur alpha.
Par défaut, loopCount est égal à -1, mode à INCREASING_ENABLE, triggerTime à 0, phaseDelayDuration à 0, increasingAlphaDuration à 1000, increasingAlphaRampDuration à 0, alphaAtOneDuration à 0, decreasingAlphaDuration à 0, decreasingAlphaRampDuration à 0 et alphaAtZeroDuration à 0.

Principales méthodes
public float value ()
public float value (long atTime)

Ces méthodes renvoient la valeur comprise entre 0 et 1 de cet opérateur alpha au moment présent ou au moment atTime. Elles sont appelées par les classes d'animation pour obtenir un facteur d'interpolation entre deux valeurs initiale et finale.

public boolean finished ()

Renvoie true si cet opérateur alpha n'est plus actif.

Voici l'applet AlphaTest dérivant de la classe Applet3D : cet exemple permet de tester les combinaisons des paramètres de l'opérateur alpha, appliquées au déplacement en translation d'un cube à l'aide du comportement d'animation PositionInterpolator. Les valeurs des propriétés loopCount, mode, triggerTime, phaseDelayDuration, increasingAlphaDuration, increasingAlphaRampDuration, alphaAtOneDuration, decreasingAlphaDuration, decreasingAlphaRampDuration et alphaAtZeroDuration de l'opérateur alpha sont passées directement par des paramètres de même nom. Pour une utilisation avec la commande java, vous pouvez tester par exemple :

AlphaTest

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
 
public class AlphaTest extends Applet3D
{
  public BranchGroup createSceneTree ()
  {
    // Racine de l'arbre des objets représentés dans la scène 3D
    BranchGroup root = new BranchGroup ();
 
    // Création d'un opérateur en fonction des paramètres    
    Alpha alpha = getAlphaFromParameters ();
    
    // Création de l'animation de translation      
    TransformGroup position = new TransformGroup ();
    position.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    PositionInterpolator animation = new PositionInterpolator (alpha, position);
    animation.setStartPosition (-0.8f);
    animation.setEndPosition (0.8f);
    animation.setSchedulingBounds (new BoundingSphere (new Point3d (), 10.0));
 
    // Construction de l'arbre
    root.addChild (position);
    position.addChild (animation);
    position.addChild (createScene ());
    return root;
  }  
    
  public Alpha getAlphaFromParameters ()
  {
    // Création d'un opérateur alpha par défaut. Toutes les propriétés sont à 0 sauf
    // loopCount = -1, mode = INCREASING_ENABLE, increasingAlphaDuration = 1000
    Alpha  alpha = new Alpha ();
    String parameter;
    // Modification des propriétés de l'opérateur alpha en fonction des paramètres
    if ((parameter = getParameter ("loopCount")) != null)
      alpha.setLoopCount (Integer.parseInt (parameter));
    if ((parameter = getParameter ("mode")) != null)
    {
      // Décodage des constantes INCREASING_ENABLE et DECREASING_ENABLE
      int parameterValue = 0;
      if (parameter.indexOf ("INCREASING_ENABLE") >= 0)
        parameterValue |= Alpha.INCREASING_ENABLE;
      if (parameter.indexOf ("DECREASING_ENABLE") >= 0)
        parameterValue |= Alpha.DECREASING_ENABLE;
      alpha.setMode (parameterValue);
    }
    if ((parameter = getParameter ("triggerTime")) != null)
      alpha.setTriggerTime (Long.parseLong (parameter));
    if ((parameter = getParameter ("phaseDelayDuration")) != null)
      alpha.setPhaseDelayDuration (Long.parseLong (parameter));
    if ((parameter = getParameter ("increasingAlphaDuration")) != null)
      alpha.setIncreasingAlphaDuration (Long.parseLong (parameter));
    if ((parameter = getParameter ("increasingAlphaRampDuration")) != null)
      alpha.setIncreasingAlphaRampDuration (Long.parseLong (parameter));
    if ((parameter = getParameter ("alphaAtOneDuration")) != null)
      alpha.setAlphaAtOneDuration (Long.parseLong (parameter));
    if ((parameter = getParameter ("decreasingAlphaDuration")) != null)
      alpha.setDecreasingAlphaDuration (Long.parseLong (parameter));
    if ((parameter = getParameter ("decreasingAlphaRampDuration")) != null)
      alpha.setDecreasingAlphaRampDuration (Long.parseLong (parameter));
    if ((parameter = getParameter ("alphaAtZeroDuration")) != null)
      alpha.setAlphaAtZeroDuration (Long.parseLong (parameter));
    return alpha;
  }
 
  public Node createScene ()
  {  
    return new ColorCube (0.1);
  }
   
  // Méthode main () pour permettre d'utiliser cette classe 
  // comme applet ou comme application
  public static void main (String [] args) 
  {
    new MainFrame (new AlphaTest (), args, 300, 85);
  }  
}

Arbre AlphaTest
Figure 27. Arbre de la scène AlphaTest

Autres exemples

Applet TextTranslation, Clock3D, SunEarthMoonMotion.

La classe javax.media.j3d.PositionInterpolator

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, Interpolator et représente un comportement d'animation qui applique une translation à un groupe de transformation, pour faire varier la position des formes 3D enfants de ce groupe. La translation le long de l'axe x est calculée à un moment donné en interpolant les positions de départ et de fin en fonction de la valeur de l'opérateur alpha. La direction de la translation peut être modifiée en utilisant la transformation axisOfTranslation qui applique une transformation temporaire au repère courant pour changer la direction de l'axe x.

Constructeurs
public PositionInterpolator (Alpha alpha, TransformGroup target)
public PositionInterpolator (Alpha alpha, TransformGroup target,
                             Transform3D axisOfTranslation,
                             float startPosition, float endPosition)

Ces constructeurs permettent de créer un comportement d'animation affectant la translation du groupe de transformation target. Ce comportement fait varier la position d'une forme 3D entre les points (startPosition,0,0) à (endPosition,0,0) du repère issu de la transformation axisOfTranslation. Par défaut, startPosition est égale à 0, endPosition à 1 et axisOfTranslation à la matrice identité.

Principales méthodes
public TransformGroup getTarget ()
public void setTarget (TransformGroup target)

Ces méthodes permettent d'interroger ou de modifier le groupe de transformation target dont la transformation est affectée par ce comportement d'animation. target doit avoir la capacité ALLOW_TRANSFORM_WRITE.

public Transform3D getAxisOfTranslation ()
public void setAxisOfTranslation (Transform3D axisOfTranslation)

Ces méthodes permettent d'interroger ou de modifier la transformation qui donne la nouvelle direction de l'axe x le long duquel se fait la translation.

public float getStartPosition ()
public float getEndPosition ()
public void setStartPosition (float startPosition) public void setEndPosition (float endPosition)

Ces méthodes permettent d'interroger ou de modifier les positions de départ ou de fin de ce comportement d'animation.

Exemples

Applets TextTranslation, AlphaTest.

La classe javax.media.j3d.RotationInterpolator

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, Interpolator et représente un comportement d'animation qui applique une rotation à un groupe de transformation, pour faire varier la position des formes 3D enfants de ce groupe. La rotation autour de l'axe y est calculée à un moment donné en interpolant les angles de départ et de fin en fonction de la valeur de l'opérateur alpha. La direction de l'axe de rotation peut être modifiée en utilisant la transformation axisOfRotation qui applique une transformation temporaire au repère courant pour changer la direction de l'axe y.

Constructeurs
public RotationInterpolator (Alpha alpha, TransformGroup target)
public RotationInterpolator (Alpha alpha, TransformGroup target,
                             Transform3D axisOfRotation,
                             float minimumAngle, float maximumAngle)

Ces constructeurs permettent de créer un comportement d'animation affectant la rotation du groupe de transformation target. Ce comportement fait varier la rotation entre les angles minimumAngle à maximumAngle radians autour de l'axe y du repère issu de la transformation axisOfRotation. Par défaut, minimumAngle est égale à 0, maximumAngle à 2*PI et axisOfRotation à la matrice identité.

Principales méthodes
public TransformGroup getTarget ()
public void setTarget (TransformGroup target)

Ces méthodes permettent d'interroger ou de modifier le groupe de transformation target dont la transformation est affectée par ce comportement d'animation. target doit avoir la capacité ALLOW_TRANSFORM_WRITE.

public Transform3D getAxisOfRotation ()
public void setAxisOfRotation (Transform3D axisOfRotation)

Ces méthodes permettent d'interroger ou de modifier la transformation qui donne la nouvelle direction de l'axe y autour duquel se fait la rotation.

public float getMinimumAngle ()
public float getMaximumAngle ()
public void setMinimumAngle (float minimumAngle) public void setMaximumAngle (float maximumAngle)

Ces méthodes permettent d'interroger ou de modifier les angles minimum ou maximum de ce comportement d'animation.
 

Voici l'applet Clock3D dérivant de la classe Applet3D et utilisant 3 comportements d'animations de classe RotationInterpolator. Ceux-ci font tourner les aiguilles d'une horloge à trois vitesses différentes, un tour étant effectué en 60*1000 ms pour l'aiguille des secondes, en 3600*1000 ms pour celle des minutes et en 12*3600*1000 ms pour celle des heures. Le mode des opérateurs alpha est égal à DECREASING_ENABLE pour que alpha décroît de 1 à 0 et qu'ainsi les aiguilles tourne en sens inverse du sens direct de l'axe y. Une transformation initiale est appliquée aux aiguilles pour mettre l'horloge à l'heure.

import java.util.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.applet.MainFrame;
 
public class Clock3D extends Applet3D
{
  public BranchGroup createSceneTree ()
  {
    // Création des attributs d'apparence avec des couleurs
    Appearance grayAppearance = new Appearance ();
    grayAppearance.setColoringAttributes (
        new ColoringAttributes (0.7f, 0.7f, 0.7f, ColoringAttributes.SHADE_GOURAUD));
    Appearance blackAppearance = new Appearance ();
    blackAppearance.setColoringAttributes (
        new ColoringAttributes (0, 0, 0, ColoringAttributes.SHADE_GOURAUD));
    Appearance redAppearance = new Appearance ();
    redAppearance.setColoringAttributes (
        new ColoringAttributes (1, 0, 0, ColoringAttributes.SHADE_GOURAUD));
 
    // Création des objets de la scène (cadran + aiguilles)
    Primitive clockFace = new Cylinder (0.7f, 0.01f, grayAppearance);
    Primitive seconds   = new Box (0.01f, 0.01f, 0.75f / 2, redAppearance);
    Primitive minutes   = new Box (0.03f, 0.01f, 0.6f  / 2, blackAppearance);
    Primitive hours     = new Box (0.03f, 0.01f, 0.4f  / 2, blackAppearance);
    
    Calendar date = new GregorianCalendar ();
    int currentSecond = date.get (Calendar.SECOND); 
    int currentMinute = date.get (Calendar.MINUTE);
    int currentHour   = date.get (Calendar.HOUR_OF_DAY) % 12;
    
    BoundingLeaf schedulingBounds = new BoundingLeaf (new BoundingSphere ());
 
    // Transformation secondes
    Transform3D secondsTransformation = new Transform3D ();
    secondsTransformation.rotY (-currentSecond * Math.PI / 30);
    Transform3D secondsTranslation = new Transform3D ();
    secondsTranslation.setTranslation (new Vector3f (0, 0.03f, -(0.75f / 2 - 0.1f)));
    secondsTransformation.mul (secondsTranslation);
    TransformGroup secondsTransformationGroup = 
        new TransformGroup (secondsTransformation);
 
    // Animation des secondes avec un comportement de rotation
    TransformGroup secondsAnimationGroup = new TransformGroup ();
    secondsAnimationGroup.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    Alpha secondsAlpha = new Alpha (-1, Alpha.DECREASING_ENABLE, 0, 0, 0, 0, 0,
                                    60 * 1000, 0, 0); // Un tour en 60 s
    RotationInterpolator secondsRotator = 
        new RotationInterpolator (secondsAlpha, secondsAnimationGroup);
    secondsRotator.setSchedulingBoundingLeaf (schedulingBounds);
    
    // Construction de la branche des secondes
    secondsAnimationGroup.addChild (secondsRotator);
    secondsAnimationGroup.addChild (secondsTransformationGroup);
    secondsTransformationGroup.addChild (seconds);
 
    // Transformation minutes
    Transform3D minutesTransformation = new Transform3D ();
    minutesTransformation.rotY (-currentMinute * Math.PI / 30);
    Transform3D minutesTranslation = new Transform3D ();
    minutesTranslation.setTranslation (new Vector3f (0, 0.02f, -(0.6f / 2 - 0.05f)));
    minutesTransformation.mul (minutesTranslation);
    TransformGroup minutesTransformationGroup = 
        new TransformGroup (minutesTransformation);
 
    // Animation des minutes avec un comportement de rotation
    TransformGroup minutesAnimationGroup = new TransformGroup ();
    minutesAnimationGroup.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    Alpha minutesAlpha = new Alpha (-1, Alpha.DECREASING_ENABLE, 0, 0, 0, 0, 0, 
                                    3600 * 1000, 0, 0); // Un tour en 1 h (3600 s)
    RotationInterpolator minutesRotator = 
        new RotationInterpolator (minutesAlpha, minutesAnimationGroup);
    minutesRotator.setSchedulingBoundingLeaf (schedulingBounds);
    
    // Construction de la branche des minutes
    minutesAnimationGroup.addChild (minutesRotator);
    minutesAnimationGroup.addChild (minutesTransformationGroup);
    minutesTransformationGroup.addChild (minutes);
 
    // Transformation hours
    Transform3D hoursTransformation = new Transform3D ();
    hoursTransformation.rotY ((-currentHour * 60 - currentMinute) * Math.PI / 360);
    Transform3D hoursTranslation = new Transform3D ();
    hoursTranslation.setTranslation (new Vector3f (0, 0.01f, -(0.4f / 2 - 0.05f)));
    hoursTransformation.mul (hoursTranslation);
    TransformGroup hoursTransformationGroup = new TransformGroup (hoursTransformation);
 
    // Animation des heures avec un comportement de rotation
    TransformGroup hoursAnimationGroup = new TransformGroup ();
    hoursAnimationGroup.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    Alpha hoursAlpha = new Alpha (-1, Alpha.DECREASING_ENABLE, 0, 0, 0, 0, 0,  
                                  12 * 3600 * 1000, 0, 0); // Un tour en 12 h
    RotationInterpolator hoursRotator = new RotationInterpolator (hoursAlpha, 
                                                                  hoursAnimationGroup);
    hoursRotator.setSchedulingBoundingLeaf (schedulingBounds);
    
    // Construction de la branche des heures
    hoursAnimationGroup.addChild (hoursRotator);
    hoursAnimationGroup.addChild (hoursTransformationGroup);
    hoursTransformationGroup.addChild (hours);
 
    // Rotation de PI / 2 autour de l'axe x pour avoir l'horloge de face
    Transform3D clockTransformation = new Transform3D ();
    clockTransformation.rotX (Math.PI / 2);
    TransformGroup clockTransformationGroup = new TransformGroup (clockTransformation);
 
    // Construction de l'horloge
    BranchGroup root = new BranchGroup();
    root.addChild (clockTransformationGroup);
    clockTransformationGroup.addChild (schedulingBounds);
    clockTransformationGroup.addChild (clockFace);
    clockTransformationGroup.addChild (secondsAnimationGroup);
    clockTransformationGroup.addChild (minutesAnimationGroup);
    clockTransformationGroup.addChild (hoursAnimationGroup);
    
    return root;
  }
  
  // Méthode main () pour permettre d'utiliser cette classe 
  // comme applet ou comme application
  public static void main (String [] args) 
  {
    new MainFrame (new Clock3D (), args, 150, 150);
  }  
}

Arbre Clock3D
Figure 28. Arbre de la scène Clock3D

Autre exemple

Applet SunEarthMoonMotion.

La classe javax.media.j3d.ScaleInterpolator

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, Interpolator et représente un comportement d'animation qui applique une homothétie à un groupe de transformation, pour faire varier l'échelle des formes 3D enfants de ce groupe. Les homothéties sur les 3 axes sont calculées à un moment donné en interpolant les facteurs minimumScale et maximumScale en fonction de la valeur de l'opérateur alpha. Les axes d'homothétie peuvent être modifiés en utilisant la transformation axisOfScale qui applique une transformation temporaire au repère courant.

Constructeurs
public ScaleInterpolator (Alpha alpha, TransformGroup target)
public ScaleInterpolator (Alpha alpha, TransformGroup target,
                          Transform3D axisOfScale,
                          float minimumScale, float maximumScale)

Ces constructeurs permettent de créer un comportement d'animation affectant les facteurs d'homothétie du groupe de transformation target. Ce comportement fait varier la changement d'échelle entre les facteurs minimumScale et maximumScale sur les 3 axes du repère issu de la transformation axisOfScale. Par défaut, minimumScale est égale à 0.1f, maximumScale à 1 et axisOfScale à la matrice identité.

Principales méthodes
public TransformGroup getTarget ()
public void setTarget (TransformGroup target)

Ces méthodes permettent d'interroger ou de modifier le groupe de transformation target dont la transformation sera affectée par ce comportement d'animation. target doit avoir la capacité ALLOW_TRANSFORM_WRITE.

public Transform3D getAxisOfScale ()
public void setAxisOfScale (Transform3D axisOfScale)

Ces méthodes permettent d'interroger ou de modifier la transformation qui modifie les axes sur lesquels s'applique le facteur d'homothétie.

public float getMinimumScale ()
public float getMaximumScale ()
public void setMinimumScale (float minimumScale) public void setMaximumScale (float maximumScale)

Ces méthodes permettent d'interroger ou de modifier les facteurs d'homothétie minimum ou maximum de ce comportement d'animation.

La classe javax.media.j3d.ColorInterpolator

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, Interpolator et représente un comportement d'animation qui affecte la couleur de diffusion d'un attribut d'apparence de classe Material, pour faire varier la couleur des formes 3D utilisant cet attribut. La couleur est calculée à un moment donné en interpolant les couleurs de début et de fin en fonction de la valeur de l'opérateur alpha.

Constructeurs
public ColorInterpolator (Alpha alpha, Material target)
public ColorInterpolator (Alpha alpha,  Material target,
                          Color3f startColor, Color3f endColor)

Ces constructeurs permettent de créer un comportement d'animation affectant la couleur de diffusion de l'attribut d'apparence target, pour faire varier la couleur de startColor à endColor (égaux par défaut aux couleurs noir et blanc).

Principales méthodes
public Material getTarget ()
public void setTarget (Material target)

Ces méthodes permettent d'interroger ou de modifier l'attribut d'apparence target dont la couleur de diffusion sera affectée par ce comportement d'animation. target doit avoir la capacité ALLOW_COMPONENT_WRITE.

public void getStartColor (Color3f startColor)
public void getEndColor (Color3f endColor)
public void setStartColor (Color3f startColor) public void setEndColor (Color3f endColor)

Ces méthodes permettent d'interroger ou de modifier les couleurs de début ou de fin de ce comportement d'animation.

La classe javax.media.j3d.TransparencyInterpolator

Cette classe dérive des classes SceneGraphObject, Node, Leaf, Behavior, Interpolator et représente un comportement d'animation qui affecte la valeur de transparence d'un attribut d'apparence de classe TransparencyAttributes, pour faire varier la transparence des formes 3D utilisant cet attribut. La transparence est calculée à un moment donné en interpolant les valeurs de transparence minimum et maximum en fonction de la valeur de l'opérateur alpha. Pour rappel, une valeur de transparence est compris entre 0 (totalement opaque) et 1 (totalement transparent).

Constructeurs
public TransparencyInterpolator (Alpha alpha, TransparencyAttributes target)
public TransparencyInterpolator (Alpha alpha, TransparencyAttributes target,
                                 float minimumTransparency, float maximumTransparency)

Ces constructeurs permettent de créer un comportement d'animation affectant la couleur de diffusion de l'attribut d'apparence target, pour faire varier la couleur de startColor à endColor (égales par défaut à 0 et 1).

Principales méthodes
public TransparencyAttributes getTarget ()
public void setTarget (TransparencyAttributes target)

Ces méthodes permettent d'interroger ou de modifier l'attribut d'apparence target dont la valeur de transparence sera affectée par ce comportement d'animation. target doit avoir la capacité ALLOW_VALUE_WRITE.

public float getMinimumTransparency ()
public float getMaximumTransparency () public void setMinimumTransparency (float minimumTransparency)
public void setMaximumTransparency (float maximumTransparency)

Ces méthodes permettent d'interroger ou de modifier les valeurs de transparence minimum ou maximum de ce comportement d'animation.

Un exemple complet : Du soleil à la lune

Voici l'applet SunEarthMoonMotion dérivant de la classe Applet3D : cet exemple utilise 3 comportements d'animations de classe RotationInterpolator, pour simuler la rotation de la terre autour d'elle-même et du soleil et la rotation de la lune autour de la terre, sur un fond étoilé utilisant l'image du fichier stars.gif. La terre effectue ici une révolution en 120 s (au lieu d'un an) et les autres vitesses de rotation sont modifiées proportionnellement. Une source lumineuse confondue avec le soleil éclaire la terre et la lune. La terre a une texture utilisant le fichier demo/java3d/images/earth.jpg fourni avec Java 3D : recopiez-le dans votre répertoire courant.
Comme pour toutes les applets de ce manuel, les tailles et positions du soleil, de la terre et de la lune utilisent une unité qui permet de les afficher ici avec les dimensions par défaut de l'univers 3D fixées par la classe Applet3D. Néanmoins, comme Java 3D permet de manipuler des dimensions qui vont de moins d'un Angström à des millions d'années lumière, il est aussi possible de créer un univers 3D avec une scène utilisant les dimensions réelles.

SunEarthMoonMotion

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.image.TextureLoader; 
 
public class SunEarthMoonMotion extends Applet3D
{  
  public BranchGroup createSceneTree ()
  { 
    // Rapport utilisé pour les durées de rotation (1 an <=> 120 s)
    final long DURATION_RATIO = (365L * 24 * 3600) / 120;
    
    // Création des attributs d'apparence de la lune avec une couleur blanche
    Appearance moonAppearance = new Appearance ();
    moonAppearance.setMaterial (new Material (new Color3f (), 
                                                new Color3f (0.08f, 0.08f, 0.08f), 
                                                new Color3f (1, 1, 1),
                                                new Color3f (), 0));
    // Création des attributs d'apparence de la terre avec une texture
    Appearance earthAppearance = new Appearance ();
    Texture texture = new TextureLoader ("earth.jpg", this).getTexture ();
    earthAppearance.setTexture (texture);
  	TextureAttributes textureAttributes = new TextureAttributes ();
  	textureAttributes.setTextureMode (TextureAttributes.MODULATE);
    earthAppearance.setTextureAttributes (textureAttributes);    
    earthAppearance.setMaterial (new Material (new Color3f (), 
                                                 new Color3f (0.08f, 0.08f, 0.08f), 
                                                 new Color3f (1, 1, 1), 
                                                 new Color3f (), 0));
    // Création des attributs d'apparence du soleil avec une couleur d'émission 
    Appearance sunAppearance = new Appearance ();
    sunAppearance.setMaterial (new Material (new Color3f (),
                                               new Color3f (1, 1, 0.7f), 
                                               new Color3f (), new Color3f (), 0));
 
    // Création des trois sphères représentant le soleil, la terre et la lune
    Primitive sun   = new Sphere (0.1f, sunAppearance);
    Primitive earth = new Sphere (0.07f,   Sphere.GENERATE_NORMALS 
                                         | Sphere.GENERATE_TEXTURE_COORDS, 
                                  earthAppearance);
    Primitive moon  = new Sphere (0.025f, moonAppearance);
    
    BoundingSphere schedulingBounds = new BoundingSphere (new Point3d (), 100.0);
 
    Light sunLight = new PointLight ();
    sunLight.setInfluencingBounds (schedulingBounds);
    
    // Translation de la terre 
    Transform3D earthTranslation = new Transform3D ();
    earthTranslation.setTranslation (new Vector3f (-0.7f, 0, 0));
    TransformGroup earthTranslationGroup = new TransformGroup (earthTranslation);
 
    // Animation de la terre avec un comportement de rotation autour du soleil
    TransformGroup sunEarthAnimationGroup = new TransformGroup ();
    sunEarthAnimationGroup.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    Alpha sunEarthAlpha = 
        new Alpha (-1, 365L * 24 * 3600 * 1000 / DURATION_RATIO); // Un tour en 1 an
    RotationInterpolator sunEarthRotator = 
        new RotationInterpolator (sunEarthAlpha, sunEarthAnimationGroup);
    sunEarthRotator.setSchedulingBounds (schedulingBounds);
 
    // Rotation de l'axe de rotation de la terre de 23 degré
    Transform3D earthAxisRotation = new Transform3D ();
    earthAxisRotation.rotZ (Math.PI * 23 / 180);
    TransformGroup earthAxisRotationGroup = new TransformGroup (earthAxisRotation);
    
    // Animation de la terre avec un comportement de rotation autour d'elle-même
    TransformGroup earthAnimationGroup = new TransformGroup ();
    earthAnimationGroup.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    Alpha earthAlpha = 
        new Alpha (-1, 24L * 3600 * 1000 / DURATION_RATIO); // Un tour en 24 h
    RotationInterpolator earthRotator = 
        new RotationInterpolator (earthAlpha, earthAnimationGroup);
    earthRotator.setSchedulingBounds (schedulingBounds);
 
    // Construction de la branche avec la terre
    sunEarthAnimationGroup.addChild (sunEarthRotator);
    sunEarthAnimationGroup.addChild (earthTranslationGroup);
    earthTranslationGroup.addChild (earthAxisRotationGroup);
    earthAxisRotationGroup.addChild (earthAnimationGroup);
    earthAnimationGroup.addChild (earthRotator);  // La terre autour d'elle-même
    earthAnimationGroup.addChild (earth);
 
    // Translation de la lune
    Transform3D moonTranslation = new Transform3D ();
    moonTranslation.setTranslation (new Vector3f (-0.15f, 0, 0));
    TransformGroup moonTranslationGroup = new TransformGroup (moonTranslation);
 
    // Animation de la lune avec un comportement de rotation 
    TransformGroup moonAnimationGroup = new TransformGroup ();
    moonAnimationGroup.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE);
    Alpha moonAlpha = 
        new Alpha (-1, 27L * 24 * 3600 * 1000 / DURATION_RATIO); // Un tour en 27 j
    RotationInterpolator moonRotator = new RotationInterpolator (moonAlpha, 
                                                                 moonAnimationGroup);
    moonRotator.setSchedulingBounds (schedulingBounds);
    
    // Construction de la branche avec la lune
    moonAnimationGroup.addChild (moonRotator);
    moonAnimationGroup.addChild (moonTranslationGroup);
    moonTranslationGroup.addChild (moon);
 
    // Création d'un fond étoilé avec l'image du fichier stars.gif
    TextureLoader starsTexture = new TextureLoader ("stars.gif", this);
    Background stars = new Background (starsTexture.getScaledImage (getSize ().width, 
                                                                    getSize ().height));
    stars.setApplicationBounds (schedulingBounds);
    
    // Rotation de PI / 4 autour de l'axe x pour changer le point de vue
    Transform3D sceneTransformation = new Transform3D ();
    sceneTransformation.rotX (Math.PI / 4);
    TransformGroup sceneTransformationGroup = new TransformGroup (sceneTransformation);
    
    // Construction de la scène
    BranchGroup root = new BranchGroup();
    root.addChild (stars);
    root.addChild (sceneTransformationGroup);
    // Le soleil et la source lumineuse sont au centre du repère
    sceneTransformationGroup.addChild (sunLight);
    sceneTransformationGroup.addChild (sun);       
    // La terre tourne autour du soleil (centre du repère)
    sceneTransformationGroup.addChild (sunEarthAnimationGroup);
    // La lune tourne autour de la terre
    earthTranslationGroup.addChild (moonAnimationGroup);
        
    return root;
  }
  
  // Méthode main () pour permettre d'utiliser cette classe 
  // comme applet ou comme application
  public static void main (String [] args) 
  {
    new MainFrame (new SunEarthMoonMotion (), args, 500, 300);
  }  
}

Arbre SunEarthMoonMotion
Figure 29. Arbre de la scène SunEarthMoonMotion

Vous noterez dans cet arbre que la position et la rotation de la lune est relative à la terre, qui elle-même tourne autour du soleil.

Plus loin avec Java 3D...

Ce manuel vous a présenté une grande partie des différentes possibilités offertes par Java 3D. Cette bibliothèque a aussi d'autres fonctionnalités qui n'ont pas été développées ici comme :

Cube3D Applet

Java 3D est une bibliothèque très complète pour réaliser des scènes 3D. Mais cette solution peut vous sembler lourde à utiliser dans le cadre de développement d'applets par exemple.
L'applet Cube3D ci-contre et l'applet JeksDisplay développées par eTeks utilise uniquement la bibliothèque Java 1.0 et montre qu'il est possible d'obtenir des effets 3D simples autrement (Cube3D utilise 6 classes pour un total de 12 Ko).
Voici des liens vers d'autres solutions :

  • idx3D (applets 3D avec ses sources)
  • Anfy 3D (applets 3D)
  • GL4Java (impléméntation en Java d'OpenGL)
  • JCosmos (ressources 3D diverses)

Page d'accueilFindIt !ContactEclairage 3DLes notions de baseDébut de la page
© Copyrights 1997-2023 Emmanuel PUYBARET / eTeks
- Tous droits réservés -
Table des matièresHiérarchie des classes