[App 개발] NeHe Lesson 11
본문
**************************************
안녕하세요. 우리가 오늘 할 것이 무엇인지 알고 싶으신 분은 맨 밑에 있는 데모를 보시면 됩니다만, 별로 쓸모는 없습니다. 저는 오늘 여러분에게 사인 곡선을 이용한 애니메이션을 강의하는 bosco입니다. 이 강의는 tutorial 6 에 기초한 것이므로 적어도 그 강의 내용은 이해하고 계셔야 합니다. 소스 코드와 함께 있는 비트맵 그림을 모두 다운로드하셔야 합니다. 아니면 OpenGL이 사용할 수 있는 적당한 이미지를 여러분이 직접 사용하셔도 됩니다.
맨 처음 할 일은 tutorial 6을 열어서 #include 구문 바로 밑에 다음의 코드를 첨가하십시오. 이 코드는 프로그램에서 sin, cos등의 복잡한 수학 공식을 사용할 수 있도록 합니다.
#include
격자 모양의 좌표의 x, y, z 값을 저장하기 위하여 points 라는 배열을 쓸 것입니다. 격자는 45 x 45 크기이며 모두 44 x 44 개의 사각형을 만들 것입니다. wiggle_count 변수는 텍스쳐의 물결이 얼마나 빨리 움직이는지를 기록하는 변수입니다. 매번 두 번째 프레임마다 새 모션을 갱신합니다. 그리고 hold 변수는 깃발의 나부낌을 부드럽게 만드는 부동소숫점 변수입니다. 이 코드를 프로그램 맨 위의 #include 구문 밑, 그리고 GLuint texture[1] 사이에 첨가하십시오.
float points[ 45 ][ 45 ][3]; // 물결 격자의 좌표를 저장하는 배열
int wiggle_count = 0; // 얼마나 빨리 물결이 치는지를 기록하는 카운터
GLfloat hold; // 임시로 부동소숫점을 저장한다
이제 LoadGLTexture() 함수로 갑시다. 우리가 쓸 텍스쳐의 이름은 Tim.bmp 입니다. LoadBMP(“data/NeHe.bmp”)를 찾아서 이름을 바꿔주십시오.
if (TextureImage[0]=LoadBMP("Data/Tim.bmp"))
이번에는 InitGL() 함수의 마지막 return TRUE 전에 다음의 코드를 첨가합니다.
glPolygonMode( GL_BACK, GL_FILL ); // 뒷면을 채운다
glPolygonMode( GL_FRONT, GL_LINE ); // 앞면에는 선을 같이 그린다
여기서는 다각형의 뒷면을 채움으로써 다각형의 앞면만이 보이도록 합니다. 이것은 단순히 개인적인 취항입니다. 반드시 다각형의 위치, 꼭지점의 방향을 지정해 줘야 합니다. 잠시 제가 OpenGL을 배우는 데 있어서 가장 많은 도움을 받았던 책을 소개하려고 합니다. 물론 NeHe 사이트는 말할 것도 없고요. Addison-Wesley 에서 출판된 Programmer’s Guide to OpenGL 을 보세요. 개인적으로 가장 가치있는 책이었습니다.
다시 강의로 돌아와서, 위에서 첨가한 코드 밑에 다음의 코드를 넣습니다.
// x 평면을 모두 참조
for(int x=0; x<45; x++)
{
// y 평면을 모두 참조
for(int y=0; y<45; y++)
{
// 그물망에 물결을 치게 한다
points[x][y][0]=float((x/5.0f)-4.5f);
points[x][y][1]=float((y/5.0f)-4.5f);
points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));
}
}
잔물결의 돌출부를 없게 만드는 루프를 제안해 준 Graham Gibbons에게 감사의 말씀을 드립니다.
위의 이중 루프는 격자를 초기화합니다. 변수들은 단순히 루프 변수처럼 나누어서 초기화를 하고 있습니다. 깔끔한 방법인지는 잘 모르겠습니다. 부동소숫점을 썼을 때에 생길 이상한 그래픽 오류를 막기 위해 정수 루프를 썼습니다. 변수 x와 y를 5로 나누고 4.5를 뺀 값으로 물결의 중심 부분 좌표를 구했습니다. 축을 이동해서 동일한 효과를 구현할 수 있겠지만 저는 이 방법을 선호합니다.
points[x][y][2]는 사인 함수의 값입니다. sin()함수에는 라디안을 대입합니다. 먼저 부동소숫점 x를 40.0f와 곱하여 degree값을 취한 다음 360.0f를 나누고 pi 값을 곱하거나, 근사값을 취하여 2.0f를 곱하여 라디안으로 변환합니다.
DrawGLScene()함수를 처음부터 다시 기록하였으니, 다음의 코드로 바꿔 넣으십시오.
int DrawGLScene(GLvoid)
{
int x, y; // 루프 변수
float float_x, float_y, float_xb, float_yb; // 깃발을 작은 사각형으로 나누는 변수
루프를 조정하기 위해서 다른 변수를 사용합니다. 밑의 코드를 참조하십시오. 루프를 조정하거나 임시 값을 저장하는 것 외에 특별한 목적은 없습니다.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-12.0f);
glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);
glBindTexture(GL_TEXTURE_2D, texture[0]);
지금까지는 tutorial 6 에서 다 보신 것이고, 씬을 카메라에서 약간 더 멀리 떨어지게 했을 뿐입니다.
glBegin(GL_QUADS); // 사각형 그리기 시작
for( x = 0; x < 44; x++ ) // x 평면을 모두 참조
{
for( y = 0; y < 44; y++ ) // y 평면을 모두 참조
{
이제 다각형을 그리기 시작합니다. 앞에서 배열의 참조값을 int()함수를 써서 정수로 만들었기 때문에 여기서도 정수를 계속 사용하고 있습니다.
float_x = float(x)/44.0f;
float_y = float(y)/44.0f;
float_xb = float(x+1)/44.0f;
float_yb = float(y+1)/44.0f;
위의 네 변수는 텍스쳐의 좌표입니다. 각각의 다각형 (여기서는 격자 내의 사각형) 에 1/44 x 1/44 크기의 텍스쳐를 대입합니다. loops 변수는 왼쪽 아래 꼭지점이고, 나머지 세 개의 꼭지점을 귛가ㅣ 위해서 x+1, y+1 처럼 하나씩 값을 더합니다.
glTexCoord2f( float_x, float_y); // 왼쪽 아래 꼭지점
glVertex3f( points[x][y][0], points[x][y][1], points[x][y][2] );
glTexCoord2f( float_x, float_yb ); // 왼쪽 위 꼭지점
glVertex3f( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2] );
glTexCoord2f( float_xb, float_yb ); // 오른쪽 위 꼭지점
glVertex3f( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2] );
glTexCoord2f( float_xb, float_y ); // 오른쪽 아래 꼭지점
glVertex3f( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2] );
}
}
glEnd(); // 사각형 그리기 끝
위의 코드들이 지금까지 설명한 것을 OpenGL 에게 보내는 루틴입니다. glTexCoord2f() 함수와 glVertex3f() 함수를 각각 네 번씩 호출하는 것을 반복합니다. 사각형이 시계방향으로 그려지고 있다는 것은 앞면이 뒤로 향하게 된다는 것을 뜻합니다. 뒷면은 채워져 있고 앞면은 선이 그려져 있습니다.
만약 반시계방향으로 그리게 되면 우리는 앞면을 보게 되고, 우리는 격자가 쳐 있는 텍스쳐를 보게 될 것입니다.
if( wiggle_count == 2 ) // 매번 두 번째 프레임마다 그림으로서 속도를 줄인다
{
두 번째 씬을 그린 이후 sin 값을 새로 바꾸어 움직임을 줍니다.
for( y = 0; y < 45; y++ ) // y 축을 모두 참조
{
hold=points[0][y][2]; // 현재 값을 바로 왼쪽으로 옮긴다
for( x = 0; x < 44; x++) // x 축을 모두 참조
{
// 현재 값을 바로 오른쪽 값과 같게 한다
points[x][y][2] = points[x+1][y][2];
}
points[44][y][2]=hold; // 마지막 값은 맨 왼쪽 값을 대입
}
wiggle_count = 0; // 다시 0으로 되돌려 놓고
}
wiggle_count++; // 카운터 증가
각 줄의 첫 번째 값을 저장한 다음 값을 왼쪽으로 옮겨서 이미지가 물결을 치게 만듭니다. 처음에 저장한 값을 마지막에 대입함으로서 텍스쳐의 표면이 끊임없이 물결을 치도록 만듭니다. 그리고 wiggle_count 를 초기화하여 움직임이 계속 이루어지도록 합니다.
NeHe에서는 텍스쳐의 표면의 물결에 있던 흠집을 고쳐서 부드럽게 만들었습니다. (2000년 2월)
xrot+=0.3f;
yrot+=0.2f;
zrot+=0.4f;
return TRUE;
}
최신글이 없습니다.
최신글이 없습니다.
댓글목록 0