Transformaciones 3D complejas

Flash Player 10 y posterior, Adobe AIR 1.5 y posterior

La clase Matrix3D permite transformar puntos 3D en un espacio de coordenadas o mapear puntos 3D de un espacio de coordenadas a otro.

Para utilizar la clase Matrix3D no es necesario conocer las matemáticas de matrices. La mayoría de las operaciones comunes de transformación se pueden controlar utilizando los métodos de la clase. No tiene que preocuparse por establecer o calcular de forma explícita los valores de todos los elementos de la matriz.

Una vez establecida la propiedad z de un objeto de visualización en un valor numérico, puede recuperar la matriz de transformación del objeto utilizando la propiedad Matrix3D del objeto Transform del objeto de visualización:

var leafMatrix:Matrix3D = this.transform.matrix3D;

Puede utilizar los métodos del objeto Matrix3D para realizar la traslación, rotación, escala y proyección en perspectiva del objeto de visualización.

Utilice la clase Vector3D con sus propiedades x , y , y z para administrar puntos 3D. También puede representar un vector espacial en física, que cuenta con una dirección y una magnitud. Los métodos de la clase Vector3D permiten realizar cálculos comunes con vectores espaciales como, por ejemplo, cálculos de producto escalar, producto cruzado y suma.

Nota: la clase Vector3D no se relaciona con la clase Vector de ActionScript. La clase Vector3D contiene propiedades y métodos para definir y manipular puntos 3D, mientras que la clase Vector admite conjuntos de objetos con tipo.

Creación de objetos Matrix3D

Existen tres formas principales de crear o recuperar objetos Matrix3D :

  • Utilice el método constructor Matrix3D() para crear una instancia de una nueva matriz. El constructor Matrix3D() adopta un objeto Vector que contiene 16 valores numéricos y sitúa cada valor en una celda de la matriz. Por ejemplo:

    var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1);
  • Establezca el valor de la propiedad z de un objeto de visualización. A continuación recupere la matriz de transformación de la propiedad transform.matrix3D de ese objeto.

  • Recupere el objeto Matrix3D que controla la visualización de objetos 3D en el escenario mediante una llamada al método perspectiveProjection.toMatrix3D() en el objeto de visualización raíz.

Aplicación de varias transformaciones 3D

Puede aplicar varias transformaciones 3D a la vez utilizando un objeto Matrix3D. Por ejemplo, si desea girar, escalar y mover un cubo, puede aplicar tres transformaciones independientes a cada punto del cubo. No obstante, resulta mucho más eficaz calcular previamente varias transformaciones en un objeto Matrix3D y posteriormente realizar una transformación de matriz en cada uno de los puntos.

Nota: el orden en que se aplican las transformaciones de matriz es importante. Los cálculos de matriz no son conmutativos. Por ejemplo, con la aplicación de una rotación seguida de una traslación se obtiene un resultado diferente de la aplicación de la misma traslación seguida de la misma rotación.

En el siguiente ejemplo se muestran dos formas de realizar varias transformaciones 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; 
        } 
    } 
}

En el método doTransforms() el primer bloque de código utiliza las propiedades DisplayObject para cambiar la rotación, escala y posición de una forma de rectángulo. El segundo bloque de código utiliza los métodos de la clase Matrix3D para realizar las mismas transformaciones.

La principal ventaja del uso del método Matrix3D es que todos los cálculos se realizan en la matriz en primer lugar. Después se aplican al objeto de visualización solo una vez, cuando se establece su propiedad transform.matrix3D . La definición de las propiedades DisplayObject hace que el código fuente resulte un poco más sencillo de leer. No obstante, cada vez que se establece una propiedad de escala o rotación, esto causa varios cálculos y cambia varias propiedades del objeto de visualización.

Si el código aplica las mismas transformaciones completas a los objetos de visualización varias veces, guarde el objeto Matrix3D como una variable y posteriormente vuelva a aplicarlo una y otra vez.

Uso de objetos Matrix3D para reordenar la visualización

Tal y como se indicó anteriormente, el orden de la disposición en capas de los objetos en la lista de visualización determina el orden de las capas de visualización, independientemente de sus ejes z relativos. Si la animación transforma las propiedades de los objetos de visualización en un orden que difiere del de la lista de visualización, el espectador podría ver una disposición en capas de los objetos que no se corresponde con las capas del eje z. Por lo tanto, un objeto que deba aparecer alejado del espectador puede aparecer frente a un objeto que esté más cerca del espectador.

Para garantizar que la disposición en capas de los objetos de visualización 3D se corresponde con las profundidades relativas de los objetos, utilice un enfoque como el siguiente:

  1. Utilice el método getRelativeMatrix3D() del objeto Transform para obtener los ejes z relativos de los objetos de visualización 3D secundarios.

  2. Use el método removeChild() para eliminar los objetos de la lista de visualización.

  3. Ordene los objetos de visualización en función de sus valores de eje z.

  4. Utilice el método addChild() para volver a añadir los elementos secundarios a la lista de visualización en orden inverso.

Este reordenamiento garantiza que los objetos se muestren conforme a sus ejes z relativos.

El siguiente código muestra la correcta visualización de las seis caras de un cuadro 3D. Reordena las caras del cuadro tras haber aplicado las rotaciones:

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); 
    } 
}

Para obtener los archivos de la aplicación de este ejemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_es . Los archivos de la aplicación se encuentran en la carpeta Samples/ReorderByZ.