Graphics2010. 9. 7. 10:11

 

 

Normal Transforms

By Eric Haines (erich@acm.org)  and Tomas Möller (tompa@acm.org)

 

Normal이 어떻게 Transform되는가?

geometric object를 transform하는 행렬이 object의 normal을 변경할 수 있다.

그러나, 그 상황이 아닌 경우를 이해해야한다.

부적절한 transforming normals는 잘못된 culling과 linghting 결과를 유발한다.

incoming geometry를 잘 다루기 위해서는 transforms의 타입을 잘 알아야한다.

 

Normal은 반드시 역행렬의 전치행렬에 의해서 transform되야한다.

geometry를 transform하는 행렬을 M이라고하면, 이 geometry의 normal을 transform하기 위한 N은 아래의 것을 사용해야한다.

  1.                N = transpose( inverse(M) )

 

 

전치행렬은 대각 축을 따라서 뒤집은 형태다. 왼쪽이 주어진 행렬, 오른쪽이 전치행렬이다.

M = \begin{vmatrix} a & b & c \ d & e & f \ g & h & i \end{vmatrix}           M^{T} = \begin{vmatrix} a & d & g \ b & e & h \ c & f & i \end{vmatrix}


Figure 1 shows what can happen if the proper transform is not used.

[링크 깨짐. 직접 제작 필요]

 

  • 좌: original geometry
  • 중: 모델이 x축으로 0.5 scl되었고, normal이 이 scl 행렬을 사용했을 때
  • 우: 제대로된 normal 변형.

 

실제로, 행렬이 orthogonal임을 알면 inverse를 구할 필요가 없다. (i.e. 회전으로만 구성되어 있었다... ..; )

여기서는, original 행렬은 normals를 transform 가능하다. ortho행렬의 역행렬이 그것의 전치행렬이기때문이다.

Two matrix transposes cancel out, giving the original rotation matrix.

게다가, translation은 direction에 영향을 미치지 않기 때문에 몇 번이나 해도 상관없다.

transformation후에 normals의 renormalizing의 단계(크기를 1로 만드는 것)를 피할 수 있다.

회전&이동만 있는 행렬(rigid-body transforms)에 의해서는 길이는 보존되기 때문이다.

 

최종적으로, uniform scl을 가진 회전&이동으로 구성된 행렬이 사용되었다면, 

그런 scl은 transformed normal의 길이에만 영향을 주지 방향에는 영향을 주지 않는다.

uniform scl은 object의 크기를 동일하게 증감 시킨다. ( D3DXMatrixScaling( n, n, n )으로 만들어진 행렬 같은 것 )

non-uniform scl은 object를 stretch or squeeze할 수 있다. (i.e. xyz구분 없이 막 늘렸다 줄였다 할 수 있다)

uniform scl이 사용되면 normals는 renormalize 될 필요없다.

요약하면, Uniform Scl & Rotation & Translatoin으로 구성된 행렬로 object가 변환되면, normal은 안전하게 변환된다.

 

full inverse가 계산되었다고 할지라도, 행렬 좌우측 3x3의 adjoint(수반행렬)의 전치행렬만 요구된다.

수반행렬은 (계산된 행렬이 original 행렬의 행렬식으로 나누지 않는다는 것을 제외하고는) 역행렬과 비슷하다.

수반행렬은 역행렬을 구하는 것 보다 빠르다.

변환된 normal을 구하기만 하면 되므로 행렬식으로 나눌 필요가 없다.


표면 노말 변형을 삼각형으로 부터 구하는(e.g. 삼각형의 edges의 외적을 사용하는) 시스템에서는 문제가 되지 않는다.

그러나, 삼각형 정점들이 lighting을 위해 normal 정보를 가지고 있는 경우가 흔하기 때문에 normal transformation은 언급되어야만 한다.

 

 

부록: adjoint 계산. 3x3 행렬의 adjoint의 전치를 구하는 코드 제공.
  1.  
    typedef struct ModelMatrix {    
        float mtx[3][3];       // rotation/scale/shear matrix    
        float translate[3];    // translation
    } ModelMatrix;

    transpose_adjoint( ModelMatrix *m, ModelMatrix *adjoint )
    {
       
        // cofactor for each element
        adjoint->mtx[0][0] = m->mtx[1][1] * m->mtx[2][2] - m->mtx[1][2] * m->mtx[2][1] ;    
        adjoint->mtx[0][1] = m->mtx[1][2] * m->mtx[2][0] - m->mtx[1][0] * m->mtx[2][2] ;    
        adjoint->mtx[0][2] = m->mtx[1][0] * m->mtx[2][1] - m->mtx[1][1] * m->mtx[2][0] ;    
        adjoint->mtx[1][0] = m->mtx[2][1] * m->mtx[0][2] - m->mtx[2][2] * m->mtx[0][1] ;    
        adjoint->mtx[1][1] = m->mtx[2][2] * m->mtx[0][0] - m->mtx[2][0] * m->mtx[0][2] ;    
        adjoint->mtx[1][2] = m->mtx[2][0] * m->mtx[0][1] - m->mtx[2][1] * m->mtx[0][0] ;    
        adjoint->mtx[2][0] = m->mtx[0][1] * m->mtx[1][2] - m->mtx[0][2] * m->mtx[1][1] ;    
        adjoint->mtx[2][1] = m->mtx[0][2] * m->mtx[1][0] - m->mtx[0][0] * m->mtx[1][2] ;    
        adjoint->mtx[2][2] = m->mtx[0][0] * m->mtx[1][1] - m->mtx[0][1] * m->mtx[1][0] ;
    }

 

 

References

  1. Hanrahan, Pat, "A Survey of Ray-Surface Intersection Algorithms", chapter 3 in Andrew Glassner (editor), An Introduction to Ray Tracing, Academic Press Inc., London, 1989.
  2. Turkowski, Ken, "Properties of Surface-Normal Transformations", in Andrew Glassner (editor), Graphics Gems, Academic Press, Inc., pp. 539-547, 1990. http://www.worldserver.com/turk/computergraphics/index.html

 

 

내용 제대로 알지도 못하고 있다가, 면접가서 멍소리를 한 쓰라린 기억이... ㅜㅜㅎ

 

이 글은 스프링노트에서 작성되었습니다.

'Graphics' 카테고리의 다른 글

Normal vector compression  (0) 2011.07.11
Posted by codevania