Créer et personnaliser son 1er objet 3D avec le framework Sandy

Thomas Pfeiffer

Dans ce tutoriel, vous allez apprendre à créer puis à habiller votre premier objet en 3D grâce au framework Actionscript Sandy. ♪

- Titre : Créer et personnaliser son 1er objet 3D avec le framework Sandy

- Auteur : Thomas Pfeiffer

- Parution : 10 mars 2007

- Licence : Copyright ® 2006-2007 Thomas Pfeiffer. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Comment créer son premier cube

- I-A. Introduction

- I-B. Exemple

- I-B-1. Le code

- I-B-2. Aperçu

- I-B-3. La source

- II. Comment personnaliser notre cube 3D

- II-A. Introduction

- II-B. Liste des skins

- II-C. Exemple

- II-C-1. Le code

- II-C-2. Le rendu

- II-C-3. La source

I - Comment créer son premier cube

I-A - Introduction

Dans cette première partie de tutoriel, je vous présente la méthode pour créer votre premier Cube avec Sandy. En une cinquantaine de lignes de code, vous vous familiariserez avec l'API de Sandy, et vous obtiendrez un premier résultat (certes très modeste, mais je vous expliquerai dans les prochains tutoriels comment améliorer tout ça ;) ).

Ici, nous allons donc simplement mettre en place la création d'un écran sur lequel seront dessinés les objets, une caméra pour visualiser le monde et permettre la projection sur l'écran, les groupes (chainons les plus importants) et enfin la primitive Box qui permet de créer pour vous un objet 3D de type boite.

I-B - Exemple

I-B-1 - Le code

import sandy.core.data.*;
import sandy.core.group.*;
import sandy.primitive.*;
import sandy.view.*;
import sandy.core.*;
import sandy.skin.*;
import sandy.util.*;
import sandy.core.transform.*;
import sandy.events.*;

function init( Void ):Void
{
// nous créons notre écran. Élément primordial puisque c'est celui dans lequel les données seront affichées.
var ecran:ClipScreen = new ClipScreen( this.createEmptyMovieClip('écran', 1), 600, 600 );
// nous créons notre camera. Le second paramètre est la distance nodale, qui donne donc l'effet
// de perspective aux objets affichés
var cam:Camera3D = new Camera3D( 700, écran);
// on recule la camera afin de pouvoir rendre visible l'objet situé en 0,0,0
cam.translate(0,0,-500);
// nous ajoutons notre camera au monde 3D
World3D.getInstance().addCamera( cam );
// nous créons notre Group qui servira de racine
var bg:Group = new Group();
// et l'ajoutons au monde 3D. Par défaut le dernier branchGroup ajouté est celui qui est actif
// lors de la demande de rendu
World3D.getInstance().setRootGroup( bg );
// nous lançons la création de la scène
createScene( bg );
// maintenant que tout est créé nous pouvons lancer le rendu du monde
World3D.getInstance().render();
}

function createScene( bg:Group ):Void
{
// nous créons notre objet. Pour cela nous utilisons ici la primitive box.
// cela créé une boite qui, dans le cas où les dimensions de hauteur, profondeur, largeur, sont les mêmes
// génère un cube. Ici nous créons donc un cube de 50 pixels.
var o:Object3D = new Box( 50, 50, 50 );
// nous ajoutons l'objet comme fils du Group afin de créer l'arborescence
//et rendre l'objet affichable.
bg.addChild( o );
}
// Nous lançons la création du monde 3D
init();

Et voilà. Pas si compliqué, n'est-ce pas ?

I-B-2 - Aperçu

Animation en format "flash" non supportée.
Contenu uniquement consultable en ligne à cette adresse :
images/create_a_first_box.swf

I-B-3 - La source

Télécharger la source (Miroir)

II - Comment personnaliser notre cube 3D

II-A - Introduction

Après avoir créé notre premier cube, voilà comment l'habiller un peu plus joliment.

Pour cela, il existe les classes Skins. Les skins peuvent être appliqués sur des objets pour changer et personnaliser son apparence. Sandy possède un certain nombre de skins qui permettent une grande personnalisation des objets. Cependant il se peut que vous ayez besoin d'une fonctionnalité non existante, et pour cela il est très facile de créer votre propre skin, mais cette partie sera abordée plus tard.

On crée un skin qui va permettre d'habiller un peu mieux notre objet 3D. Ici, nous utilisons le skin SimpleColor qui demande une couleur de remplissage, la valeur de l'alpha et l'épaisseur du trait.

var skin:Skin = new SimpleColorSkin( 0xFF0000, 80, 2 );

Maintenant que nous avons notre skin créé, il faut l'appliquer à l'objet. Chaque objet possède une méthode setSkin qui reçoit en paramètre un Skin (attention avec Sprite et Clip3D pour qui cela est un petit peu différent) !

monObjet.setSkin( mon_skin );

II-B - Liste des skins

Voici la liste des skins disponibles dans Sandy, et leur signature (celle du constructeur) :

SimpleLineSkin( t:Number, c:Number, a:Number )

Skin par défaut des objets (et donc des faces). Il affiche seulement les arêtes des faces. Vous pouvez personnaliser la taille de la ligne, sa couleur, et son alpha.

SimpleColorSkin( c:Number, a:Number )

Permet de remplir les faces d'une certaine couleur (premier paramètre) avec un alpha spécifique.

MixedSkin(cb:Number,ab:Number,cl:Number, al:Number,tl:Number )

Mélange de SimpleLineSkin et SimpleColorSkin puisqu'avec ce skin vous pouvez remplir les faces d'une couleur, mais aussi dessiner les arêtes des faces.

ZLightenSkin( col:Number )

Superbe skin qui permet de donner à votre objet un effet de style éclairage de Gouraud obtenu grâce à des gradients de couleur. Le paramètre est la couleur que vous voulez donner aux objets. Attention cependant, ce skin possède des comportements encore étranges avec certaines couleurs et certains alignements avec la camera.

TextureSkin( t:BitmapData )

Permet de texturer les objets avec Bitmap, donc en flash avec un objet BitmapData. Attention on ne peut texturer un objet 3D avec un bitmap seulement si on connait les coordonnées UV pour chacune de ses faces.

Les coordonnées UV sont les coordonnées des vertex 3D dans le bitmap2D. C'est la solution utilisée pour permettre de texturer des formes 3D avec des images 2D.

Les primitives de Sandy génèrent automatiquement ces coordonnées pour vous faciliter au maximum la tâche. Si vous voulez implémenter votre propre primitive et être en mesure de la texturer, alors il vous faudra générer ces coordonnées UV vous-même. Un bon lien pour comprendre comment cela fonctionne : http://dalboris.free.fr/didacticiels/autres/uvs.htm

VideoSkin( video:Video )

Permet de texturer des objets avec un objet Vidéo. Le flux d'une webcam par exemple peut être utilisé ici.

MovieSkin( mc:MovieClip, b:Boolean )

Permet de texturer les objets avec un MovieClip! Très sympathique donc pour afficher des animations sur les faces de vos objets.

Si vous faites attention à la documentation, vous pouvez voir que la méthode setSkin de la classe Object3D possède un second argument qui est un booléen. Même si vous n'aurez certainement pas besoin de l'utiliser tout de suite, je vais en expliquer la raison.

Un objet est composé de faces, et chacune des faces de l'objet possède un skin (car en fait ce n'est pas l'objet qui possède un skin, mais bel et bien ses faces!). Pour certains besoins, il est envisageable que vous vouliez appliquer un skin en particulier à certaines faces et un autre à d'autres.

Par exemple une grande majorité auront le même skin que l'objet, et une minorité un skin spécifique. Lorsque vous modifiez le skin de l'objet, vous pouvez alors écraser le skin existant sur toutes les faces par un nouveau, ou bien ne changer que les skins des faces qui possèdent le même skin que l'objet.

Pour réaliser la première solution il suffit de passer true en second argument de la méthode Object3D::setSKin, ou pour le second comportement il faut passer false (qui est la valeur par défaut!).

II-C - Exemple

II-C-1 - Le code

import sandy.core.data.*;
import sandy.core.group.*;
import sandy.primitive.*;
import sandy.view.*;
import sandy.core.*;
import sandy.skin.*;
import sandy.util.*;
import sandy.core.transform.*;
import sandy.events.*;

function init( Void ):Void
{
// nous créons notre écran. Élément primordial puisque c'est celui dans lequel les données seront affichées.
var ecran:ClipScreen = new ClipScreen( this.createEmptyMovieClip('écran', 1), 600, 600 );
// nous créons notre camera. Le second paramètre est la distance nodale, qui donne donc l'effet
// de perspective aux objets affichés
var cam:Camera3D = new Camera3D( 700, écran);
// nous ajoutons notre camera au monde 3D
World3D.getInstance().addCamera( cam );
// nous créons notre Group qui servira de racine
var bg:Group = new Group();
// et l'ajoutons au monde 3D. Par défaut le dernier branchGroup ajouté est celui qui est actif
// lors de la demande de rendu
World3D.getInstance().setRootGroup( bg );
// nous lançons la création de la scène
createScene( bg );
// maintenant que tout est créé nous pouvons lancer le rendu du monde
World3D.getInstance().render();
}

function createScene( bg:Group ):Void
{
// nous créons notre objet. Pour cela nous utilisons ici la primitive box.
// cela créé une boite qui, dans le cas où les dimensions de hauteur, profondeur, largeur, sont les mêmes
// génère un cube. Ici nous créons donc un cube de 50 pixels.
var o:Object3D = new Box( 50, 50, 50 );
// on créé un skin qui va permettre d'habiller un peu mieux notre objet 3D.
// ici le skin SimpleColor qui demande une couleur de replissage, la valeur de l'alpha et l'épaisseur du trait.
var skin:Skin = new SimpleColorSkin( 0xFF0000, 80, 2 );
// on applique le skin sur l'objet.
o.setSkin( skin );
// Nous créons un noeud de type TransformGroup. Ce nœud pourra avoir comme fils un objet3D, et il peut contenir
// une transformation
var tg:TransformGroup = new TransformGroup();
// d'ailleurs nous créons un objet transformation
var t:Transform3D = new Transform3D();
// et disons que cela est une translation de 500 pixels dans l'axe des Z.
t.translate( 0, 0, 500 );
// Nous appliquons cette transformation au noeud, et ainsi la transformation sera appliquée
// sur tous les objets fils de ce noeud !
tg.setTransform( t );
// nous ajoutons notre objet comme enfant du noeud, et la translation lui sera donc appliquée.
tg.addChild( o );
// nous ajoutons le transformGroup comme fils du BranchGroup afin de créer l'arborescence
//et rendre l'objet affichable.
bg.addChild( tg );
}
// Nous lançons la création du monde 3D
init();

II-C-2 - Le rendu

Animation en format "flash" non supportée.
Contenu uniquement consultable en ligne à cette adresse :
images/skin_a_first_box.swf

II-C-3 - La source

Télécharger la source (Miroir)