복잡한 3D 변형 수행

Flash Player 10 이상, Adobe AIR 1.5 이상

Matrix3D 클래스를 사용하면 좌표 공간 내의 3D 점을 변경하거나 한 좌표 공간의 3D 점을 다른 좌표 공간에 매핑할 수 있습니다.

행렬 수학을 이해하지 못해도 Matrix3D 클래스를 사용할 수 있습니다. 일반적인 변형 작업은 대부분 이 클래스의 메서드를 사용하여 처리할 수 있습니다. 행렬에 있는 각 요소의 값을 명시적으로 설정하거나 계산하지 않아도 됩니다.

표시 객체의 z 속성을 숫자 값으로 설정한 후에는 표시 객체의 Transform 객체에 대한 Matrix3D 속성을 사용하여 객체의 변형 행렬을 가져올 수 있습니다.

var leafMatrix:Matrix3D = this.transform.matrix3D;

Matrix3D 객체의 메서드를 사용하여 표시 객체에 대한 평행 이동, 회전, 크기 조절 및 원근 투영을 수행할 수 있습니다.

3D 점을 관리하려면 Vector3D 클래스와 이 클래스의 x, yz 속성을 사용합니다. 이 클래스는 방향과 크기가 있는 물리학적 공간 벡터를 나타낼 수도 있습니다. Vector3D 클래스의 메서드를 사용하면 공간 벡터를 통해 더하기, 내적 및 외적 계산과 같은 일반적인 계산을 수행할 수 있습니다.

참고: Vector3D 클래스는 ActionScript Vector 클래스와는 관련이 없습니다. Vector3D 클래스에는 3D 점을 정의하고 조작하기 위한 속성 및 메서드가 포함되어 있는 반면 Vector 클래스는 유형이 있는 객체의 배열을 지원합니다.

Matrix3D 객체 만들기

Matrix3D 객체를 만들거나 가져오는 기본적인 방법으로는 다음 세 가지가 있습니다.

  1. Matrix3D() 생성자 메서드를 사용하여 새 행렬을 인스턴스화합니다. Matrix3D() 생성자는 16개의 숫자 값이 들어 있는 Vector 객체를 인수로 받아 각 값을 행렬의 셀에 배치합니다. 예를 들면 다음과 같습니다.

    var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1);
  2. 표시 객체의 z 속성 값을 설정합니다. 그런 다음 해당 객체의 transform.matrix3D 속성에서 변형 행렬을 가져옵니다.

  3. 루트 표시 객체의 perspectiveProjection.matrix3D 속성 값을 가져와서 스테이지에 3D 객체가 표시되는 방식을 제어하는 Matrix3D 객체를 가져옵니다.

여러 가지 3D 변형 적용

Matrix3D 객체를 사용하여 여러 가지 3D 변형을 한 번에 적용할 수 있습니다. 예를 들어 정육면체의 회전, 크기 조절 및 이동을 수행하려는 경우 정육면체의 각 점에 세 가지 개별 변형을 적용할 수 있습니다. 그러나 하나의 Matrix3D 객체에서 여러 변형을 미리 계산한 다음 각 점에 대해 하나의 행렬 변환을 수행하는 것이 훨씬 더 효율적입니다.

참고: 행렬 변환이 적용되는 순서는 중요합니다. 행렬 계산에서는 교환법칙이 성립되지 않기 때문입니다. 예를 들어 회전을 적용한 다음 평행 이동을 적용할 때와 평행 이동을 적용한 다음 회전을 적용할 때의 결과는 서로 다릅니다.

다음 예제에서는 여러 가지 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; 
        } 
    } 
}

doTransforms() 메서드의 첫 번째 코드 블록에서는 DisplayObject 속성을 사용하여 사각형 모양의 회전, 크기 조절 및 위치를 변경합니다. 두 번째 코드 블록에서는 Matrix3D 클래스의 메서드를 사용하여 동일한 변형을 수행합니다.

Matrix3D 메서드를 사용할 때의 주된 장점은 모든 계산이 행렬에서 먼저 수행된다는 것입니다. 그런 다음 transform.matrix3D 속성이 설정되었을 때 모든 계산이 표시 객체에 한 번만 적용됩니다. DisplayObject 속성을 설정하면 소스 코드가 좀 더 읽기 쉽게 됩니다. 그러나 회전 또는 크기 조절 속성이 설정될 때마다 여러 번 계산이 수행되고 여러 개의 표시 객체 속성이 변경됩니다.

코드에서 표시 객체에 동일한 복잡한 변형을 두 번 이상 적용할 경우에는 Matrix3D 객체를 변수로 저장한 다음 이를 반복해서 다시 적용합니다.

Matrix3D 객체를 사용하여 표시 순서 재지정

앞에서 언급했듯이 표시 목록에 있는 표시 객체의 레이어 순서는 상대적 z축에 관계없이 표시 레이어 순서를 결정합니다. 애니메이션에서 표시 객체의 속성을 표시 목록 순서와는 다른 순서로 변형할 경우 보는 사람에게는 표시 객체 레이어가 z축 레이어와 일치하지 않게 표시됩니다. 따라서 보는 사람에게서 멀리 떨어진 객체가 보는 사람과 가까이 있는 객체의 앞에 나타날 수 있습니다.

3D 표시 객체의 레이어가 객체의 상대적 깊이와 일치하게 하려면 다음과 같은 방법을 사용합니다.

  1. 변형 객체의 getRelativeMatrix3D() 메서드를 사용하여 자식 3D 표시 객체의 상대적 z축을 가져옵니다.

  2. removeChild() 메서드를 사용하여 객체를 표시 목록에서 제거합니다.

  3. 상대적 z축 값에 따라 표시 객체를 정렬합니다.

  4. addChild() 메서드를 사용하여 자식 객체를 표시 목록에 역순으로 다시 추가합니다.

이렇게 순서를 다시 지정하면 객체가 상대적 z축에 따라 표시됩니다.

다음 코드에서는 3D 상자의 여섯 개 면을 올바르게 표시합니다. 상자에 회전을 적용한 후 상자의 면 순서를 다시 지정합니다.

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_kr를 참조하십시오. 응용 프로그램 파일은 Samples/ReorderByZ 폴더에 있습니다.