티스토리 툴바


달력

05

« 2012/05 »

  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  

07 최적화 과정(1. BackfaceCulling )

3D 같이 성능이 중요한 어플리케이션 의 경우 조금이라도 계산량을 줄여야 합니다.
이같은 노력은 예전부터 각종 3D 프로그램들에 쓰여왔으며 지금은 정말 다양한 방법들의
알고리즘을 통하여 최적화 하는 방법들이 여럿 공개되어 있습니다.

이중 가장 기본적이면서도 꼭 해야만 하는 최적화 방법을 먼저 설명드리려 합니다.
BackfaceCulling 말 그대로 뒷면 제거 입니다. ㅎㅎ

화면에 안보이는 반대편의 면을 확인하여 애초에 그려주지 않는 방법 입니다.
몇몇 일부러 보여주어야만 하는 경우(Alpha 를 적용해 유리같은 효과를 주기위함) 를 제외하면
꼭 적용하여 속도 향상을 노려야 합니다... 
또한 다른 culling 방법들에 비해 정말 단순합니다.


  • culling 할 면인지 확인하기 위해 면의 방향Vector 를 구합니다. (normal Vector)
  • 시선Vectot ( 사용자가 바라보는 눈의 방향 ) 과 Dot 곱을 합니다.
  • 위의 결과로 나온 값이 음수이면 뒷면 양수이면 앞면 입니다.

위의 과정을 토대로 AS 소스로 만들어 보겠습니다.

1. 면의 방향Vector를 구하기 위해 면위의 정점3개를 입력 받습니다.

   구하려는 면의 stage 상의 위치를 받아오기 위해 getRelativeMatrix3D 를 사용합니다.
   var transform:Matrix3D = doc.transform.getRelativeMatrix3D( doc.stage );

   위에서 받아온 Matrix3D 값을 기준으로 면위의 3개의 정점을 생성 합니다.
   var vector0:Vector3D = transform.transformVector( new Vector3D( 0, 0, 0 ) );
   var vector1:Vector3D = transform.transformVector( new Vector3D( 1, 0, 0 ) );
   var vector2:Vector3D = transform.transformVector( new Vector3D( 1, 1, 0 ) );

2. Cross Product 를 사용하여 면의 방향(normal Vector)를 구합니다.
   var normalVector:Vector3D = vector1.subtract( vector0 ).crossProduct( vector2.subtract( vector0 ) );

3. 사용자가 물체를 바라보는 시선Vector 를 구합니다.
    var viewVector3D:Vector3D = new Vector3D();
    viewVector3D.x = -(doc.root.transform.perspectiveProjection.projectionCenter.x / 5 -   
                               transform.position.x);
    viewVector3D.y = -(doc.root.transform.perspectiveProjection.projectionCenter.y / 5 -
                               transform.position.y);
    viewVector3D.z = doc.root.transform.perspectiveProjection.focalLength;
  
4. 마지막으로 시선Vectot 와 normal Vector를 Dot Product 합니다.
   var num:Number = viewVector3D.dotProduct( normalVector );


이렇게 하여 구해진 마지막 num 값이 0보다 크면 면이 화면을 바라보고 있는것이고
0보다 작다면 화면 반대방향을 향하고 있는 것 입니다.


한가지 확인하고 넘어가야 할 부분이 있습니다.
위의 방법에서 시선벡터를 구하는 부분에 perspectiveProjection.projectionCenter.x / 5
라는 부분 입니다.
doc.transform.getRelativeMatrix3D( doc.stage ); 라는 소스를 통해 doc 객체의 matrix 좌표를
stage 로 변환해주면 무슨 이유에서인지 x 의 위치가 정확히 1/5 로 줄어들어 표시됩니다.
예상컨데 root.transform.perspectiveProjection 에서 원근투영시 거리비를 다시 조절해주는것 같습니다.
이에 관해 자세한 내용이나 의견 있으신 분은 알려주시면 적극 반영하겠습니다 ^^.


위의 소스를 적용시켜 만든 예제 입니다.




부가적으로 Cross Product  Dot Product 에 대한 부가적인 설명을 원하시면
[Flash 3D].03 3D공간 돌아다니기(1.Vector) <-- 를 보시기 바랍니다.





Posted by 김경한