'프로그래밍/OpenGL'에 해당되는 글 7건

  1. 2009.04.29 Texture Mapping
  2. 2009.04.25 옥트리(octree)
  3. 2009.04.24 OpenGL Viewing
  4. 2009.04.23 OpenGL 기초 1
  5. 2009.04.22 Picking 사용하기
  6. 2009.04.22 void glutIdleFunc(void (*func)(void))
  7. 2009.04.22 void glutPostRedisplay(void)
프로그래밍/OpenGL2009. 4. 29. 12:21

1. Why is the use of Texture Mapping

- 적은 수의 폴리곤으로 효과적인 렌더링을 할 수 있다.

 

1.2. Steps of Texture Mapping

① 텍스처 오브젝트를 만들고, 오브젝트에 해당하는 텍스처를 명시해야 한다.

② 텍스처가 어떻게 각각의 픽셀과 연관되어 있는지에 고나해 나타내어야 한다.

③ 텍스처 매핑을 활성화 한다.

④ 텍스처와 기하학적 좌표가 제공된 장면을 렌더링 한다.

 

2. Example Texture Mapping

AUX_RGBImageRec *LoadBMPFile(char *filename)
{
	FILE *hFile = NULL
	if(!filename) 
		return NULL
	
	if(hFile = fopen(filename, "r"))
	{
		fclose(hFile);
		return auxDIBImageLoad(filename);
	// BMP 정보를 리턴해 준다
	}

	return NULL
}

void CreateTexture()
{
	AUX_RGBImageRec *texRec[1];	// RGB정보를 가지는 구조체 정의							// 텍스쳐매핑초기화
	if(texRec[0] = LoadBMPFile("img.bmp")) 
	{
		glGenTextures(1, &g_Texture[0]); 
		// 객체의 이름을 만들어 준다
		// 첫 번째 인자: 몇 개의 텍스쳐 텍스쳐 맵핑 소스를 생성할 것인지 지정
		// 두 번째 인자: 첫 번째 텍스쳐 맵핑 소스의 식별자의 주소값
		glBindTexture(GL_TEXTURE_2D, g_Texture[0]); 
		//앞으로 설정할 텍스쳐의 식별자를 지정
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		//GL_TEXTURE_MIN_FILTER: 맵핑 소스가 맵핑되어질 물체보다 클 경우
		//GL_TEXTURE_MAG_FILTER: 맵핑 소스가 맵핑되어질 물체보다 작을 경우
		//GL_NEAREST_MIPMAP_LINEAR   OpenGL   고화질
		//GL_NEAREST_MIPMAP_NEAREST  OpenGL   저화질. 권장.
		//GL_NEAREST_MIPMAP_LINEAR   OpenGL   고화질
		//GL_LINEAR_MIPMAP_NEAREST   Direct3D 저화질. 권장.
		//GL_LINEAR_MIPMAP_LINEAR    주로 배경(벽이나 지면의 재질감)의 설정
		//GL_LINEAR : 보간법
		//GL_NEAREST : 최근점법
		glTexImage2D(GL_TEXTURE_2D, 0, 3, texRec[0]->sizeX, texRec[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, texRec[0]->data);
		// 두 번째 인자 : 항상 0, 세 번째 인자: 색상 구성 요소의 개수 RGB 3		   개,여섯번째: 이미지 경계에 대한 픽셀 두께, 여덟 번째: 색상 구성 요		   소들이 갖는 값의 타입
	}

	if(texRec[0])		// 할당된 메모리를 해제
	{
		if(texRec[0]->data)
		{
			free(texRec[0]->data);
			free(texRec[0]);
		}

	}	

	glEnable(GL_TEXTURE_2D);		//텍스쳐 맵핑 사용함을 알림
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}

void RenderScene()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	gluLookAt(0, 0, 6,	0,0,0,	0,1,0);

	glBindTexture(GL_TEXTURE_2D, g_Texture[0]);
	glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);
		glVertex3f(-1, 1, 0);

		glTexCoord2f(0.0f, 0.0f);
		glVertex3f(-1, -1, 0);

		glTexCoord2f(1.0f, 0.0f);
		glVertex3f(1, -1, 0);

		glTexCoord2f(1.0f, 1.0f);
		glVertex3f(1, 1, 0);
	glEnd();

	SwapBuffers(g_hDC);
	
}

※ texel - 텍스처 데이터(컬러, 명도, 컬러와 알파 데이터)들의 사각형 배열 각각의 값
※ tessellation - 폴리곤의 각 꼬지점만을 명시해주면 자동으로 폴리곤을 오목한 부분이 없도록 쪼개서 연출해주는 기능

'프로그래밍 > OpenGL' 카테고리의 다른 글

옥트리(octree)  (0) 2009.04.25
OpenGL Viewing  (0) 2009.04.24
OpenGL 기초  (1) 2009.04.23
Picking 사용하기  (0) 2009.04.22
void glutIdleFunc(void (*func)(void))  (0) 2009.04.22
Posted by 마블(이환문)
프로그래밍/OpenGL2009. 4. 25. 20:03

Octree

정의

옥트리는 삼차원 공간에서 오브젝트를 표현하기 위한 자료구조이다. 이는 자동적으로 그것들을 계층화하여 그룹화하고, 공간 내의 빈 부분에 대한 표현을 피한다.

첫 번째 옥트리 노드는 루트 셀인데, 아래의 그림에서 보이듯이 이는 여덟 개의 연속되는 요소들의 배열이다. 이들 각 요소들은 여덟 개의 연속된 요소들 중 다른 하나를 가리킬 수 있다. 여기에서 각각은 여덟 개의 연속되는 요소들 중 다른 하나를 가리키는 식인데, 이는 특정한 최대 숫자의 레벨에 도달할 때까지 계속된다. 마지막 레벨은 단말 레벨이며, 여기에서 단말 요소나 복셀(voxel)이 저장된다.

 
복셀 검색 원리

위의 그림은 자료 구조가 메모리(왼쪽)와 그것의 삼차원 공간 표현(오른쪽) 사이에서 어떻게 대응되는지를 보여준다. 트리는 여덟 개의 복셀과 다섯 개의 레벨을 가지고 있다. 각 레벨은 서로 다른 색으로 표현된다. 옥트리의 마지막 레벨에 저장되는 여덟 개의 레벨은 분홍색으로 표현된다. 위의 그림의 표는 마지막 셀에 있는 다섯번 째 복셀(index 4)의 좌표를 보여준다. 그것의 좌표는 : 31, 30, 30이며, 후에 오른쪽에서 이진 형식으로 보여진다. 마지막으로 각 좌표 비트와 연관된 각 열도 옥트리의 레벨과 관련이 있다. 각 열의 비트를 합치면, 관련 레벨을 위한 셀의 각 요소에 대한 (테이블의 마지막 열에 나온) 인덱스를 획득하게 된다. 그리고 이것은 트리를 순회하고 검색된 복셀을 찾는 데 사용된다. 이것이 옥트리에서 주어진 복셀을 검색하는 원리이다.

(역주 :

각 열을 합칠 때, x를 0비트, y를 1비트, z를 2비트로 취급하면, 1 + 2 + 4 = 7, 0 + 0 + 4 = 4가 된다. 위의 표에서 열이 나타내는 숫자 0, 1, 2, 3, 4는 복셀의 인덱스를 의미하고 있다.

그런데 표가 이상하다. 비트의 합이 0 ~ 7까지 순서대로 나오는게 맞을텐데 다 7이고 4번째 열만 4다

)

이러한 구조의 주요 이점은 복셀 좌표가 저장되지 않고, 순회되는 요소들의 위치에 의해 암묵적으로 내포된다는 것이다. 이것은 좌표가 저장하기에는 크고 성가신 고해상도 복셀 공간에서 매우 편리하다. 3D 그리드도 복셀 위치를 내포하는 좌표를 가지고 있지만, 대부분의 볼륨이 비어있는 경우에도 볼륨 내의 모든 복셀을 표현해야 한다는 심각한 단점을 가지고 있다.

메모리 점유

위의 단말 레벨에서 모든 셀의 요소들이 셀을 가리키고 있다면, 그 옥트리를 "꽉찬 옥트리(full octree)"라고 부른다. n개의 레벨을 가지고 있는 꽉찬 옥트리는 해상도 2n x 2n x 2n의 정규 3D 그리드와 같은 복셀 개수를 포함한다(예를 들어 꽉찬 옥트리가 5레벨이라면 32 x 32 x 32 해상도를 가진 3D 그리드와 같다). 이런 극단적인 경우에 옥트리는 관련 3D 그리드보다 14% 많은 방(역주 : 메모리공간인듯)을 차지한다. 그러나 복셀이 볼륨 대신에 서피스를 표현한다면, 대부분의 공간은 비어있으며 그것은 옥트리 내에 표현되지 않는다. 이런 경우에 옥트리는 매우 경제적이며, 적은 메모리 소비만으로 고해상도 복셀 공간을 만들 수 있게 해 준다

'프로그래밍 > OpenGL' 카테고리의 다른 글

Texture Mapping  (0) 2009.04.29
OpenGL Viewing  (0) 2009.04.24
OpenGL 기초  (1) 2009.04.23
Picking 사용하기  (0) 2009.04.22
void glutIdleFunc(void (*func)(void))  (0) 2009.04.22
Posted by 마블(이환문)
프로그래밍/OpenGL2009. 4. 24. 14:03

뷰잉

I. 개요

A. 뷰잉 변환: 카메라가 Scene을 향하도록 설정한다

B. 모델링 변환: 원하는 장면을 화면에 담도록 모델을 구성한다

C. 투영 변환: 사용할 카메라 렌즈를 선택하거나 줌을 조절한다

D. 뷰포트 변환: 사진의 크기를 결정한다

E. 연산들의 순서: 뷰잉 변환이 모델링 변환보다 먼저 수행되도록 작성해야 하며, 투영 변환이나 뷰포트 변환은 드로잉 작업이 수행되기 전에 어느 곳에 나와도 상관없다.

1. 오브젝트 좌표 -> 모델뷰행렬 (눈 좌표) -> 투영행렬 (클립 좌표) -> 투시분할 -> 정규화 장치 좌표 -> 뷰포트 전환(윈도우 좌표)

II. 변환 행렬

A. 컴퓨터 그래픽을 이해하기 위해서는 가장 핵심적이고 기본이 되는 4x4 행렬 형식의 변환을 설명하는 것으로부터 시작된다.

B. 기본변환

1. 이 절에서는 평행 이동, 회전, 크기 같은 기본변환들을 알아본다

C. 평행이동(Translation)

1. 한 위치를 다른 위치로 변경하는 것은 평행이동 행렬 T로 표현된다. 이 행렬은 하나의 벡터 t=(tx,ty,tz)를 이용하여 개체를 이동시킨다.

2. T(t) = T(tx,ty,tz) = ( 1 0 0 tx )

( 0 1 0 ty)

( 0 0 1 tz)

( 0 0 0 1)

  



D. 회전(rotation)

1. 회전 행렬은 Rx(ɸ), Ry(ɸ), Rz(ɸ)에 의해 표시된다.

2. 이 행렬들은 하나의 개체를 x, y, z축으로 ɸ라디안 만큼 회전시킴을 의미한다.

Rx(a)= 

  Ry(a) =
 
Rz(a) =

E. 크기 조정(scaling)

1. 크기 조정 행렬 S(s) = S(x,y,z)는 한 개체를 x,y,z방향으로 각각 x배, y배, z배만큼 확대 축소한다.

2. 조정행렬

  


3. 만약 x = y = z 이면 크기 조정 연산은 균등(uniform)하다고 하고 그렇지 않은 경우는 비균등(nonuniform)하다고 한다.

F. 예제

1. 지금까지 각각의 변환 행렬들에 대해서 살펴보았다. 그렇다면 어떤 한 점을 어느 지점으로 이동 시킨 후에 다시 어떤 축을 중심으로 회전하고 크기를 변경시키고자 할 때 행렬이 어떤식으로 계산되어 지는지를 알아보도록 한다

2. p = (3,2,1)의 점을 X축으로 -1만큼 이동 후 z축으로 90 회전시킬때의 행렬

   =>  
 

3. 위 행렬은 아래와 같이 계산되어 질 수도 있음


G. 본 절에서 설명된 변환 행렬 이외에도 쉬어변환 강체 변환, 법선 벡터 변환등 다양한 행렬 표현이 존재한다

III. 뷰잉 및 모델링 변환

A. 고정 좌표계

1. 모델의 위치, 방향, 크기 등에 영향을 미치는 행렬 곱셈을 고정 좌표계 관점에서 생각하는 경우에는 코드에 나온 순서와 반대로 곱셈이 수행된다는 것을 명심해야 한다.

B. 로컬 좌표계 이동하기

1. 행렬 곱셈을 바라볼때 변환할 오브젝트가 고정 좌표계에 있지않고, 오브젝트에 로컬 좌표계가 달려 있는 것처럼 생각할 수 있다. 모든 연산들은 이러한 좌표계에 상대적으로 수행된다.

2. 모델링 변환

a) glTranslate{fd}(TYPE x, TYPE y, TYPE z);

(1) 인자로 지정된 x,y,z 값 만큼 오브젝트(또는 로컬 좌표계)를 평행 이동 시키도록 지정된 행렬과 현재 행렬을 곱한다.

b) glRotate{fd}(TYPE angle, TYPE x, TYPE y, TYPE z);

(1) 원점에서 x,y,z에 이르는 선을 기준으로 오브젝트(또는 로컬 좌표계)를 반시계 방향으로 회전시키는 행렬과 현재 행렬을 곱한다. angle 매개변수에는 회전할 각도를 지정한다

c) glScale{fd}(TYPE x, TYPE y, TYPE z);

(1) 오브젝트를 각 축을 따라 늘이거나 , 대칭이동 행렬과 현재 행렬을 곱한다. 오브젝트를 구성하는 점의 x,y,z 좌표는 인자로 주어진 x,y,z 값과 곱해진다.

d) glMultiMatrix

C. 뷰잉 변환

1. 뷰잉 변환을 사용하면 시점의 위치와 방향을 변경할 수 있다.

2. glTranslate와 glRotate 사용하기

a) 카메라는 초기에 z축의 음의 방향을 향하고 있다는 점에 주의

b) 오브젝트를 볼 수 있게 하기 위해서는 몇가지 변환을 수행해야 한다.

c) 시점을 오브젝트 뒤로 이동시킬 수 있다.

3. gluLookAt 유틸 사용하기

a) void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery,GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz);

b) 이 행렬은 뷰잉 행렬을 정의한 뒤 이를 현재 행렬의 오른쪽에 곱한다. 원하는 시점은 eyex, eyey, eyez로 지정한다. centerx, centery, centerz인자로 원하는 시선에 존재하는 임의의점을 지정할 수 있지만, 일반적으로 바라보는 장면의 가운데 지점을 지정할 때 사용한다. upx, upy, upz 인자는 위쪽에 해당하는 방향을 가리킨다

IV. 투영 변환

A. 기본형식

1. glMatrixMode(GL_PROJECTION)

2. glLoadIdenty();

B. 원근투영

1. 원근 투영의 가장 큰 특징은 바로 포쇼트닝(foreshortening, 단축법, 오브젝트가 카메라로부터 멀리 떨어질수록 작게 그리는 기법)이다. 이러한 효과는 관측 공간을 피라미드의 절두체로 정의할 때 나타난다.

2. 절두체를 정의하는 glFrustum() 커맨드는 먼저 원근 투영을 나타내는 행렬을 계산한 다음, 그 결과를 현재 투영 행렬과 곱한다.

3. glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);

a) 원근 형태의 절두체를 나타내는 행렬을 생성하고, 이를 형재 행렬과 곱한다. left, bottom, -near과 right, top, -near은 각각 카메라와 가까운곳에 위치한 클리핑 평면의 좌측 하단 모서리와 우측 상단 모서리 좌표를 나타낸다. near와 far인자는 각각 시점과 가까이 있는 클리핑 평면과 멀리 떨어진 클리핑 평면까지의 거리를 나타낸다.


b) gluPerspective(GLdouble 래표, GLdouble aspect, GLdouble near, GLdouble far);

(1) 원근 대칭 절두체를 나타내는 행렬을 생성하고 이를 현재 행렬과 곱한다. fovy 인자는 yz 평면상의 FOV각도를 나타내며, 이 값은 [0.0, 180.0]을 벗어날 수 없다. aspect 인자는 절두체의 종횡비를 나타낸다. near과 far는 각각 시점과 두 클리핑 평면 사이의 거리를 나타내며 반드시 양수로 지정되어야 한다.

C. 직교 투영(orthogonal projection)

1. 평행 육면체 모양의 관측 공간을 사용한다

2. 원근 투영과 달리 관측 공간의 양 끝면의 크기가 일정하기 때문에 카메라 거리가 오브젝트의 모양에 영향을 미치지 않는다

3. 건축 설계도나 CAD 설계등과 같이 오브젝트의 크기와 각도를 정확히 유지해야 하는 애플리케이션에서 주로 사용된다.

4. glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);

a) 직교 평행 관측 공간에 대한 행렬을 생성하고 이를 현재 행렬과 곱한다.


V. 뷰포트 변환

A. 뷰포트는 이미지가 그려질 윈도우의 직사각형 모양의 영역을 뜻한다

B. 윈도우 좌표로 측정됨, 이들은 윈도우의 좌측 하단 모서리를 기준으로 나타낸 스크린상의 픽셀 위치로 표현한다.

C. 관측공간을 벗어난 정점들은 모두 클리핑 된다.

D. 뷰포트 정의하기

1. 기본적으로 스크린 상에 윈도우를 생성하는 작업은 윈도우시스템이 담당한다

2. 그러나 기본적으로 윈도우를 처음 생성할 때 전체 윈도우에 해당하는 픽셀 영역을 뷰포트로 설정하도록 되어있다.

E. void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);

1. 최종 이미지가 매핑될 윈도우상의 픽셀 사각형을 정의한다.

2. (x,y)매개변수는 이러한 뷰포트의 좌측 하단 모서리를 나타낸다

3. width와 height는 뷰포트의 크기를 지정한다.

 

※ 다시한번 아래그림을 보면서 행렬과 좌표의 변화를 단계별로 생각해보자!


Reference :http://www.gisdeveloper.co.kr/opengl_tutorials/opengl15/15.htm

Sample Code

void init(void)

{

glClearColor(0.0, 0.0, 0.0, 0.0);

glShadeModel(GL_FLAT);

}

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(1.0, 1.0, 1.0);

glLoadIdentity();

gluLookAT(0,0, 0.0, 5, 0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glScalef(1.0, 2.0, 1.0);

glutWireCube(1.0):

glFlush();

}

  

void reshape(int w, int h)

{

glViewport(0, 0, (GLsizei) w, (GLsizei) h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glFrustum(-1.0, 1.0, -1, 0, 1.0, 1.5, 20.0);

glMatrixMode(GL_MODELVIEW);

}

  

int main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);

glutInitWindowSize(500,500);

glutInitWindowPosition(100,100);

  

gluitCreateWindow(argv[0]);

init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutMainLoop();

return 0;

}

int DrawGLScene(GLvoid)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity(); //<1>

glTranslatef(0.0f, 0.0f, -22.0f); //<2>


glPushMatrix(); //<3>

glRotatef(o1_rot, 0.0f, 1.0f, 0.0f); //<4>

gluQuadricDrawStyle(obj, GLU_FILL); //<5>

glColor3f(0.9f, 0.9f, 0.9f); //<5>

gluSphere(obj, 2.0f, 24, 24); //<5>

gluQuadricDrawStyle(obj, GLU_LINE); //<5>

glColor3f(0.6f, 0.6f, 1.0f); //<5>

gluSphere(obj, 2.1f, 24, 24); //<5>

glPopMatrix(); //<6>


glPushMatrix(); //<7>

glRotatef(o2_rot1, 0.0f, 1.0f, 0.0f); //<8>

glTranslatef(distance, 0.0f, 0.0f); //<9>

glRotatef(o2_rot2, 0.0f, 1.0f, 0.0f); //<10>

gluQuadricDrawStyle(obj, GLU_FILL); //<11>

glColor3f(0.9f, 0.9f, 0.9f); //<11>

gluSphere(obj, 0.7f, 12, 12); //<11>

gluQuadricDrawStyle(obj, GLU_LINE); //<11>

glColor3f(1.0f, 0.6f, 0.6f); //<11>

gluSphere(obj, 0.75f, 12, 12); //<11>

glPopMatrix(); //<12>


o1_rot+=0.5f; if(o1_rot>359.5f) o1_rot=0.0f; //<13>

o2_rot1+=0.05f; if(o2_rot1>359.95f) o2_rot1=0.0; //<13>

o2_rot2+=2.0f; if(o2_rot2>358.0f) o2_rot2=0.0; //<13>


return TRUE;

}

i) <1>번 코드는 변환 행렬을 단위 행렬로 초기화 시켜주는 예이다.

ii) <2>번 코드는 이동 변환 행렬을 이용해서 좌표축을 Z축으로 -20만큼 이동한 것이다. 이렇게 이동한 이유는 우리가 OpenGL에서 물체를 바로보는 눈의 위치가 (0,0,0)에 있기 때문이다. 만약 이러한 이동이 없이 물체를 그려준다면 물체의 위치와 눈의 위치가 같게 되어서 물체가 보이지 않으므로 물체를 뒤쪽으로 이동시켜야 그려줌으로써 물체가 잘 보이도록 해주는 것이다.

iii) <3>번 코드에서 <6>번 코드까지 지구를 그려주는 것이다. 지구는 제자리에서 자전만 한다.

iv) <3>번 코드는 지금까지 변환행렬에 의해서 변환된 좌표축을 저장해 놓는 것이다.

v) <4>번 코드는 y축을 기준으로해서 회전을 o1_rot 각 만큼 회전을 시키는 것이다. 결과적으로 <2>번 코드에서의 이동 변환 행렬과 <4>번 코드의 회전 변환 행렬의 연산으로 좌표축이 변경될 것임을 알수있다.

vi) <5>번 코드들은 지구를 그려주는 코드들이다. (자세한 설명은 Quadric 객체를 설명한 장을 참고하기 바란다)

vii) <6>번 코드는 <3>번 코드에서 저장해둔 좌표축을 꺼내는 것인데 이렇게 함으로써 <4>번 코드에 의해 변환되기 이전의 좌표축으로 되돌릴수있다.

viii) <7>부터 <12>번까지는 달을 그려주는 것이다. 달은 지구를 중심으로 공전하며 또 스스로 자전한다.

ix) <7>번 코드 다시 변환행렬을 스택에 저장한다.

x) <8>번 코드는 y축을 기준으로 회전을 o2_rot1 각 만큼 하게 된다.

xi) <9>번 코드는 x축으로 distance만큼 이동을 하게된다. 결과적으로 <8>과 <9>번 코드에 의해서 달은 지구를 중심으로 공전을 하게되는 것이다.

xii) <10>번 코드는 y축을 기준으로 o2_rot2 각 만큼 회전하게 된다. 이 코드로써 달이 자전 하게 된다.

xiii) <8>, <9>, <10>번의 변환행렬의 순서는 중요하다. 순서가 바뀔 경우 우리가 원하는 동작과 위치는 잘못될 것이다.

xiv) <11>번 코드는 달을 그려주는 코드들이다. (자세한 설명은 Quadric 객체를 설명한 장을 참고하기 바란다)

xv) <12>번 코드는 다시 <7>번 코드에 의해서 저장된 변환 행렬을 꺼내는 것이다.

xvi) <13>번 코드들은 지구와 달의 회전각들을 일정하게 증가시켜주는 코드들이다.

xvii) 이렇게 정리를 하면 되겠다. 물체 마다 하나씩의 지역 좌표계를 둔다는 것이다. 즉 PushMatrix와 PopMatrix 사이에서 물체의 변환 행렬을 정의해주면 다른 물체에는 전혀 영향을 받지 않으므로 각 물체마다 독립적으로 생각해줄 수 있다.

 

 

 

 

 

 

'프로그래밍 > OpenGL' 카테고리의 다른 글

Texture Mapping  (0) 2009.04.29
옥트리(octree)  (0) 2009.04.25
OpenGL 기초  (1) 2009.04.23
Picking 사용하기  (0) 2009.04.22
void glutIdleFunc(void (*func)(void))  (0) 2009.04.22
Posted by 마블(이환문)
프로그래밍/OpenGL2009. 4. 23. 16:20

1. OpenGL의 좌표계

- 오른손 좌표계를 사용함

1.1 Viewport

- 논리적 좌표를 물리적인 화면 픽셀 좌표로 전환하는 과정



1.2 Local coordinate system

- 3D에서 object는 정점(vertex) 리스트로 구성된다. 그 정점들을 기준좌표(0, 0, 0)으로 부터의 거리. 즉, 상대적 좌표리스트로 구성됨.

1.3 World coordinate system

- Local coordinate system으로 구성된 오브젝트를 실제의 위치상에 배치하기 위해서는 월드상의 좌표계로 이동하여 계산하도록 한다.


1.4 Camera coordinate system

- 카메라가 보고 있는 위치에 따라 오브젝트가 다르게 보이므로 최종적으로 카메라좌표를 기준으로 각 오브젝트들의 위치계산을 해야 한다.

- 관측지점과 관측 방향을 알아야 함.

 

2. 투영

- 3D 좌표계 내에서 만들어진 지오메트리들을 편평한 2D 공간으로 옮기는 과정.


2.1 직교 투영(orthographic projection)

- 정사각형 또는 직사각형의 영역 내에 모든 것이 투영.

- 그 영역을 벗어나는 것들은 그려지지 않는다.

- 영역 내에 있는 모든 물체들이 거리에 관계없이 모두 같은 크기 비율로 표현


2.2 원근 투영(perspective projection)

- 물체의 거리에 따라서 2D 화면에 나타나는 크기가 달라짐


3. OpenGL Rendering Pipeline

 

3.1 Display list

- 기하학적인 정보를 나타내는 데이터든, 픽셀을 나타내는 데이터든 상관없이 모든 데이터들을 display list에 저장해둘 수 있다.

3.1.1 Display list를 사용하는 이유

- OpenGL 커맨드들을 나중에 다시 사용하기 위해서 저장하는 데 사용되기 때문에 성능을 향상시켜 줄 수 있다.

3.2 평가자

- 모든 기하 프리미티브들은 결국 정점으로 표현된다. 매개변수 곡선이나 곡면은 기저 함수라고 불리는 다항 함수와 제어점들로 표현된다. 평가자를 사용하면, 제어점으로부터 곡면을 표현하는 데 사용되는 정점들을 구할 수 있다. 이때 다항식 매핑(polynomial mapping)이라는 기법을 사용하면, 제어점으로부터 표면 법선(surface normal), 텍스처 좌표, 컬러, 공간 좌표 등을 얻을 수 있다.

- 제어점만으로 커브나 표면상의 임의의 점을 지정 하여, 커브나 표면 렌더링 가능.

3.3 정점 연산(Per-Vertex Operation)

- 공간 좌표와 같은 일부 정점 데이터들을 4X4 부동 소수점 행렬로 변환.

- 3D 공간의 한 지점을 나타내던 공간 좌표를 스크린상의 한 지점으로 투영 시킨다.

 

3.4 Primitive Assembly

- 주된 부분은 clipping 수행.

3.5 Rasterization

- 기본도형에 속한 영역을 한 줄씩 픽셀들로 채우는 과정

- 기하 데이터와 픽셀 모이터를 모두 fragment로 변환한다.

- 각각의 fragment들은 사각형으로 되어 있으며, 프레임버퍼의 한 픽셀에 대응된다.


3.6 Fragment 연산

- 특정한 fragment 연산을 tngiod하여 특정한 fragment들을 변경하거나 제거한다

- 가장 먼저 수행하는 연산은 텍스처 메모리로부터 각각의 fragment에 대한 텍셀(texture element)를 생성하여 해당 fragment에 적용하는 텍스처링이다. 텍스처링 이후 fog연산과 scissor 테스트, 알파 테스트, 스텐실 테스트, 깊이 버퍼 테스트 등을 차례로 수행

※ scissor 테스트 : 응용 프로그램은 뷰포트 안에 가위 사각형 이라고 하는 사각형 영역을 지정할 수 있다. 그 사각형은 렌더링이 일어나는 영역을 결정한다

'프로그래밍 > OpenGL' 카테고리의 다른 글

옥트리(octree)  (0) 2009.04.25
OpenGL Viewing  (0) 2009.04.24
Picking 사용하기  (0) 2009.04.22
void glutIdleFunc(void (*func)(void))  (0) 2009.04.22
void glutPostRedisplay(void)  (0) 2009.04.22
Posted by 마블(이환문)
프로그래밍/OpenGL2009. 4. 22. 15:19

1) Picking의 원리
우리가 화면에서 무엇인가를 선택할때는 화면을 보고 그 위에 마우스를 올리고 클릭한다. 그러나 컴퓨터는
멍청해서 이게 어디인지 모른다. 그래서 화면을 다시 그리면서 그리는 붓에 마우스가 걸리면 그제야 그게 어딘
지 알게된다. 예를들어 아래 표에서 화살표 위치를 픽킹했다면 컴터는 화면을 다 다시 그리면서 저 칸에 그림
을 그리게 되면 "엇!! 여기 마우스가 있었군!!" 하고 알게된다.

위와 같은 원리로 픽킹을 하게 되므로 다시 그릴 때 마우스 위치에 걸리면 현재 자기가 무엇을 그리는지를
알아야 되고(Name을 이용) 검사할 칸의 크기를 알아야 되고(int형으로 가로세로 픽셀수를 정해줌) 몇 개가 어
느 위치에 그릴 때 선택되었는지(버퍼)를 알아야 한다.

2) Picking 예제

 

//픽킹을 위한 버퍼의 크기인데 넉넉히 줘도 된다. 모자라면 안된다.
#define BUFFER_LENGTH 64
//픽킹으로 사용되는 입력은 마우스의 좌표이다.
void PickingPlane(int mx, int my)
{
GLuint selectBuff[BUFFER_LENGTH];
GLint hits, viewport[4];
glSelectBuffer(BUFFER_LENGTH, selectBuff); //Picking에 사용될 버퍼를 설정한다.
glGetIntegerv(GL_VIEWPORT, viewport);//변환에 필요한 정보인 viewport정보를 얻어온다.
//여기서 부터는 랜더링이 화면에 되지 않는다. 즉, 앞에서 말한것처럼 컴퓨터가 마우스가 어디서
//걸리는지 찾기 위해서 다시 혼자 그려보는 그런 단계가 시작된다.
glRenderMode(GL_SELECT);
//현재의 프로젝션 메트릭스 저장.
//지금부터 설정되는 메트릭스의 순서에 유의해야 한다. 기본이 Modelview인데 새로 프로젝션을 설정하는데
//이후에 생긴 변환이 현재 사용하는 변환에 영향을 주지 않도록 push matrix를 하는것이다.
glMatrixMode(GL_PROJECTION);
glPushMatrix();//저장.
//랜더링과 같은 환경을 구현하기 위해서 똑같이 다시 그릴수 있는 변환을 한다.
glLoadIdentity();
gluPickMatrix(mx,viewport[3]-my,2,2,viewport);
int w = viewport[2], h = viewport[3];
if(w<=h)
glOrtho(-BASE_UNIT,BASE_UNIT,
-BASE_UNIT*(GLfloat)h/(GLfloat)w,BASE_UNIT*(GLfloat)h/(GLfloat)w
,-BASE_UNIT,BASE_UNIT);
else
glOrtho(-BASE_UNIT*(GLfloat)w/(GLfloat)h,BASE_UNIT*(GLfloat)w/(GLfloat)h,
-BASE_UNIT,BASE_UNIT,
-BASE_UNIT,BASE_UNIT);
//똑같이 그리기 위해 변환과 네임을 쓰는건 다 그려준다.
glMatrixMode(GL_MODELVIEW);
glPushMatrix();//다른 부분에 영향을 주지 않도록 메트릭스 저장
RenderInit();
//다 똑같은데 이 함수만 다르다. 즉, 이름을 정해가면서 그린다.(뒤에서 다룸)
DrawCube(BASE_UNIT,true);
glPopMatrix();
//이상은 네임을 로드/푸시하는것 말고는 보통 상태에서 그리는 것과 같다.
//앞에서 저장한 프로젝션 메트릭스를 복구하기 위해 프로젝션으로 변경.
glMatrixMode(GL_PROJECTION);
glPopMatrix();//복구
//랜더링을 모두 실행.- 이제 어딘지 검사하기 위해서 OpenGL혼자 그려본 것이 끝났다.
//그럼 어디서 걸렸는지 녀석에게 물어보자.
glFlush();
//Picknig을 종료하면서 스택을 얻어온다. 즉, 녀석에게 니가 아는걸 알려달라고 하는 것과 같다.
hits = glRenderMode(GL_RENDER);
//다시 그림을 그리기 위해서 모델뷰로 변경한다. 이제부터는 다시 화면에 그려진다.
glMatrixMode(GL_MODELVIEW);
}

'프로그래밍 > OpenGL' 카테고리의 다른 글

옥트리(octree)  (0) 2009.04.25
OpenGL Viewing  (0) 2009.04.24
OpenGL 기초  (1) 2009.04.23
void glutIdleFunc(void (*func)(void))  (0) 2009.04.22
void glutPostRedisplay(void)  (0) 2009.04.22
Posted by 마블(이환문)
프로그래밍/OpenGL2009. 4. 22. 15:17

glutIdleFunc()를 이용하면 처리하고 있는 이벤트가 하나도 없을 때 실행될 함수를 설정할 수 있다. 이 함수는 연속적인 애니메이션이나 다른 백그라운드 프로세스(background process)를 위해서 유용하게 사용될 수 있다.

이 명령은 실행중인 이벤트가 없을 경우에 실행될 함수인 func를 설정하기 위해 사용된다. 만약에 NULL값을 넘겨주면 func는 실행되지 않는다.

'프로그래밍 > OpenGL' 카테고리의 다른 글

옥트리(octree)  (0) 2009.04.25
OpenGL Viewing  (0) 2009.04.24
OpenGL 기초  (1) 2009.04.23
Picking 사용하기  (0) 2009.04.22
void glutPostRedisplay(void)  (0) 2009.04.22
Posted by 마블(이환문)
프로그래밍/OpenGL2009. 4. 22. 15:17


GLUT이 현재 창을 새로고침 하도록 한다

'프로그래밍 > OpenGL' 카테고리의 다른 글

옥트리(octree)  (0) 2009.04.25
OpenGL Viewing  (0) 2009.04.24
OpenGL 기초  (1) 2009.04.23
Picking 사용하기  (0) 2009.04.22
void glutIdleFunc(void (*func)(void))  (0) 2009.04.22
Posted by 마블(이환문)