Compteur :
Java 3D - Chapitre 5 : Apparence

Retour table des matières Java 3D

 

Après avoir appris à construire des objets 3D multiples, nous allons voir dans ce chapitre comment leur attribuer une apparence.
L'apparence permet de définir la façon dont un objet 3D va apparaître à l'écran (couleurs, matériaux, transparence, textures ...), nous allons utiliser pour cela la classe Appearance.

 

 

1. Couleurs

 

L'attribution d'une couleur à un objet 3D est assez complexe à traiter et elle dépend de plusieurs paramètres. Nous avons déjà vu dans le chapitre 3 que l'on pouvait donner une couleur à un objet géométrique en utilisant la méthode
setColors() de la classe GeometryArray, l'objet est donc colorisé en fonction des couleurs que l'on a attribuées à chacun de ses sommets.
Cependant, il existe trois autres façons de coloriser un objet :
- en utilisant la méthode setColor() de la classe ColoringAttributes
- en utilisant les couleurs de la classe Material
- en utilisant l'éclairage de la scène 3D.
Enfin, pour compliquer un peu le tout, nous allons voir dans le cas où les couleurs des sommets sont utilisées que la classe ColoringAttributes peut modifier la façon dont ces couleurs seront affichées.

 

Nous allons étudier dans ce paragraphe une façon de coloriser un objet 3D à l'aide de la classe ColoringAttributes :

 

public static final int SHADE_FLAT
La couleur de remplissage d'une facette d'un objet 3D est obtenue sans interpolation par rapport aux couleurs des sommets (couleur unie).

public static final int SHADE_GOURAUD
La couleur de remplissage d'une facette d'un objet 3D est obtenue par interpolation des couleurs des sommets (dégradé de couleurs).

 

public ColoringAttributes(Color3f color, int shadeModel)
Construit un objet de type ColoringAttributes avec une couleur color et dont le type de remplissage des facettes est donnée par la valeur de shadeModel.

 

public void setColor(Color3f color)
Définit la couleur de l'objet de type ColoringAttributes. Cette couleur ne sera pas toujours prise en compte, nous verrons à la fin de ce chapitre les priorités des différents modes de colorisation.

 

Cette classe ColoringAttributes s'utilise en conjonction avec la classe Appearance dont nous faisons une première description ici :

 

public Appearance()
Construit un objet de type Appearance.

 

public void setColoringAttributes(ColoringAttributes coloringAttributes)
Mets à jour l'objet de type ColoringAttributes de l'apparance Appearance.

 

Voici maintenant un premier exemple dans lequel nous allons utiliser la classe ColoringAttributes pour la couleur, sans utiliser les couleurs des sommets. Nous allons construire un objet équivalent à l'objet ColorCube fourni par la bibliothèque Java 3D de Sun en partant d'un simple objet de type Box.

 

  1. Création de l'apparence (et donc de la couleur) de la face avant du cube

Nous utilisons une couleur rouge unie donc le champ SHADE_FLAT

Appearance appearanceFront = new Appearance();
appearanceFront.setColoringAttributes(
    new ColoringAttributes(new Color3f(Color.red), ColoringAttributes.SHADE_FLAT));

Ensuite, il faut faire de même pour la colorisation des cinq autres faces.

 

  1. On crée un objet de type Box

Box colorBox = new Box();

 

  1. Enfin, on récupère la référence de la face avant de notre cube (objet de type Shape3D) à laquelle on applique
    l'apparance appearanceFront (couleur rouge)

colorBox.getShape(Box.FRONT).setAppearance(appearanceFront);

On fait bien sûr de même avec les 5 autres faces du cube avec 5 autres couleurs.

Colorisation d'un cube avec la classe ColoringAttributes

Le fichier ColorAttributesCube.java présente le code source complet de cet exemple.
Exécutez l'applet ColorAttributesCube.html pour voir le résultat.

 

Nous allons étudier un exemple dans lequel nous allons mettre en concurrence deux méthodes de colorisation d'un objet : couleurs des sommets et utilisation de la classe ColoringAttributes. Nous allons étudier les paramètres permettant de définir dans quel cas une de ces deux méthodes a préséance sur l'autre. Nous allons également voir que la classe ColoringAttributes permet également de modifier la colorisation d'un objet même lorsque la couleur des sommets est utilisée.

Nous allons construire un objet géométrique (cône) et nous allons colorer chacune de ses faces par une couleur unie mais en utilisant cette fois ci les couleurs des sommets plutôt que la classe ColoringAttributes. Cependant, c'est la classe ColoringAttributes qui va nous permettre de définir une couleur unie (et non pas un dégradé) pour chaque facette du cône.

 

  1. Création de l'apparence permettant d'attribuer une couleur unie aux facettes du cône

Appearance appearanceCone = new Appearance();

// Couleur et modele de remplissage
ColoringAttributes coloring = new ColoringAttributes();
coloring.setShadeModel(ColoringAttributes.SHADE_FLAT);
appearanceCone.setColoringAttributes(coloring);

 

  1. On associe l'apparence à notre cône

this.setAppearance(appearanceCone);

this représente ici notre objet cône qui dérive de la classe Shape3D dont on utilise la méthode setAppearance()

Dans ce cas précis, c'est donc la couleur des sommets qui sera utilisée mais le remplissage des facettes sera d'une couleur unie et non pas dégradée comme c'est le cas par défaut si on n'utilise pas l'objet coloring de type ColoringAttributes.
Une facette est constituée de 3 sommets (ou vertices) et c'est la couleur du 3ème sommet qui sera prise en compte lorsqu'on utlise un remplissage de couleur unie.
Le fait d'attribuer une couleur grâce à la méthode setColor() de ColoringAttributes ne changera rien car la couleur dominante lorsqu'on colorise un objet est toujours la couleur des sommets.
Nous verrons dans le paragraphe Rendu comment rendre la couleur de la classe ColoringAttributes prépondérante par rapport à la couleur des sommets.

Colorisation unie (pas de dégradé) des facettes d'un cône

Le fichier RemplissageCone.java présente le code source complet de cet exemple.
Exécutez l'applet RemplissageCone.html pour voir le résultat.

 

2. Matériaux

 

Nous allons voir dans l'exemple décrit dans ce paragraphe qu'il existe une troisième façon de donner une couleur à un objet.
Pour cela, nous allons lui associer un materiau auquel nous allons affecter une couleur d'émission. Il n'est pas besoin que la scène soit éclairée pour que la couleur d'émission soit visible mais nous verrons ici dans la partie consacrée à l'éclairage que la lumière est indispensable pour que les couleurs ambiantes, spéculaires et diffuses associées à un matériau apparaîssent.
La couleur d'émission d'un matériau est prioritaire par rapport à la couleur d'un objet de type ColoringAttributes.

 

  1. Construction du matériau et de sa couleur d'émission bleue

Material emissiveColor = new Material();
emissiveColor.setEmissiveColor(new Color3f(Color.blue));

 

  1. Construction d'une apparence associée au matériau précédemment créé

Appearance appearance = new Appearance();
appearance.setMaterial(emissiveColor);

 

  1. Association de l'apparence et de notre objet à coloriser (ici une sphère)

Sphere sphere = new Sphere(0.5f);
sphere.setAppearance(appearance);

Sphère de couleur bleue obtenue grâce à la couleur d'émission du matériau

Bien entendu, nous étudierons en détail la classe Material ici dans la partie consacrée à l'éclairage d'une scène 3D et notamment les autres couleurs qui constituent un matériau et qui ne peuvent apparaître que lorsque la scène 3D est éclairée.

Le fichier MaterialSphere.java présente le code source complet de cet exemple.
Exécutez l'applet MaterialSphere.html pour voir le résultat.

 

3. Rendu

 

Nous allons étudier dans cette section quelques aspects de la classe RenderingAttributes.
Nous allons voir que cette classe permet en autres d'ignorer les couleurs des sommets et de rendre tout ou partie d'un objet invisible.

 

  1. Pour ignorer les couleurs des sommets (vertices), il suffit d'appeler la méthode setIgnoreVertexColors() de la
    classe RenderingAttributes :

RenderingAttributes rendering = new RenderingAttributes();
rendering.setIgnoreVertexColors(true); // couleurs sommets ignorees

 

  1. Ensuite, il faut ajouter ces attributs de rendu à l'apparence que nous allons donner à notre objet :

Appearance appearancePyramide = new Appearance();
appearancePyramide.setRenderingAttributes(rendering);

 

  1. Les attributs de couleurs de la classe ColoringAttributes sont alors pris en compte au détriment des couleurs des
    sommets :

appearancePyramide.setColoringAttributes(
    new ColoringAttributes(new Color3f(Color.orange), ColoringAttributes.SHADE_FLAT));

 

  1. Enfin, attribuons l'apparence à notre objet :

this.setAppearance(appearancePyramide);

Pyramide dont la couleur des sommets est ignorée (c'est la couleur de ColoringAttributes qui est utilisée)

Le fichier RenduPyramide1.java présente le code source complet de cet exemple.
Exécutez l'applet RenduPyramide1.html pour voir le résultat.

 

Dans ce paragraphe, nous allons faire "clignoter" une pyramide en la rendant alternativement visible et invisible grâce à la méthode setVisible() de la classe RenderingAttributes :

public void setVisible(boolean visible)
Lorsque le boolean visible est a true, l'objet est visible, s'il est à false, l'objet sera invisible.

 

  1. Création de notre objet de type RenderingAttributes

Comme la pyramide que nous allons créer va devenir alternativement visible et invisible, il ne faut pas oublier les capabilités adéquates pour l'objet RenderingAttributes :

// Rendu
RenderingAttributes rendering = new RenderingAttributes();

// On n'oublie surtout pas de declarer les capacites pour ce rendu :
// on doit etre capable de lire et de modifier la valeur de l'attribut
// visible.
rendering.setCapability(RenderingAttributes.ALLOW_VISIBLE_READ);
rendering.setCapability(RenderingAttributes.ALLOW_VISIBLE_WRITE);

 

  1. Création de l'apparence associée

/**
* Creation de l'apparence de la pyramide
*/
Appearance appearancePyramide = new Appearance();

// On met a jour l'apparence avec cet attribut de rendu.
// Toute modification ulterieure de l'attribut de rendu modifiera
// de facto l'apparence
appearancePyramide.setRenderingAttributes(rendering);

this.setAppearance(appearancePyramide);

 

  1. Création d'un Timer pour faire clignoter la pyramide

/**
* Creation et lancement d'un objet Timer (thread) qui va
* alternativement changer l'attribut de rendu en visible ou invisible
* tous les 500 ms.
*/
Timer clignotant = new Timer(500, new ActionListener() {
  public void actionPerformed(ActionEvent event) {
    clignoter();
  }
});

clignotant.start();

 

  1. Ecriture du callback appelé par le timer

/**
* Fait clignoter la pyramide en changeant son attribut de rendu en visible
* ou invisible alternativement
*/
private void clignoter() {
  rendering.setVisible(!rendering.getVisible());
}

 

Le fichier RenduPyramide2.java présente le code source complet de cet exemple.
Exécutez l'applet RenduPyramide2.html pour voir le résultat.

 

Nous allons étudier ici un dernier aspect de la classe RenderingAttributes très utile qui permet de rendre certaines facettes d'un objet transparentes alors que d'autres parties du même objet resteront visibles. En particulier nous allons créer un cône en rotation dont une facette sur deux est transparente.

 

  1. Création des couleurs de l'objet en utilisant la classe Color4f et le canal alpha

Jusqu'à présent, nous utilisions toujours la classe Color3f pour créer une couleur. Dans le cas présent, nous allons utiliser la classe Color4f afin d'introduire une donnée supplémentaire appelée canal alpha. C'est cette donnée supplémentaire qui va nous permettre de jouer sur la visibilité de l'objet. Le constructeur de la classe Color4f utilisée est le suivant :

public Color4f(float x, float y, float z, float w)
x, y et z représentent les 3 composantes rouges, vertes et bleues de la couleur (valeurs comprises entre 0 et 1) tandis que w représente la valeur du canal alpha.

 

  1. Création de notre objet (cône) en utilisant TriangleFanArray.COLOR_4 cette fois pour bien signifier que les couleurs
    des sommets sont de type Color4f (si on utilise le champ COLOR_3, il y aura une erreur à l'exécution)

TriangleFanArray triangleFanArray =
  new TriangleFanArray(nbPtsCorps+nbPtsBase,
                                    TriangleFanArray.COORDINATES|TriangleFanArray.COLOR_4,
                                    stripVertexCount);

 

  1. Création des attributs de rendu permettant de définir la visibilité d'un facette en fonction du canal alpha des couleurs de ces sommets

RenderingAttributes rendering = new RenderingAttributes();
rendering.setAlphaTestFunction(RenderingAttributes.EQUAL);
rendering.setAlphaTestValue(1.0f);

Les 3 lignes précédentes signifient que tout vertex (ou sommet) dont la valeur de alpha sera égale à 1 sera affiché, et tous les autres seront invisibles. La classe RenderingAttributes possède bien sûr d'autres champs statiques que EQUAL permettant d'autres façons de sélectionner les sommets visibles.

 

  1. Enfin, il faut inclure les paramètres de rendu dans l'apparence de notre objet :

Appearance appearanceCone = new Appearance();
appearanceCone.setRenderingAttributes(rendering);

Une facette sur deux du cône est transparente

Le fichier RenduFacettesCone.java présente le code source complet de cet exemple.
Exécutez l'applet RenduFacettesCone.html pour voir le résultat.

 

Nous avons vu dans les 3 premiers paragraphes de ce chapitre qu'il y avait plusieurs façons de coloriser un objet. Or la priorité des critères pour l'attribution de la couleur définitive d'un objet est la suivante :

  1. Les couleurs des sommets sont toujours prioritaires (sauf si la méthode setIgnoreVertexColor(true) de la classe
    RenderingAttributes est appelée).
  2. Dans une scène non éclairée, c'est la couleur d'emission des attributs de la classe Material qui sera prépondérante sur
    la couleur des attributs de la classe ColoringAttributes (si bien sûr les couleurs des sommets ne sont pas définies).
  3. Dans une scène éclairée, c'est la combinaison des couleurs des attributs de la classe Material actives sous la lumière (voir ici le chapitre consacré à l'éclairage) qui est prioritaire sur la couleur des attributs de la classe
    ColoringAttributes.

 

4. Affichage

 

Après avoir étudié les attributs de couleur et de rendu, nous allons voir que les attributs d'affichage vont nous permettre d'afficher un objet 3D selon trois formes :
le mode point, le mode lignes (couramment appelé fil de fer ou wireframe en anglais) et enfin le mode polygone (mode par défaut). C'est la classe PolygoneAttributes qui va nous permettre de sélectionner l'un de ces modes pour afficher notre objet 3D :

public PolygonAttributes(int polygoneMode, int cullFace, float polygonOffset)

polygonMode permet de sélectionner le rendu des facettes :
polygonMode = PolygonAttributes.POLYGON_FILL est le comportement par défaut, les facettes sont remplies
polygonMode = PolygonAttributes.POLYGON_LINE : seuls les contours des facettes sont dessinnés (lignes)
polygonMode = PolygonAttributes.POLYGON_POINT : seuls les sommets des facettes sont dessinnés.

cullFace permet de cacher la face avant ou la face arrière d'un polygone, voici deux illustrations explicitant la notion de face avant/arrière :

cullFace = PolygonAttributes.CULL_NONE : faces avant et arrière cachées
cullFace = PolygonAttributes.CULL_BACK : face arrière cachée (par defaut)
cullFace = PolygonAttributes.CULL_FRONT : face avant cachée

polygonOffset permet de décaler (positivement ou négativement) le polygone selon l'axe des Z

Il suffit ensuite d'utiliser la méthode setPolygonAttributes() de la classe Appearance pour prendre en compte le mode d'affichage des facettes.

Lorsqu'on affiche un objet 3D en mode point (sommets uniquement), on peut utiliser la classe PointAttributes pour accéder à encore davantage de paramètres d''affichage :

public PointAttributes(float pointSize, boolean pointAntialiasing)

pointSize représente la taille du point affiché (en pixels)
pointAntialiasing = true permet de lisser les contours du point (si sa taille est supérieure à 1 pixel)

Il suffit ensuite d'utiliser la méthode setPointAttributes() de la classe Appearance pour prendre en compte l'objet de type PointAttributes :

// Affichage en mode points
Appearance appearanceCone = new Appearance();

PolygonAttributes facettes = new PolygonAttributes(PolygonAttributes.POLYGON_POINT,
                                                   PolygonAttributes.CULL_NONE,
                                                   0);
appearanceCone.setPolygonAttributes(facettes);

PointAttributes pointAttributes = new PointAttributes(6f, true);
appearanceCone.setPointAttributes(pointAttributes);

 

Lorsqu'on affiche un objet 3D en mode ligne ou fil de fer (wireframe ou meshes en anglais), on peut utiliser la classe LineAttributes pour accéder à encore davantage de paramètres d''affichage :

public LineAttributes(float lineWidth, int linePattern, boolean lineAntialiasing)

lineWidth représente la largeur de la ligne en pixels
linePattern représente le motif de la ligne dessinée (pointillés, tirets, ...)
lineAntialiasing = true permet de lisser la ligne

Il suffit ensuite d'utiliser la méthode setLineAttributes() de la classe Appearance pour afficher l'objet en mode lignes :

// Affichage en mode ligne
Appearance appearanceCone = new Appearance();

PolygonAttributes facettes = new PolygonAttributes(PolygonAttributes.POLYGON_LINE,
                                                   PolygonAttributes.CULL_NONE,
                                                   0);
appearanceCone.setPolygonAttributes(facettes);

LineAttributes lineAttributes = new LineAttributes(1f,
                                                   LineAttributes.PATTERN_DASH_DOT,
                                                   false);
appearanceCone.setLineAttributes(lineAttributes);

Affichage en mode point, ligne et polygone

Le fichier AffichageCone.java présente le code source complet d'un exemple affichant 3 cônes selon les 3 modes décrits précédemment.
Exécutez l'applet AffichageCone.html pour voir le résultat.

 

5. Transparence

 

Nous allons voir dans ce paragraphe comment jouer avec la transparence d'un objet 3D.
Pour cela, nous allons utiliser la classe TransparencyAttributes dont voici le principal constructeur :

public TransparencyAttributes(int tMode, float tVal)
tMode indique le mode de transparence que l'on veut utiliser. Citons entre autres les 2 valeurs :
- TransparencyAttributes.BLENDED : la couleur de l'objet 3D est mélangée avec la couleur de l'arrière-plan de la scène 3D
- TransparencyAttributes.SCREEN_DOOR : la couleur de l'objet 3D est représentée sous forme de grille dont les trous ont la couleur de l'arrière-plan.
tVal représente représente le taux de transparence (0 correspond a une opacité totale et 1 à une transparence totale).

Attention :

La valeur de la transparence tVal est l'inverse de celle utilisée pour le canal alpha dans les classes de type Color4f où le 0 représente une transparence totale et le 1 une opacité totale.

Ensuite, comme pour les attributs de rendu avec la classe RenderingAttributes, on va enregistrer ces attributs de transparence dans l'apparence de notre objet 3D. On va utiliser cette fois la méthode setTransparencyAttributes() de la classe Appearance :

Appearance appearancePyramide = new Appearance();
appearancePyramide.setTransparencyAttributes(
    new TransparencyAttributes(TransparencyAttributes.BLENDED,
                               0.5f));

Transparence réglable d'une pyramide

Le fichier TransparencePyramide.java présente le code source complet d'un exemple affichant une pyramide dont on peut régler la transparence grâce à un curseur.
Exécutez l'applet TransparencePyramide.html pour voir le résultat.

 

6. Textures

 

Dans ce dernier paragraphe du chapitre consacré à l'apparence, nous allons étudier un aspect très interessant et fondamental de toute programmation en 3D : les textures.
Ce sont en effet les textures qui donnent vie aux objets et à la scène 3D. Nous allons étudier deux exemples d'utilisation des textures : le premier concerne le placage de texture sur un objet simple (une sphère), le second concerne le placage de texture sur un objet à géométrie complexe (la pyramide étudiée dans le paragraphe précédent). De plus, dans ce second exemple, nous utiliserons également la transparence.

 

 

  1. Pour construire une texture, il faut d'abord charger une image

BufferedImage image = ImageIO.read(new File("bois.jpg"));

 

  1. Ensuite, il faut utiliser la classe TextureLoader pour récupérer une instance de la classe Texture. La classe Texture est abstraite, on ne peut donc pas l'instancier directement, d'où l'utilisation de la classe TextureLoader :

Texture texture = new TextureLoader(image).getTexture();

Pour optimiser le traitement des textures, Java 3D impose que la hauteur et la largeur de l'image (en pixels) soient une puissance de 2.

 

  1. Construction de notre objet 3D, ici une sphère. Il ne faut surtout pas oublier d'utiliser le champ Primitive.GENERATE_TEXTURE_COORDINATES pour que l'on puisse plaquer la texture sur la sphère. Il faut en effet générer les coordonnées de texture pour que le plaquage soit valide :

Sphere sphere = new Sphere(0.5f, Primitive.GENERATE_TEXTURE_COORDS, appearance);

 

  1. Enfin, il faut intégrer notre texture à l'apparence de la sphère grâce à la méthode setTexture() de la classe Appearance :

Appearance appearance = new Appearance();
appearance.setTexture(texture);

 

Attention :

Nous avons utilisé en 1 la méthode read() de la classe ImageIO pour charger l'image en mémoire. Or ceci ne marchera que si notre programme Java sera exécuté en tant qu'application, en mode applet l'image ne se chargera pas pour raison de sécurité. Il faut alors recourir à l'algorithme suivant pour que le chargement de l'image se fasse, même en mode applet :

try {
    URL url = this.getCodeBase();
    String path = url.toString() + "bois.jpg";
    URL urlTexture = new URL(path);
    texture = new TextureLoader(urlTexture, this).getTexture();
}
catch (MalformedURLException ex1) {
    System.out.println("Impossible de charger le fichier texture \"bois.jpg\"");
}

 

Remarque :

Le code exposé dans l'encadré Attention marche également lorsqu'on utilise notre programme en mode application mais je préfère plutôt dans ce cas utiliser la méthode read() de la classe ImageIO car si se fichier image bois.jpg est inexistant, la méthode ImageIO.read() renvoie une exception vérifiée de type IOException alors que la classe TextureLoader ne renverra pas d'exception vérifiée. Seule une exception de type javax.imaio.IIOException non vérifiée sera lancée.

Placage de texture sur une sphère

Le fichier TextureSphere.java présente le code source complet de cet exemple.
Exécutez l'applet TextureSphere.html pour voir le résultat.

 

 

Dans cet exemple, nous allons étudier un placage de texture sur un objet à géométrie complexe de type TriangleArray. Avant tout, il faut définir comment la texture va être plaquée sur l'objet géométrique (ce que nous avions fait pour la sphère en utilisant Primitive.GENERATE_TEXTURE_COORDS). Or ici, nous ne sommes plus en présence d'un objet de type Primitive comme la sphère mais d'un objet de type GeometryArray comme TriangleArray. Pour définir la façon dont on va plaquer la texture, il faut établir une correspondance entre l'image constituant la texture et les sommets de l'objet 3D à texturer.
Pour cela, il faut considérer l'image de la texture comme si elle était affichée dans un repère [s,t] avec s et t variant entre 0 et 1. On va alors associer un couple [s,t] de coordonnées de texture correspondant à un point de l'image à chaque sommet de notre objet 3D. On utilise la méthode setTextureCoordinates() de la classe GeometryInfo pour réaliser cette association comme dans notre exemple :

triangleArray.setTextureCoordinates(0,
                                    new TexCoord2f[] {
                                    new TexCoord2f(0.5f, 0.5f),
                                    new TexCoord2f(0, 0),
                                    new TexCoord2f(1, 0),
                                    new TexCoord2f(0.5f, 0.5f),
                                    new TexCoord2f(1, 0),
                                    new TexCoord2f(1, 1),
                                    new TexCoord2f(0.5f, 0.5f),
                                    new TexCoord2f(1, 1),
                                    new TexCoord2f(0, 1),
                                    new TexCoord2f(0.5f, 0.5f),
                                    new TexCoord2f(0, 1),
                                    new TexCoord2f(0, 0),
});

 

Attention :

La librairie Java 3D contient un bug à propos du placage de textures.
En effet, nous utilisons la méthode setTextureCoordinates() de la classe GeometryInfo car la méthode de même nom de la classe GeometryArray est bugguée, le placage étant complètement erratique.
C'est pourquoi, notre objet de type TriangleArray sera construit avec le constructeur de GeometryInfo :

GeometryInfo triangleArray = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);


On notera par contre que la méthode setTextureCoordinates() - avec un s à la fin - de la classe GeometryArray fonctionne parfaitement mais elle est marquée comme dépréciée !!!!
Notre seul et unique replis est donc d'utiliser la classe GeometryInfo pour construire notre objet à géométrie complexe sur lequel on veut plaquer une texture.

Notre objet 3D étant une pyramide constituée de 12 sommets, on associe chacun de ces sommets à un point de l'image constituant la texture et dont les coordonnées [s,t] sont définies par l'objet new TexCoord2f(s, t).
Ensuite pour chaque facette de notre objet, Java 3D utilise ces coordonnées pour extraire la portion d'image correspondante et la plaquer sur la facette. Cette portion d'image est déformée pour s'adapter aux dimensions de la facette.

Plusieurs textures peuvent être appliquées sur un objet 3D, et par conséquent plusieurs groupes de coordonnées de textures [s,t] doivent être utilisés. Dans l'exemple qui nous préoccupe, nous nous limiterons à une seule texture et par conséquent à un seul groupe de coordonnées. Le premier argument de la méthode setTextureCoordinates() correspond à l'indice du groupe des coordonnées de texture, comme nous n'avons qu'un seul groupe, la valeur de l'indice est donc 0.
Avant d'utiliser la méthode setTextureCoordinates(), il est obligatoire de définir le nombre de groupes de coordonnées de texture que nous allons utiliser sur notre objet ainsi que la dimension des coordonnées de texture (2D, 3D ou 4D).
Ici nous nous limiterons donc à un seul groupe de coordonnées de texture et ces coordonnées seront de dimension 2.
Nous utilisons la méthode setTextureCoordinateParams de la classe GeometryInfo pour définir ces 2 valeurs :

public void setTextureCoordinateParams(int numSets, int dim)
numSets représente le nombre de groupes de coordonnées de texture
dim représente la dimension des coordonnées de texture

Dans notre exemple cela donne donc :

triangleArray.setTextureCoordinateParams(1, 2);

Après avoir défini la façon dont notre texture sera appliquée sur notre objet 3D, il faut définir la texture elle même. Pour cela, on il faut construire un objet de type Texture à partir d'un image exactement comme nous l'avons fait pour notre premier exemple à l'aide de la classe TextureLoader.

Enfin, nous allons aller un peu plus loin avec la classe TextureAttributes qui va nous permettre de définir la façon dont les couleurs de la texture seront mélangées avec la couleur propre des facettes de notre objet :

public TextureAttributes(int textureMode,
                         Transform3D transform,
                         Color4f textureBlendColor,
                         int perspCorrectionMode)

textureMode représente le mode d'application de la texture sur les facettes de l'objet 3D
textureMode = TextureAttributes.REPLACE : la couleur de la texture remplace la couleur des facettes
textureMode = TextureAttributes.DECAL : la couleur des facettes apparaît sur les zones transparentes de la texture (ce mode permet en outre de jouer sur la transparence de la couleur de la texture)
textureMode = TextureAttributes.BLEND: mélange la couleur de la texture avec la couleur du paramètre textureBlendColor
textureMode = TextureAtrributes.MODULATE : mélange la couleur de la texture avec la couleur des facettes (utile pour avoir des effets d'éclairage sur l'objet 3D texturé)

On se referera à la documentation de Sun sur le constructeur de la classe TextureAttributes pour une explication encore plus complète sur le paramètre textureMode.
Toutefois, le meilleur moyen de se faire une idée est d'essayer tous les choix possibles pour ce paramètre et de voir le résultat !!

transform est une matrice de transfomation servant à transformer les coordonnées de texture
textureBlendColor est la couleur utilisée lorsqu'on utilise le paramètre textureMode = TextureAttributes.BLEND
perspCorrectionMode est le mode de correction de perspective servant à l'interpolation des coordonnées de texture et/ou de la couleur de la texture. On pourra utiliser soit NICEST (le plus beau) soit FASTEST (le plus rapide).

Pour associer ces attributs de texture à l'apparence, il suffit d'utiliser simplement la méthode setTextureAttributes() de la classe Appearance :

Appearance appearance = new Appearance()
appearance.setTextureAttributes(textureAttributes);

Enfin, comme pour le premier exemple, il faut associer la texture elle même à l'apparence :

appearance.setTexture(texture);

Placage de texture sur une pyramide avec transparence

Le fichier TexturePyramide.java présente le code source complet de cet exemple.
Exécutez l'applet TexturePyramide.html pour voir le résultat.

 

Retour haut de page

Chapitre 04 : Transformations << >> Chapitre 06 : Eclairage