Выполнение сложных трехмерных преобразований

Flash Player 10 и более поздних версий, Adobe AIR 1.5 и более поздних версий

Класс Matrix3D позволяет преобразовывать трехмерные точки в рамках координатной плоскости или переносить трехмерные точки из одной плоскости координат в другую.

Для использования класса Matrix3D не требуется знание матричной математики. С помощью методов этого класса можно обрабатывать большую часть общих операций преобразования. Нет необходимости явно устанавливать или вычислять значения для каждого элемента в матрице.

После установки свойства z объекта отображения на числовое значение можно получить матрицу преобразования этого объекта с помощью свойства Matrix3D его объекта Transform.

var leafMatrix:Matrix3D = this.transform.matrix3D;

С помощью методов объекта Matrix3D можно выполнять перемещение, поворот, масштабирование и перспективную проекцию объекта отображения.

Для управления трехмерными точками можно использовать класс Vector3D и его свойства x , y и z . Этот класс также может представлять пространственный вектор в физике, имеющий направление и величину. Методы класса Vector3D позволяют выполнять общие вычисления с пространственными векторами, например, сложение, скалярное произведение и векторное произведение.

Примечание. Класс Vector3D не связан с классом Vector в ActionScript. Класс Vector3D содержит свойства и методы для определения трехмерных точек и управления ими, а класс Vector поддерживает массивы объектов со строгим контролем типов.

Создание объектов Matrix3D

Существует три основных способа создания или получения объектов Matrix3D :

  • Использование конструктора Matrix3D() для создания новой матрицы. Конструктор Matrix3D() принимает объект Vector , содержащий 16 числовых значений, и помещает каждое из них в ячейку матрицы. Например:

    var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1);
  • Указание числового значения для свойства z любого объекта отображения. Матрицу преобразования после этого можно получить, запросив свойство transform.matrix3D этого объекта.

  • Получение объекта Matrix3D, управляющего отображением трехмерных объектов в рабочей области, происходит путем вызова метода perspectiveProjection.toMatrix3D() корневого объекта отображения.

Применение нескольких трехмерных преобразований

С помощью одного объекта Matrix3D можно одновременно применить несколько трехмерных преобразований. Например, если требуется повернуть, масштабировать, а затем переместить куб, можно применить три отдельных преобразования для каждой точки куба. Однако более эффективным является выполнение предварительного расчета нескольких преобразований в одном объекте Matrix3D, а затем выполнение одного преобразования матрицы для каждой из этих точек.

Примечание. Важную роль играет порядок, в котором применяются преобразования матрицы. Вычисления матрицы на являются коммутативными. Например, применение поворота с последующим перемещением дает не тот же результат, что применение такого же перемещения с последующим поворотом.

Пример демонстрирует два способа выполнения нескольких трехмерных преобразований.

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

В методе doTransforms() первый блок кода использует свойства DisplayObject для изменения поворота, масштабирования и позиции прямоугольной фигуры. Второй блок кода использует методы класса Matrix3D для выполнения тех же преобразований.

Главное преимущество использования методов Matrix3D заключается в том, что все вычисления выполняются сначала в матрице. Затем выполняется их применение к объекту отображения только один раз при указании его свойства transform.matrix3D . Установка свойств DisplayObject немного облегчает чтение исходного кода. Однако каждый раз при установке свойства поворота или масштабирования выполняются многочисленные расчеты и изменение многих свойств объекта отображения.

При применении одних и тех же сложных преобразований к объектам отображения с помощью кода более одного раза требуется сохранить объект Matrix3D как переменную для повторного его использования.

Использование объектов Matrix3D для изменения порядка отображения

Как было указано ранее, порядок слоев объектов отображения в списке отображения определяет порядок слоев отображения независимо от положения объектов по соответствующим осям z. При преобразовании с помощью анимации свойства объектов отображения в порядке, отличном от порядка в списке отображения, пользователь может увидеть неправильное последовательное расположение объектов отображения, не соответствующее расположению слоев по оси z. Таким образом, объект, который должен находиться дальше от пользователя, может быть отображен перед объектом, находящимся ближе к пользователю.

Для соответствия расположения слоев трехмерных объектов отображения соответствующей глубине объектов требуется использовать, например, следующий подход:

  1. Используйте метод getRelativeMatrix3D() объекта Transform для получения относительных значений z-axes нижестоящих трехмерных объектов отображения.

  2. Используйте метод removeChild() для удаления объектов из списка отображения.

  3. Отсортируйте объекты отображения на основе их относительных значений по оси z.

  4. Используйте метод addChild() для повторного добавления нижестоящих объектов в список отображения в обратном порядке.

Такая перестановка позволяет выстроить объекты отображения в соответствии с их относительными значениями по оси z.

Следующий код обеспечивает правильное отображение шести граней параллелепипеда. Он изменяет порядок граней параллелепипеда после применения поворотов:

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

Получить файлы приложения для этого примера можно на странице www.adobe.com/go/learn_programmingAS3samples_flash_ru . Файлы приложения находятся в папке Samples/ReorderByZ.