Złożone transformacje trójwymiarowe

Flash Player 10 i nowsze wersje, Adobe AIR 1.5 i nowsze wersje

Klasa Matrix3D umożliwia transformowanie punktów 3D w przestrzeni współrzędnych lub odwzorowanie punktów 3D z jednej przestrzeni współrzędnych na inną.

Do korzystania z klasy Matrix3D nie jest niezbędna znajomość zasad wykonywania operacji matematycznych na macierzach. Większość typowych transformacji można zrealizować za pomocą metod klasy. Nie jest konieczne jawne przypisywanie lub obliczenie wartości poszczególnych elementów macierzy.

Po przypisaniu właściwości z obiektu wyświetlanego wartości liczbowej można pobrać macierz transformacji obiektu, odczytując właściwość Matrix3D obiektu Transform obiektu wyświetlanego:

var leafMatrix:Matrix3D = this.transform.matrix3D;

Metody obiektu Matrix3D umożliwiają translację, obracanie, skalowanie i rzutowanie perspektywiczne obiektu wyświetlanego.

Klasa Vector3D zawierająca właściwości x , y i z służy do zarządzania punktami 3D. Może również reprezentować wektor przestrzenny o określonym kierunku i długości. Metody klasy Vector3D umożliwiają wykonywanie typowych obliczeń na wektorach przestrzennych, takich jak dodawanie, obliczanie iloczynu skalarnego i wyznaczanie iloczynu wektorowego.

Uwaga: Klasa Vector3D nie jest powiązana z klasą Vector w języku ActionScript. Klasa Vector3D zawiera właściwości i metody służące do definiowania punktów 3D i manipulowania nimi, natomiast klasa Vector służy do pracy z tablicami obiektów określonego typu.

Tworzenie obiektów Matrix3D

Istnieją trzy główne sposoby tworzenia i odczytywania obiektów Matrix3D :

  • Utworzenie instancji nowej macierzy za pomocą konstruktora Matrix3D() . Konstruktor Matrix3D() jako parametr akceptuje obiekt Vector zawierający 16 wartości liczbowych i umieszcza te wartości w komórkach macierzy. Na przykład:

    var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1);
  • Przypisanie wartości właściwości z obiektu wyświetlanego. Następnie odczytanie macierzy transformacji z właściwości transform.matrix3D obiektu.

  • Odczytanie obiektu Matrix3D sterującego wyświetlaniem obiektów 3D na stole montażowym przez wywołanie metody perspectiveProjection.toMatrix3D() obiektu ekranowego najwyższego poziomu.

Stosowanie więcej niż jednej transformacji 3D

Korzystając z obiektu Matrix3D można zastosować wiele transformacji 3D naraz. Na przykład, chcąc obrócić, przeskalować, a następnie przemieścić sześcian, moglibyśmy zastosować trzy odrębne transformacje do każdego punktu sześcianu. Jednak znacznie bardziej efektywne będzie wstępne obliczenie wielu transformacji w jednym obiekcie Matrix3D i wykonanie po jednej transformacji macierzowej na każdym z punktów.

Uwaga: Ważna jest kolejność wykonywania transformacji macierzowych. Operacje na macierzach nie są przemienne. Na przykład obrót, po którym następuje translacja, prowadzi do innego rezultatu niż ta sama translacja, po której następuje ten sam obrót.

Poniższy przykład ilustruje dwa sposoby wykonywania więcej niż jednej transformacji 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; 
        } 
    } 
}

W metodzie doTransforms() pierwszy blok kodu powoduje zmodyfikowanie właściwości DisplayObject w celu zmiany obrotu, skali i położenia prostokąta. W drugim bloku kodu zastosowano metody klasy Matrix3D w celu wykonania tych samych transformacji.

Zasadnicza przewaga zastosowania metod klasy Matrix3D polega na tym, że wszystkie obliczenia są wykonywane najpierw na macierzy. Następnie są stosowane do obiektu wyświetlanego tylko raz, w momencie przypisania macierzy do właściwości transform.matrix3D . Kod, w którym stosowane są właściwości obiektu DisplayObject, jest nieco bardziej czytelny. Jednak każde przypisanie wartości właściwości obrotu lub skalowania powoduje wykonanie wielu obliczeń i zmianę wielu właściwości obiektu wyświetlanego.

Jeśli kod ma wielokrotnie wykonywać te same złożone transformacje na obiektach wyświetlanych, należy zapisać obiekt Matrix3D jako zmienną i wielokrotnie przypisywać go do odpowiednich właściwości obiektów.

Wykorzystanie obiektów Matrix3D do zmiany kolejności wyświetlania

Jak już wcześniej wspomniano, kolejność obiektów wyświetlanych na liście wyświetlania decyduje o tym, na jakich warstwach będą wyświetlane, niezależnie od ich współrzędnych z. Jeśli animacja transformuje właściwości obiektów wyświetlanych tak, że ich wzajemne rozmieszczenie różni się od kolejności na liście wyświetlania, mogą nakładać się wzajemnie na siebie w sposób inny niż wynikający ze współrzędnych z. A zatem obiekt, który powinien znajdować się dalej od obserwatora, może przesłaniać obiekt, który powinien znajdować się bliżej.

Aby wzajemne nakładanie się obiektów wyświetlanych 3D odpowiadało ich położeniom na osi z, należy zastosować strategię zbliżoną do następującej:

  1. Za pomocą metody getRelativeMatrix3D() obiektu Transform pobierz względne wartości z-axes podrzędnych obiektów wyświetlanych 3D.

  2. Za pomocą metody removeChild() usuń obiekty z listy wyświetlania.

  3. Posortuj obiekty wyświetlane na podstawie wartości współrzędnych z.

  4. Za pomocą metody addChild() dodaj elementy podrzędne do listy wyświetlania, w kolejności odwrotnej do wyniku sortowania.

Taka zmiana kolejności zagwarantuje, że obiekty wyświetlane będą zgodnie z ich współrzędnymi z.

Poniższy kod wymusza prawidłowe wyświetlanie ścian sześcianu. Kolejność ścian jest zmieniana po obróceniu sześcianu:

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

Aby pobrać pliki tej przykładowej aplikacji, należy przejść na stronę www.adobe.com/go/learn_programmingAS3samples_flash_pl . Pliki aplikacji znajdują się w folderze Samples/ReorderByZ.