Execução de transformações 3D complexas

Flash Player 10 e posterior, Adobe AIR 1.5 e posterior

A classe Matrix3D permite transformar pontos 3D dentro de um espaço de coordenadas ou mapear pontos 3D de um espaço de coordenadas para outro.

Você não precisa conhecer a matemática de matrizes para usar a classe Matrix3D. A maior parte das operações de transformação comuns pode ser feita usando-se os métodos da classe. Você não precisa se preocupar em definir ou calcular explicitamente os valores de cada elemento da matriz.

Depois de definir a propriedade z de um objeto de exibição como um valor numérico, você pode recuperar a matriz de transformação dele usando a propriedade Matrix3D do objeto Transform do objeto de exibição:

var leafMatrix:Matrix3D = this.transform.matrix3D;

Você pode usar os métodos do objeto Matrix3D para executar translação, rotação, dimensionamento e projeção em perspectiva no objeto de exibição.

Use a classe Vector3D com suas propriedades x , y e z para gerenciar pontos 3D. Ela também pode representar um vetor espacial na física, que tem uma direção e uma magnitude. Os métodos da classe Vector3D permitem executar cálculos comuns com vetores espaciais, como cálculos de adição, produto escalar e produto complementar.

Nota: A classe Vector3D não está relacionada à classe Vector do ActionScript. A classe Vector3D contém propriedades e métodos para definir e manipular pontos 3D, enquanto a classe Vector oferece suporte a matrizes de objetos com tipo.

Criação de objetos Matrix3D

Há três maneiras de criar ou recuperar objetos Matrix3D :

  • Use o método do construtor Matrix3D() para instanciar uma nova matriz. O construtor Matrix3D() toma um objeto Vector que contém 16 valores numéricos e coloca cada valor em uma célula da matriz. Por exemplo:

    var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1);
  • Defina o valor da propriedade z de um objeto de exibição. Em seguida, recupere a matriz de transformação da propriedade transform.matrix3D desse objeto.

  • Recupere o objeto Matrix3D que controla a exibição de objetos 3D no palco chamando o método perspectiveProjection.toMatrix3D() no objeto de exibição raiz.

Aplicação de várias transformações 3D

É possível aplicar muitas transformações 3D de uma só vez usando um objeto Matrix3D. Por exemplo, para girar, dimensionar e, depois, movimentar um cubo, você pode aplicar três transformações separadas a cada ponta do cubo. No entanto, é muito mais eficiente pré-calcular várias transformações em um objeto Matrix3D e, em seguida, executar uma transformação de matriz em cada uma das pontas.

Nota: A ordem em que as transformações de matriz são aplicadas é importante. Os cálculos de matriz não são comutativos. Por exemplo, o resultado de aplicar uma rotação seguida de uma translação é diferente do resultado de aplicar a mesma translação seguida da mesma rotação.

O exemplo a seguir mostra duas maneiras de executar várias transformações 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; 
        } 
    } 
}

No método doTransforms() , o primeiro bloco de código usa as propriedades DisplayObject para alterar a rotação, o dimensionamento e a posição de uma forma de retângulo. O segundo bloco de código usa os métodos da classe Matrix3D para fazer as mesmas transformações.

A principal vantagem de usar os métodos Matrix3D é que todos os cálculos são realizados primeiro na matriz. Em seguida, eles são aplicados ao objeto de exibição apenas uma vez, quando sua propriedade transform.matrix3D é definida. Configurar propriedades DisplayObject torna a leitura do código-fonte um pouco mais simples. Todavia, sempre que é definida uma propriedade de rotação ou dimensionamento, ela gera vários cálculos e altera diversas propriedades do objeto de exibição.

Se o seu código aplicará as mesmas transformações complexas a objetos de exibição mais de uma vez, salve o objeto Matrix3D como uma variável e, em seguida, aplique-o de novo repetidas vezes.

Uso de objetos Matrix3D para reordenar a exibição

Conforme mencionado anteriormente, a ordem em camadas dos objetos de exibição na lista de exibição determina a ordem em camadas da exibição, independentemente dos eixos x relacionados. Se a sua animação transforma as propriedades de objetos de exibição em uma ordem diferente da ordem da lista de exibição, o visualizador poderá ver os objetos de exibição em uma disposição em camadas que não corresponde à disposição em camadas no eixo z. Por isso, um objeto que deve parecer mais distante do visualizador pode aparecer na frente de um objeto que está mais perto do visualizador.

Para assegurar que a disposição em camadas dos objetos de exibição 3D corresponda às profundidades relativas dos objetos, use uma abordagem como a seguinte:

  1. Use o método getRelativeMatrix3D() do objeto Transform para obter os eixos z relacionados dos objetos de exibição 3D filho.

  2. Use o método removeChild() para remover os objetos da lista de exibição.

  3. Classifique os objetos de exibição com base nos valores do eixo z relacionado.

  4. Use o método addChild() para adicionar os filhos de volta à lista de exibição na ordem inversa.

Essa reordenação assegura que seus objetos serão exibidos de acordo com os eixos z relacionados.

O código a seguir força a exibição correta das seis faces de uma caixa 3D. Ele reordena as faces da caixa depois que rotações foram aplicadas a ela:

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 obter os arquivos de aplicativo desse exemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_br . Os arquivos do aplicativo estão na pasta Samples/ReorderByZ.