OpenGL

OpenGL: Normal Vector

FunnyPR 2014. 5. 4. 18:48

■ OpenGL: Normal Vector


1. 법선벡터

법선(法線, normal)벡터: 임의 두 점사이 직선에 90도 각도로 수직을 이루는 선을 법선이라고 함.

- 아나 한국말은 용어가 어렵다. 한문 하나하나 봐야 이해가 된다. 법은 法일반적인 법법이고 선은 줄선線인데 법에 다른 의미로 모형 도는 꼴 법이라고도 할 수 있고.... 모형의 선? 아놔.. 이렇게 만드니 이해하기 어렵다. 그냥 그림으로 보는게 좋다. 



그림에 파란색 아이를 법선 벡터라고 하고 이 벡터는 각 꼭지점을 지나는 평면을 그리면 무수하게 많이 표현될 수 있다. 


3D 개념에서 법선벡터를 이해하는게 중요하다고 한다. 


왜 모든 꼭지점(Vertex)에 법선 벡터를 만들어야 하나?

-  모든 꼭지점에 법선 벡터를 사용함으로써 울퉁불퉁한 곡면을 부드럽게 표현, 완벽한 조명 적용 가능 하다고 함


http://opengl.czweb.org/ch09/275-279.html



 

위 그림에서 x, y 평면에 면이 하나 있고 점 (1,1,0)이 존재 한다. 이 점을 기준으로 수직으로 (1,10,0)을 그었을때 이 직선을 법선벡터(Normal Vector)이라고 함 





법선벡터를 좀더 간단히 표현하기 위해 기존의 (1, 1, 0 ) - (1, 10 ,0)을 하면 그림에서 볼 수 있듯이 Translated Normal vector이 나오게 된다.


벡터란 방향을 알려주는 역할을 하며 여기서는 버텍스나 폴리곤이 어떤 방향으로 위치해 있는지 OpenGL에게 알려주게 됨


1
2
3
4
5
6
glBegin(GL_TRIANGLES);
        glNormal3f(0.0f, -1.0f, 0.0f);
        glVertex3f(0.0f, 0.0f, 60.0f);
        glVertex3f(-15.0f, 0.0f, 30.0f);
        glVertex3f(15.0f,0.0f,30.0f);
glEnd();


위 소스에 보면 삼각형을 만드는데 3개의 꼭지점이 있고 법선벡터가 y 축의 -1.0으로 설정된것을 확인할 수 있다. 법선벡터 설정은 glNormal3f 함수를 사용한다. 


폴리곤 설정시 법선벡터는 폴리곤의 앞으로 나아감.


2. 단위 법선 벡터

법선벡터 -->정규화 --> 단위 벡터 --> OpenGL

단위가 1인 벡터를 단위벡터라고 함. 

단위가 1인 법선벡터를 만들기 위해서 정규화(Normalization) 과정이 들어간다. 

glEnable(GL_NORMALIZE); // 효율적이지 못하다. 

glEnable(GL_RESCALE_NORMALS); // 단위 길이(1)이 아니지만 같은 비율을 통해 단위길이로 변환할 수 있음

때문에 직접 계산하는것이 프로세싱 속도를 높이는데 도움이 된다. 


단위벡터 만들기: (x^2 + y^2 + z^2)^1/2 하면 됨



3. 법선 벡터 찾기 




위 4점으로 만들어진 Polygon(면)에서 법선 벡터를 어떻게 구할까?

3점만 있으면 구하기 쉽다. 

위 점들 중 3개점을 각각 P1, P2, P3라 지정하고 P1과 P2를 연결하는 V1 벡터, P1과 P3를 연결하는 V2벡터로 지정





수학: 두 벡터가 한점에서 만나면 평면을 만들 수 있고, 두 벡터 V1, V2 외적을 구하면 그 평면의 법선벡터를 구할 수 있다.

1. 3지점을 얻어 한점에서 만나는 두개의 벡터를 그림 

2. 두 벡터의 외적을 구하여 법선벡터를 구함




http://opengl.czweb.org/ch09/279-282.html


법선벡터 구하는 예제

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
// Points p1, p2, & p3 specified in counterclockwise order
void calcNormal(float v[3][3], float out[3])
        {
        float v1[3],v2[3];
        static const int x = 0;
        static const int y = 1;
        static const int z = 2;
 
        // Calculate two vectors from the three points
        v1[x] = v[0][x] - v[1][x];
        v1[y] = v[0][y] - v[1][y];
        v1[z] = v[0][z] - v[1][z];
 
        v2[x] = v[1][x] - v[2][x];
        v2[y] = v[1][y] - v[2][y];
        v2[z] = v[1][z] - v[2][z];
 
        // Take the cross product of the two vectors to get
        // the normal vector which will be stored in out[]
        out[x] = v1[y]*v2[z] - v1[z]*v2[y];
        out[y] = v1[z]*v2[x] - v1[x]*v2[z];
        out[z] = v1[x]*v2[y] - v1[y]*v2[x];
 
        // Normalize the vector (shorten length to one)
        ReduceToUnit(out);
        }


좀 더 공부해서 법선벡터를 많이 사용할때의 곡면 표현의 차이점을 봐야 겠다.