마침내 주사위

          이제 주사위를 그릴 모든 준비가 끝났다. 정6면체의 8개의 꼭지점을 3각형으로 자른  주사위는  24개의 꼭지점을 가진 볼록 14면체이다.   6개의 8각형 큰 면과 8개의 3각형 작은 면을 가진 14면체다. 따라서 주사위를 그리려면 14개의 면을 그려야 한다.  24개의 꼭지점에 번호를 매기고 그 번호로 면을 정의하는 인덱스를 코딩하여야 한다. 나는 프라톤 입체를 그릴 때와 마찬가지로 모형을 만들어 사용하였다.  찰흙과 이쑤시개로 만든 정6면체 모형의 8 귀퉁이에 생긴 3각형 꼭지점에 번호를 붙였다.


          아래 그림 <그림1>의 왼쪽 것이 바로 그것이다.  이 경우 번호 매김은 어떤 순서로 하거나 상관이 없다.  나중에 면을 정의하는 인덱스 배열을 만들 때 그 순서를 일관성 있게만 해 주면 된다. 

 



그림 1) 주사위를 그리기 위하여 만든 모형과 플래시로 만든 주사위 스크린 셧


           위 그림 <그림1>의 오른 쪽 것이 왼쪽 모형에 따라 만든 주사위 최종 결과물 스크린 셧이다.   이제 이 주사위를 던질 수 있게 만드는 법을 설명한다. 

먼저 이 주사위를 생성하는 CreateDice 클래스의에 대해 설명한다.  그 클래스의  빼대는 <표1>에 올려 놓았다.  20개의 속성과  6개 메쏘드 함수로 구성되었다. 20개의 속성 가운데 2개만 public 으로 밖에서 불러 내어 조종할 수 있고 나머지 18개는 private 속성으로 클래스 내부에서만 사용할 수 있다. 메쏘드 함수도 두개만 public이고 나머지 4개는 private로 클래스 안에서만 사용할 수 있다.  public 함수중에서 하나는 생성자(constructor) 함수로 클래스 인스턴스를 만들 때 한번만 쓰이는 것이므로 아무때나 밖에서 실행시킬 수 있는 public 함수는 하나뿐이다. 


 

1

class CreateDice{

2

        public var mc:MovieClip;

3

        private var sizeCube:Number;

4

        private var cornerSizeRatio:Number;

5

        private var sd :Number ;

6

        private var sizeDot:Number;

7

        private var colA:Array ;

8

        private var colCorner:Array;

9

        private var colDot:Number;

10

        public var rotMat : Rotation3D ;

11

        private var aCube:Array;

12

        private var currentCube:Array ;

13

        private var aCube2D:Array ;

14

        private var corns2D:Array;

15

        private var corns2D3:Array;

16

        private var cornsIndex8:Array ;

17

        private var cornsIndex3:Array ;

18

        private var dotsC:Array ;

19

        private var dotData:Array;

20

        private var distZ:Number;

21

        private var isIsometric:Boolean;

22

 

23

 

public function CreateDice(diceMc:MovieClip , diceSize:Number, cornSize:Number , dotSizeR:Number,  colorArray:Array,          colorCorner:Array,dotCol:Number){//***//}

24

private function init():Void {//***//}

25

private function calDotData(pt3D1:Array):Array {//***//}

26

private function drawFilledPoly(corners,  fillC,  alp):Void {//***//}

27

private function drawDot (oneDot):Void{//***//}

28

public function showDice(dist:Number, isIso:Boolean):Void  {//***//}

29

}//end class def.


표1) class CreateDice 의 코드의 골자



          줄2의 MovieClip 속성 mc 는 주사위가 생성되는 무비클립이다. 따라서 주사위의 병진 운동은 mc._x, mc._y를 변동시켜 스크린 위에서 움직이게 한다.  줄3의 sizeCube는 주사위의 크기로서 초기화할 때 한번 생성자 함수의 인수로 받아 정하면 주사위를 없앨 때까지 바꿀 수 없다. 줄4의 cornerSizeRatio는 주사위의 모서리의 잘린 부분의 크기를 정한다. <그림37>에서 cornerSizeRatio=0.3이다. 줄5의 내부 속성변수 sd=1-cornerSizeRatio 로<그림37>에서 보면 0.7이 된다.  나머지 속성변수를 모두  여기서  설명하지 않겠다.  클래스 안에서 이들 속성이 어떻게 쓰였는가를 보면 그 속성의 의미를 이해할 수 있다.  



그림 2) 무비1에 그린 주사위 설계도



 

           가장 중요한 속성은 aCube 라는 배열로 전에 말했던 24개의 꼭지점을 정의하는 데이터 배열이다.  이 x,y,z 성분으로 표시되는 24개의 3차원 점의 배열임에 주의하기 바란다.  주사위의 중심을 3차원공간 자리표의 원점(0,0,0) 에 놓고  이 원점에서 주사위의 변까지의 거리를 1로 잡았을 때의 꼭지점 자리표를 <그림36>의 모형의 번호순으로 기입한 것이다.  생성자 함수를 실행하면 그 일부에서 아래 <표10>의 코드로 기술 되는 aCube 배열이 생성된다.

 

 aCube = new Array( [sd, 1, -1],  [1, sd, -1], [1, 1, -sd], [sd, -1, -1], [1, -sd, -1], [1, -1, -sd], [-sd, -1, -1], [-1, -sd, -1], [-1, -1, -sd], [-sd, 1, -1], [-1, sd, -1], [-1, 1, -sd], [sd, 1, 1], [1, sd, 1], [1, 1, sd], [sd, -1, 1], [1, -sd, 1], [1, -1, sd], [-sd, -1, 1], [-1, -sd, 1], [-1, -1, sd], [-sd, 1, 1], [-1, sd, 1], [-1, 1, sd] );

표2 주사위의 24개의 꼭지점의 3차원 자리표로 된 배열  (표10)

 


          다음 중요 속성 변수는 주사위의 텍스쳐 데이터인 점들의 위치를 담은 배열 18줄의 dotsC와 그리기 데이터를 담은 19줄의 otData 다.  dotsC 는 주사위의 점들의 중심의 자리표를 모은 배열이다.  주사위에는  점이 1+2+3+4+5+6 = 21 개가 있다. 이들의 위치를 다음과 같이 배열에 담았다.

        <그림2>의 설계도에 점들의 위치를 표시했는데 는 "2" 와 "4" 만 실선으로 표시된 위치에 점을 그리고 나머지 "1", "3", "5", "6" 은 점선으로 그린 원들의 위치에 그렸다. 그리고 21개의 점들은 ·"1", "2", "3", "4", "5", "6" 면의 점들의 순서대로 배열에 담는다. 즉 "1" 면의 점은 dotsC[0] 에, "2" 면의 점은 dotsC[1], dotsC[2] 에, "3" 면의 점은 dotsC[3], dotsC[4], dotsC[5]에 담는다. 나머지도 마찬가지이다.  줄4~6은 점의 크기를 주사위의 크기에 비례하여 키운다. 줄7~11은 이제 이 주사위의 점을 그리기 위한 텍스쳐 데이터를 만드는 코드다.


 

그림 3) 주사위의 한점을 그리는데 필요한 8개의 데이터 점.

 

 

          점(근사원) 하나마다  8개의 3차원점을 사용하기로 한다. <그림3>의 가운데 점이 주사위의 점의 위치를 나타내고 정4각형의 변과 꼭지점에 놓인 8개의 점이 근사원을 그리는데 쓰인다. 원 위의 점을 양끝으로 하고 꼭지점점을 조절점(control point)으로 해서 curveTo를 사용한 곡선 4개로 근사원을 그린다.




1

dotsC =  new Array([0, 0, -1], [1, 0.4, -0.4], [1, -0.4, 0.4], [-0.5, -1, -0.5], [0, -1, 0], [0.5, -1, 0.5], [-0.5, 1, -0.5], [0.5, 1, -0.5], [0.5, 1, 0.5], [-0.5, 1, 0.5], [-1, 0, 0], [-1, 0.5, -0.5], [-1, -0.5, -0.5], [-1, -0.5, 0.5], [-1, 0.5, 0.5], [-0.5, -0.5, 1], [0, -0.5, 1], [0.5, -0.5, 1], [0.5, 0.5, 1], [0, 0.5, 1], [-0.5, 0.5, 1]);

2

for (var i=0; i<21; i++) {

3

 for (var j=0; j<3; j++) {

4

dotsC[i][j] = dotsC[i][j]*sizeCube/2;

5

}

6

}

7

dotData = new Array( 21);     

8

for (var i= 0; i<21; i++)

9

dotData[i] = new Array[[0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0]];

10

for (var i= 0; i<21; i++)

11

dotData[i] = calDotData(dotsC[i]);

표3 주사위의 점들을 그리기 위한 코드



 

          <표3>의 줄9에 정의된  8요소 배열에 이 8개의 3차원 점들을 담는다. 그리고 모두 21개의 점에 대해서 이 데이터점을 생성한다. (<표3> 줄10, 11 참조)  이것을 손으로 일일이 코딩하는 것은 힘들 뿐 아니라 자칫 에러를 유발할 수 있으므로 이것을 피하기 위하여 아래의 코드와 같은 생성함수를 만들어 <표3> 줄11에서 시행한다. 

           아래의 <표4>에 올려 놓은 CalDotData 함수는 인수로 받은 근사원의 중심이 어느 평면에 놓여 있나를 판별한 다음 이 평면에 근사원 중심점 주변에 8개의 점을 생성하여 반환하는 함수다.  

 


1

private function calDotData(pt3D1:Array):Array {

2

var pt3DA = [[0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0]];

3

if (Math.abs (pt3D1[0])==(sizeCube/2))

4

{pt3DA[0] =[pt3D1[0], pt3D1[1] + sizeDot,  pt3D1[2]];

5

pt3DA[1] = [pt3D1[0], pt3D1[1] + sizeDot,  pt3D1[2]+sizeDot];

6

pt3DA[2] = [pt3D1[0], pt3D1[1],  pt3D1[2]+sizeDot];

7

pt3DA[3] = [pt3D1[0], pt3D1[1] -sizeDot,  pt3D1[2]+sizeDot];

8

pt3DA[4] = [pt3D1[0], pt3D1[1] -sizeDot,  pt3D1[2]];

9

pt3DA[5] = [pt3D1[0], pt3D1[1] -sizeDot,  pt3D1[2]-sizeDot];

10

pt3DA[6] = [pt3D1[0], pt3D1[1],  pt3D1[2]-sizeDot];

11

pt3DA[7] = [pt3D1[0], pt3D1[1] +sizeDot,  pt3D1[2]-sizeDot];

12

        }

13

else

14

{if( Math.abs (pt3D1[1])==(sizeCube/2))

15

{pt3DA[0] = [pt3D1[0] + sizeDot,  pt3D1[1],  pt3D1[2]];

16

pt3DA[1] = [pt3D1[0] + sizeDot,  pt3D1[1],  pt3D1[2]+ sizeDot];

17

pt3DA[2] = [pt3D1[0],  pt3D1[1], pt3D1[2]+sizeDot];

18

pt3DA[3] = [pt3D1[0] -sizeDot,  pt3D1[1], pt3D1[2]+sizeDot];

19

pt3DA[4] = [pt3D1[0] -sizeDot,  pt3D1[1], pt3D1[2]];

20

pt3DA[5] = [pt3D1[0] -sizeDot,  pt3D1[1], pt3D1[2]-sizeDot];

21

pt3DA[6] = [pt3D1[0],  pt3D1[1], pt3D1[2]-sizeDot];

22

pt3DA[7] = [pt3D1[0] +sizeDot,  pt3D1[1], pt3D1[2]-sizeDot];

23

        }

24

          else

25

{pt3DA[0] =[pt3D1[0],  pt3D1[1] + sizeDot,  pt3D1[2]];

26

pt3DA[1] = [pt3D1[0]+sizeDot , pt3D1[1] + sizeDot,  pt3D1[2]];

27

pt3DA[2] = [pt3D1[0]+sizeDot , pt3D1[1],  pt3D1[2]];

28

pt3DA[3] = [pt3D1[0]+sizeDot , pt3D1[1] - sizeDot,  pt3D1[2]];

29

pt3DA[4] = [pt3D1[0],  pt3D1[1] - sizeDot,  pt3D1[2]];

30

pt3DA[5] = [pt3D1[0]-sizeDot , pt3D1[1] - sizeDot,  pt3D1[2]];

31

pt3DA[6] = [pt3D1[0]-sizeDot , pt3D1[1],  pt3D1[2]];

32

pt3DA[7] = [pt3D1[0]-sizeDot , pt3D1[1] + sizeDot,  pt3D1[2]];

33

         }

34

        }

35

        return pt3DA;

36

}

표4 calDotData 함수의 코드.  점의 위치를 인수로 받아서 그 주변의 8개의
점을 생성하여 반환한다.(12)

 

 

          이 마디는 너무 길어지므로 다음 강좌에서 이어서 설명한다. 

Posted by 샛솔 :