Namide

Modélisation 3D et Flash

Visage 3D en Flash

Cette semaine, je me suis fixé un défi : modéliser un visage en 3D, le texturer et l'afficher dans Flash. Tout cela en partant de zéro en modélisation 3D, et d'encore plus loin en création de texture (de - 1 alors…). Nous allons tenter de faire cela sur Away 3D lite, une bibliothèque de rendu 3D légère et dont les performances sont optimisées pour FlashPlayer 10 (donc plutôt rapide ;).
La bonne nouvelle : c'est beaucoup plus facile que ce que l'on pense !

Pour visionner le rendu final vous devez posseder la versions 10.0 de FlashPlayer.
Télécharger la dernière version de Flashplayer
Rendu 3D final

Cet article s'attardera sur la partie ActionScript 3 sans décrire le processus de modélisation et texturing (aussi appelé UV mapping). Néanmoins, les tutoriels qui ont étés lus pour modéliser et texturer notre objet 3D seront cités (pas de panique, il n'y en a que deux).

Pour faire cela, il nous faut donc un logiciel de modélisation 3D (ici Blender), un logiciel de retouche d'image (Gimp ou Photoshop par exemple) et Flash 10 (ou Flash Developp, Flash Builder…).

Première étape : la modélisation avec Blender

esquisses
Esquisse qui a servi pour le visage

Voici le tutoriel qui a servi pour modéliser le personnage de cet exemple : modélisation d'un visage "low poly", survol des techniques. Pour gagner du temps, il a été choisi de se fonder sur un personnage existant, mais libre à vous de vous diriger vers de la création pure. Le personnage de cet exemple est inspiré de Noa, héroïne de la série de bande dessinée Sky-doll, d'Alessandro Barbucci et Barbara Canepa (© Soleil Productions). Il vaut mieux commencer par dessiner notre modèle de face puis de profil, avant d'ouvrir le logiciel 3D.

Attention, Flash n'a pas de z-buffer intégré. Pour superposer les facettes, Away 3D lite calcule approximativement la profondeur de chaque facette (probablement en prenant une moyenne des sommets). Cela peut provoquer du clipping. Pour pallier cela, je conseille d’utiliser des facettes de tailles semblables quand elles sont proches et d’éviter de les superposer. Par exemple, si vous souhaitez habiller un personnage, désactivez le corps qui se trouve dessous. Pour notre exemple, je n'ai pas modélisé le crâne sous les cheveux.

Deuxième étape : le texturing ou UV mapping

esquisses
Dessin ayant servi pour l'inspiration du personnage et de ses couleurs, par Matteo de Longis, en hommage à Sky-doll

Voici le tutoriel ayant servi pour cet exemple : UV mapping avec Blender. Une fois la texture "dépliée" il a été simple de dessiner les points principaux avec l'outil "texture paint" directement sur le modèle 3D dans Blender avant de retravailler la texture sur Photoshop. Pour ne pas passer trop de temps sur ces étapes, dans notre exemple, les teintes ont étés prélevées à la pipette sur les zones de visage d'une illustration du visage de Noa. Ainsi, on assure une cohérence graphique entre les couleurs.

Troisième étape : le rendu dans Flash !

Away 3D lite peut importer plusieurs types de fichier. Pour notre exemple nous allons utiliser le format 3DS pour le modèle et une image au format JPG pour la texture. Dans Blender nous pouvons faire :

Pour la partie Away 3D, voici les bases de la bibliothèque. Si vous n'avez jamais utilisé de bibliothèque 3D cela peut vous être utile pour comprendre la suite.

En premier, téléchargeons le fichier 3DS dans le SWF. Comme nous sommes dans Flash, nous allons utiliser la classe URLLoader et importer dynamiquement notre modèle en tant que fichier binaire. Si nous avions utilisé le SDK de Flex, nous aurions directement encapsulé le fichier dans le SWF à l'aide d'un "embed". La bibliothèque Away 3D lite prend la suite : elle nous permet (entre autres) d'interpréter le fichier pour en faire un objet 3D. Avant de l'afficher il faudra retrouver le maillage de notre élément en parcourant les enfants de l'objet 3D pour lui appliquer la texture. Dans notre exemple, l'objet 3D obtenu par le fichier 3DS ne contient qu'un enfant, mais quand il y en a plusieurs il faut les essayer pour trouver à qui appartient la bonne texture (je ne suis pas encore arrivé à récupérer les noms des différents maillages). Nous pouvons ensuite, à chaque image, faire tourner progressivement notre objet 3D avant de rafraîchir son rendu.


import away3dlite.containers.Scene3D;
import away3dlite.containers.View3D;
import away3dlite.cameras.Camera3D;
import away3dlite.loaders.Max3DS;
import away3dlite.materials.BitmapFileMaterial;
import away3dlite.containers.ObjectContainer3D;
import away3dlite.core.base.Mesh;

    /////////////////////////////////////////////
   //			
  //    OBJETS 3D PERMETTANT LE RENDU	
 //	      			
/////////////////////////////////////////////

var _scene:Scene3D;
var _view:View3D;
var _camera:Camera3D;
var _model3D:ObjectContainer3D;

    /////////////////////////////////////////////////////////
   //					 
  //    OBJETS PERMETTANT LE CHARGEMENT DU MODELE 3D
 //					
/////////////////////////////////////////////////////////

// Permet d'interpreter notre fichier au format 3ds
var _objLoader:Max3DS;

// permet de télécharger notre fichier 3ds en tant qu'objet binaire
// indiquer l'emplacement du fichier avec la classe URLRequest pour lancer le chargement
var _model3DLoader:URLLoader = new URLLoader(new URLRequest("face.3ds"));
// lancer la fonction init() une fois que le téléchargement est finis
_model3DLoader.addEventListener(Event.COMPLETE, init);
// préciser à Flash que le fichier est un fichier binaire
_model3DLoader.dataFormat = URLLoaderDataFormat.BINARY;

    /////////////////////////
   //
  //    INITALISATION
 //
/////////////////////////

function init(e:Event):void
{
        initScene3D();
        loadModel3D();
}

// utilisation élémentaire de Away3D
function initScene3D():void
{
        // Scene3D est l'élément principal qui contiendra nos objets 3D
        _scene = new Scene3D();

        // La caméra est facultative mais elle permet une meilleur gestion des positionnements et de la focale
        _camera = new Camera3D();
        _camera.z = 0;

        // View3D permet l'affichage de nos éléments 3D
        _view = new View3D();
        _view.scene = _scene;
        _view.camera = _camera;
        // positionner View3D au centre de la scène
        _view.x = stage.stageWidth/2;
        _view.y = stage.stageHeight/2;

        addChild( _view );
}

    /////////////////////////////////////
   //                   
  //    CHARGEMENT DU MODELE 3D	    
 //				
/////////////////////////////////////

function loadModel3D():void
{
        _objLoader = new Max3DS();

        // redimentionner le modèle 3D, multiplie par 8 sa taille
        _objLoader.scaling = 8;
        // analyse le fichier 3DS pour en faire un ObjectContainer3D
        _model3D = _objLoader.parseGeometry(_model3DLoader.data) as ObjectContainer3D;

        // récupère le premier enfant de _model3D pour lui appliquer la texture
        (_model3D.children[0] as Mesh).material =  new BitmapFileMaterial("face_texture.jpg");

        // lisse la texture
        ((_model3D.children[0] as Mesh).material as BitmapFileMaterial).smooth = true;

        // ajoute _model3D sur Scene3D puis on le place bien
        _scene.addChild(_model3D);
        _model3D.rotationX = -90;
        _model3D.y = 10;

        addEventListener(Event.ENTER_FRAME, refresh);
}

    /////////////////////////
   //		
  //    RENDU FINAL	 
 //		
/////////////////////////

function refresh(p_e:Event = null):void
{
        // fait correspondre la rotation au temps passé
        // cela produit un mouvement uniforme et indépendant des FPS
        _model3D.rotationY = (getTimer()) / 20;

        // lance un rendu
        _view.render();
}
pack-3d.zip (28.4ko)

Pack contenant les fichiers utilisés dans notre exemple :

  • face.3ds
  • face.fla
  • face_texture.jpg