Transformations 3D complexes

Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures

La classe Matrix3D vous permet de transformer des points 3D dans un espace de coordonnées ou de mapper des points 3D d’un espace de coordonnées sur un autre.

Il n’est pas nécessaire de comprendre les mathématiques matricielles pour pouvoir utiliser la classe Matrix3D. Ses méthodes permettent de gérer la plupart des opérations de transformation courantes. Il est inutile de vous soucier de la définition explicite ou du calcul de la valeur de chaque élément de la matrice.

Une fois la propriété z d’un objet d’affichage définie sur une valeur numérique, vous pouvez récupérer la matrice de transformation de l’objet par le biais de la propriété Matrix3D de l’objet Transform de l’objet d’affichage :

var leafMatrix:Matrix3D = this.transform.matrix3D;

Les méthodes de l’objet Matrix3D vous permettent d’opérer une translation sur un objet d’affichage, de le faire pivoter et de le mettre à l’échelle, ainsi que de lui appliquer une projection de perspective.

Utilisez la classe Vector3D et ses propriétés x, y et z pour gérer les points 3D. Elle peut également représenter en physique un vecteur spatial, doté d’une direction et d’une magnitude. Les méthodes de la classe Vector3D vous permettent d’effectuer des calculs courants portant sur des vecteurs spatiaux : somme, produit scalaire et produit vectoriel, par exemple.

Remarque : la classe Vector3D n’a aucun rapport avec la classe Vector d’ActionScript. La classe Vector3D contient des propriétés et des méthodes permettant de définir et de manipuler les points 3D, alors que la classe Vector prend en charge les tableaux d’objets typés.

Création d’objets Matrix3D

Vous pouvez créer ou récupérer des objets Matrix3D de trois façons principales :

  • Utilisez la méthode constructeur Matrix3D() pour instancier une nouvelle matrice. Le constructeur Matrix3D() gère un objet Vector contenant 16 valeurs numériques et place chacune d’elles dans une cellule de la matrice. Exemple :

    var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1);
  • Définissez la valeur de la propriété z d’un objet d’affichage. Récupérez ensuite la matrice de transformation de la propriété transform.matrix3D de cet objet.

  • Récupérez l’objet Matrix3D qui régit l’affichage des objets 3D sur la scène en appelant la méthode perspectiveProjection.toMatrix3D() sur l’objet d’affichage racine.

Application de plusieurs transformations 3D

Vous pouvez appliquer simultanément de nombreuses transformations 3D à l’aide d’un objet Matrix3D. Ainsi, pour faire pivoter, mettre à l’échelle, puis déplacer un cube, vous pourriez appliquer trois transformations distinctes à chacun de ses points. Il est cependant beaucoup plus efficace de précalculer plusieurs transformations dans un même objet Matrix3D et d’appliquer une transformation matricielle unique à chacun des points.

Remarque : l’ordre d’application des transformations matricielles est important. Les calculs matriciels ne sont pas réversibles. Ainsi, l’application d’une rotation puis d’une translation ne donne pas le même résultat que l’opération inverse.

L’exemple suivant illustre deux façons d’appliquer plusieurs transformations 3D.

package { 
    import flash.display.Sprite;     
    import flash.display.Shape; 
    import flash.display.Graphics; 
    import flash.geom.*; 
 
public class Matrix3DTransformsExample extends Sprite 
    { 
        private var rect1:Shape; 
        private var rect2:Shape; 
         
public function Matrix3DTransformsExample():void 
        { 
            var pp:PerspectiveProjection = this.transform.perspectiveProjection; 
            pp.projectionCenter = new Point(275,200); 
            this.transform.perspectiveProjection = pp; 
             
            rect1 = new Shape(); 
            rect1.x = -70; 
            rect1.y = -40; 
            rect1.z = 0; 
            rect1.graphics.beginFill(0xFF8800); 
            rect1.graphics.drawRect(0,0,50,80); 
            rect1.graphics.endFill(); 
            addChild(rect1); 
 
            rect2 = new Shape(); 
            rect2.x = 20; 
            rect2.y = -40; 
            rect2.z = 0; 
            rect2.graphics.beginFill(0xFF0088); 
            rect2.graphics.drawRect(0,0,50,80); 
            rect2.graphics.endFill(); 
            addChild(rect2); 
             
            doTransforms(); 
        } 
 
        private function doTransforms():void 
        { 
            rect1.rotationX = 15; 
            rect1.scaleX = 1.2; 
            rect1.x += 100; 
            rect1.y += 50; 
            rect1.rotationZ = 10; 
 
            var matrix:Matrix3D = rect2.transform.matrix3D; 
            matrix.appendRotation(15, Vector3D.X_AXIS); 
            matrix.appendScale(1.2, 1, 1); 
            matrix.appendTranslation(100, 50, 0); 
            matrix.appendRotation(10, Vector3D.Z_AXIS); 
            rect2.transform.matrix3D = matrix; 
        } 
    } 
}

Dans la méthode doTransforms(), le premier bloc de code utilise les propriétés DisplayObject pour modifier la rotation, la mise à l’échelle et la position d’un rectangle. Le second bloc utilise les méthodes de la classe Matrix3D pour effectuer des transformations identiques.

L’utilisation des méthodes Matrix3D présente un avantage principal : tous les calculs sont déjà effectués dans la matrice. Ils sont ensuite appliqués une seule fois à l’objet d’affichage, lors de la définition de sa propriété transform.matrix3D. La définition des propriétés DisplayObject améliore quelque peu la lisibilité du code source. Cependant, chaque définition d’une propriété de rotation ou de mise à l’échelle donne lieu à plusieurs calculs et entraîne la modification de plusieurs propriétés de l’objet d’affichage.

Si votre code applique plusieurs fois des transformations complexes identiques à des objets d’affichage, enregistrez l’objet Matrix3D en tant que variable, puis réappliquez-le autant de fois que nécessaire.

Réorganisation de l’affichage à l’aide d’objets Matrix3D

Comme indiqué plus haut, l’ordre d’apparition des objets d’affichage dans la liste d’affichage détermine l’ordre d’apparition à l’affichage, quels que soient leurs axes z relatifs. Si votre animation transforme les propriétés d’objets d’affichage dans un ordre différent de celui de la liste d’affichage, l’ordre d’apparition des objets d’affichage ne correspondra peut-être pas à celui des axes z. Un objet qui devrait sembler plus éloigné de l’observateur risque donc d’apparaître devant un objet plus proche.

Pour avoir la certitude que l’ordre d’apparition des objets d’affichage 3D correspond à leur profondeur relative, procédez comme suit :

  1. A l’aide de la méthode getRelativeMatrix3D() de l’objet Transform, extrayez la profondeur relative (z-axes) des objets d’affichage 3D enfant.

  2. Supprimez les objets de la liste d’affichage à l’aide de la méthode removeChild().

  3. Triez les objets d’affichage en fonction de leurs valeurs d’axe z relatives.

  4. Ajoutez à nouveau les enfants à la liste d’affichage en ordre inverse, par le biais de la méthode addChild().

Cette réorganisation garantit que vos objets s’affichent conformément à leurs axes z relatifs.

Le code suivant garantit l’affichage correct d’une boîte 3D à six faces. Il réorganise les faces de la boîte une fois que des rotations lui ont été appliquées.

public var faces:Array; . . . 
 
public function ReorderChildren() 
{     
    for(var ind:uint = 0; ind < 6; ind++) 
    { 
        faces[ind].z = faces[ind].child.transform.getRelativeMatrix3D(root).position.z; 
        this.removeChild(faces[ind].child); 
    } 
    faces.sortOn("z", Array.NUMERIC | Array.DESCENDING); 
    for (ind = 0; ind < 6; ind++) 
    { 
        this.addChild(faces[ind].child); 
    } 
}

Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application résident dans le dossier Samples/ReorderByZ.