850 likes | 1.37k Views
DirectX9 를 이용한 3D GAME 프로그래밍 입문. Frank D. Luna 저 최현호 역 , 김성완 감수 정보문화사 , 2004 강의노트 : vmlab.suwon.ac.kr/mwlee. DirectX 설치. DirectX 환경설정 설치 : DirectX 2004 년 버전 압축해제는 C:DXSDK 로 , INCLUDE 및 LIB 파일 추가 도구 => 옵션 =>Directories 에서 INCLUDE/LIB 를 다음으로 설정 C:DXSDKINCLUDE
E N D
DirectX9를 이용한 3D GAME 프로그래밍 입문 Frank D. Luna 저 최현호 역, 김성완 감수 정보문화사, 2004 강의노트: vmlab.suwon.ac.kr/mwlee
DirectX 설치 • DirectX 환경설정 • 설치: DirectX 2004 년 버전 • 압축해제는 C:\DXSDK 로, • INCLUDE 및 LIB 파일 추가 • 도구=>옵션=>Directories 에서 INCLUDE/LIB 를 다음으로 설정 • C:\DXSDK\INCLUDE • C:\DXSDK\LIB 컴퓨터게임(DirectX)
예제 프로그램 사이트 • http://www.wordware.com/files/dx9/ 컴퓨터게임(DirectX)
DirectX 컴파일시 (Visual C++ 6.0) • 여러 파일 추가시 • project => Add-to-project => Files 에서 해당 파일들 추가 • 빌드시 링크해야 하는 것 • project => Setting => Link 에서 • d3d9.lib d3dx9.lib winmm.lib 추가 • console => windows로 변경 컴퓨터게임(DirectX)
오류 처리 (1) • LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main 오류 처리 • Project => Setting => Link 에서 • console => windows 로 바꿈 • d3dx9.lib(fastftoa.obj) : error LNK2001: unresolved external symbol __aulldvrm • Debug/camera.exe : fatal error LNK1120: 1 unresolved externals • Error executing link.exe. 오류 처리 • Project => Setting => Link 에서 • d3d9.lib d3dx9d.lib winmm.lib 추가 (d3dx9 => d3dx9d 로 변경 링크) 컴퓨터게임(DirectX)
오류처리 (2) • Linking...d3dx9.lib(jidctflt.obj) : error LNK2001: unresolved external symbol __ftol2d3dx9.lib(cshaderprogram.obj) : error LNK2001: unresolved external symbol __ftol2d3dx9.lib(jcdctmgr.obj) : error LNK2001: unresolved external symbol __ftol2d3dx9.lib(cbaseprogram.obj) : error LNK2001: unresolved external symbol __ftol2d3dx9.lib(cprogram.obj) : error LNK2001: unresolved external symbol __ftol2… 등 오류 발생 시 • Project=>Setting => Link => Object/Library Module 에서 • d3d9.lib d3dx9d.lib winmm.lib 으로 해야 함 컴퓨터게임(DirectX)
PART 1 One 수 학 적 준 비
수 학 적 준 비 • 목 표 • 기하학과 벡터의 대수학, 그래픽에 응용되는 방법 • 행렬과 행렬의 대수학, 3D 기하정보의 변환에 행렬 이용 방법 • 평면과 광선을 대수적으로 모델링 하는 방법, 3D 그래픽에 응용하는 방법 • 3D 수학 연산에 사용되는 D3DX 라이브러리의 클래스와 함수 컴퓨터게임(DirectX)
3- 공간의 벡터 • 벡터 : 방향을 가진 선분 • 길이, 방향의 두 가지 속성을 가짐 • 위치는 벡터의 속성이 아님 • 벡터 u 와 벡터 v 는 동일하다. 머리 벡터 u 벡터 v 꼬리 컴퓨터게임(DirectX)
왼손 좌표 시스템과 오른쪽 좌표 시스템 • Z 축 방향의 차이로 인한 구별 • 왼손 시스템 • 양의 Z 좌표가 내가 보는 방향임 • 오른손 시스템 • 양의 Z 좌표가 나를 향함 Y Y z x X z 왼손 좌표계 오른손 좌표계 컴퓨터게임(DirectX)
벡터의 꼬리가 원점과 일치하면 벡터가 표준점에 위치한 것이라 함 • 벡터가 표준점 내에 위치하면 머리점의 좌표를 확인하는 방법으로 벡터를 기술할 수 있게 됨 • 이 좌표들을 벡터의 성분이라 한다. • 2, 3, 4차원 벡터의 표시 예 • U = (Ux, Uy), N = (Nx, Ny, Nz), C = (Cx, Cy, Cz, Cw) 컴퓨터게임(DirectX)
표준점에 고정된 벡터들은 특정 좌표 시스템과의 관계로 기술할 수 있다. • 포인트와 벡터를 혼동하는 일이 발생하면 안됨 • 포인트는 시스템 내의 한 위치 나타냄 • 벡터는 크기와 방향을 가짐 Y c a X u = v b 컴퓨터게임(DirectX)
특별한 3D 벡터 • 0 벡터. 모든 성분이 0, 0 벡터는 0 으로 표시 • Ex) 0 = (0, 0, 0) • 3좌표의 표준 기저 벡터 • i, j, k 벡터 • 모두 1의 크기를 가짐 • i = (1, 0, 0), j = (0, 1, 0), k = (0, 0, 1) • 크기를 1로 가지는 벡터를 단위벡터라 함. k j i 컴퓨터게임(DirectX)
D3DXVECTOR3 클래스 이용 typedef struct D3DXVECTOR3 : public D3DVECTOR { public : D3DXVECTOR3(){}; D3DXVECTOR3(CONST FLOAT *); D3DXVECTOR3(CONST D3DVECTOR &); D3DXVECTOR3(FLOAT x, FLOAT y, FLOAT z); //형 변환 operator FLOAT*(); operator CONST FLOAT * () const; 컴퓨터게임(DirectX)
// 할당 연산자 D3DXVECTOR3& operator += (CONST D3DXVECTOR3&); D3DXVECTOR3& operator -= (CONST D3DXVECTOR3&); D3DXVECTOR3& operator *= (FLOAT); D3DXVECTOR3& operator /= (FLOAT); // 단항 연산자 D3DXVECTOR3 operator + () const; D3DXVECTOR3 operator - () const; // 이항 연산자 D3DXVEcTOR3 operator + (CONST D3DXVECTOR3 &) const; D3DXVEcTOR3 operator - (CONST D3DXVECTOR3 &) const; 컴퓨터게임(DirectX)
D3DXVECTOR3 operator * (FLOAT) const; D3DXVECTOR3 operator / (FLOAT) const; friend D3DXVECTOR3 operator * (FLOAT, CONST struct D3DXVECTOR3 &); BOOL operator == (CONST D3DVECTOR3 &) const; BOOL operator != (CONST D3DXVECTOR &) const; } D3DXVECTOR3, *LPD3DXVECTOR3; 컴퓨터게임(DirectX)
D3DX 라이브러리에서는 3 공간 내의 벡터를 표현하기 위해 D3DXVECTOR3 클래스 이용 typedef struct _D3DVECTOR { float x; float y; float z; } D3DVECTOR; • D3DVECTOR3는 D3DVECTOR에서 성분 데이터 상속 • 2D와 4D 벡터 표현을 위한 D3DXVECTOR2, D3DXVECTOR4 클래스 제공 컴퓨터게임(DirectX)
벡터 상등 • 기하학적으로는 같은 방향, 같은 길이의 두 벡터는 동일한 것이나, • 대수적 으로는 벡터가 동일한 차원, 대응 성분이 같은 경우에 두 벡터를 동일한 것으로 봄 • ux = vx, uy = vy, uz = vz라면 • (ux, uy, uz) = (vx, vy, vz) • 동등 연산자(오버로딩된)를 이용해 같은지 확인 D3DXVECTOR u(1.0f, 0.0f, 1.0f); D3DXVECTOR v(0.0f, 1.0f, 0.0f); if(u == v) return true; 컴퓨터게임(DirectX)
부동 소수점 수를 비교할 때에는 주의 • 부동 소수점의 부정확성 때문에 같은 것으로 생각되는 것도 다를 수가 있다. • 따라서 두 수가 대략적으로 같은지를 확인해야 함 • 매우 작은 값인 EPSILON 상수를 버퍼로 사용하는데 두 수의 거리가 EPSILON보다 작을 경우 같은 것 • D3DXVECTOR3 클래스를 이용할 때에는 오버로드된 비교연산자가 다음 작업을 자동으로 수행 컴퓨터게임(DirectX)
const float EPSILON = 0.001f; bool Equals(float lhs, float rhs) { // 만약 lhs == rhs 라면 두 수의 차이는 0이어야 한다 return fabs(lhs - rhs) < EPSILON ? true : false; } 컴퓨터게임(DirectX)
백터의 크기 계산 • 벡터의 크기는 방향을 가진 선분의 길이 • 벡터의 성분이 주어졌을 때, 다음 식을 이용해 벡터의 크기를 계산할 수 있다. • |u| = ux + uy + uz • D3DX 라이브러리를 이용할 때는 다음을 이용 FLOAT D3DXVec3Lenth(CONST D3DXVECTOR3* pv); D3DXVECTOR3 v(1.0f, 2.0f, 3.0f); float magnitude = D3DXVec3Length(&v); 2 2 2 컴퓨터게임(DirectX)
벡터의 정규화 • 벡터의 크기를 1로 만들어 단위 벡터가 되도록 함 • 벡터의 각 성분을 벡터의 크기로 나눔 u = = • D3DX 라이브러리를 이용할 때는 다음 함수를 통해 벡터를 정규화 할 수 있다. D3DXVECTOR3 * D3DXVec3Normalize( D3DXVECTOR3* pOut, CONSTD3DXVECTOR3* pV ); ux uy uz u |u| ^ |u| |u| |u| 컴퓨터게임(DirectX)
벡터 더하기 • 성분을 더하면 두개의 벡터를 더할 수 있다. • u + v = (ux + vx, uy + vy, uz + vz); • 코드 내에서 벡터를 더하기 위해서는 오버로드 된 덧셈 연산자 이용 u + v u v 컴퓨터게임(DirectX)
D3DXVECTOR3 u(2.0f, 0.0f, 1.0f); D3DXVECTOR3 v(0.0f, -1.0f, 5.0f); D3DXVECTOR3 sum = u + v; // u, v (벡터 변수) // = (2.0f, -1.0f, 6.0f) 컴퓨터게임(DirectX)
벡터 빼기 • 더하기와 비슷하게 벡터의 대응되는 성분을 빼는 방법으로 벡터 빼기를 수행할 수 있다. • 반드시 동일한 차원을 가져야 한다. • u – v = u + (-v) = (ux - vx, uy - vy, uz - vz); u D3DXVECTOR3 u(2.0f, 0.0f, 1.0f); D3DXVECTOR3 v(0.0f, -1.0f, 5.0f)); D3DXVECTOR3 difference= u - v; u - v v -v 컴퓨터게임(DirectX)
스칼라 곱 • 벡터는 스칼라로 곱하는 것이 가능 • 이를 통해 벡터의 배율이 변경 됨 • 음수를 곱하는 경우 방향이 바뀜 • ku = (kux, kuy, kuz); D3DXVECTOR3 u(1.0f 1.0f, -1.0f); D3DXVECTOR3 scaleVec = u * 10.0f; 컴퓨터게임(DirectX)
내 적 • u • v = ux·vx + uy·vy + uz·vz = s • 코사인의 법칙을 이용하면 u • v = |u|*|v| 관계 발견 • u와 v과 모두 단위 벡터일 경우 u • v 두 벡터 간의 코사인이 된다. • 내적의 특성 • u • v = 0 라면 u v 이다. • u • v > 0 라면 두 벡터간의 각도 는 90보다 작다. • u • v < 0 라면 두 벡터간의 각도 는 90보다 크다. 컴퓨터게임(DirectX)
D3DX함수를 이용해 벡터간의 내적 구할 수 있다. FLOAT D3DXVec3Dot( CONST D3DXVECTOR 3* pV1; CONST D3DXVECTOR 3* pV2; ); D3DXVECTOR3 u(1.0f, -1.0f, 0.0f); D3DXVECTOR3 v(3.0f, 2.0f, 1.0f); float dot = D3DXVec3Dot(&u, &v); 컴퓨터게임(DirectX)
외 적 • u와 v 두 벡터의 외적을 수행하면 다른 벡터인 p를 얻으며, 서로 직각을 이룬다. • p = u x v = [(uy*vz-uz*vy), (uz*vx-ux*vz), (ux*vy-uy*vx)] u x v v u 컴퓨터게임(DirectX)
다음의 D3DX 함수를 이용하면 두 벡터간의 외적 계산 할 수 있다. D3DXVEDCTOR3 *D3DXVec3Cross( D3DXVECTOR3 * pOut, CONST D3DXVECTOR3* pV1, CONST D3DXVECTOR3* pV2); 컴퓨터게임(DirectX)
행 렬 • M x N 행렬을 m행과 n열을 가지는 일반적인 배열 • 3 x 3 행렬 M, 2 x 4 행렬 B를 본다. • M = B = • 한 개의 행이나 열만을 가지는 행렬도 가능 • 이를 행 벡터, 열 벡터라고 부름 • V = U = M11 m12 m13 M21 m22 m23 M31 m32 m33 B11 B12 B13 B14 B21 B22 B23 B24 V11 V12 V13 V14 v11 V12 V13 V14 컴퓨터게임(DirectX)
상등 스칼라 곱, 더하기 • 동일한 차원을 가지고 각각의 대응되는 항목이 같은 두 개의 행렬을 같은 것으로 취급 • A = C, A B, A D • 행렬의 각 항목을 스칼라로 곱하는 방법으로 행렬을 스칼라 곱할 수 있다. kD = • 2 -1 3 • -6 3 0 0 • 5 • -2 3 • 2 • 5 -8 • 5 • -2 3 D = A = B = C = K(1) k(2) k(-1) k(3) K(-6) k(3) k(0) k(0) 컴퓨터게임(DirectX)
5 • -2 3 • 2 • 5 -8 1+6 5+2 -2+5 3+(-8) + • 행렬이 동일한 차원을 가진 경우에는 두 행렬을 더할 수 있다. A + B = = • 더하기와 마찬가지로 빼기도 같은 방법으로 수행 컴퓨터게임(DirectX)
곱 • 행렬 곱은 3D 컴퓨터 그래픽에서 행렬을 이용하기 위한 가장 중요한 연산이다. • 행렬 곱은 벡터의 변환을 수행하거나 몇 가지의 변환을 조합하는데 이용된다. • 행렬 곱 AB를 얻기 위해서는 A의 열 수와 B이 행 수가 반드시 같아야 한다. • 2x3, 3x3 차원을 가지는 A와 B의 두 행렬 곱의 예 컴퓨터게임(DirectX)
B11 B12 B13 B21 B22 B23 B31 B32 B33 A11 A12 A13 A21 A22 A23 • A = B = • 곱셈 AB의 경우에는 A의 열 수와 B의 행 수가 일치 • 곱셈 정의 가능 • 하지만 BA곱은 불가능: B의 열 수와 A의 행 수가 일치 않음 • AB = = 4 1 -2 1 1 3 2 1 a1• b1 a1• b2 a2• b1 a2• b2 (4 1) • (1 2) (4 1) • (3 1) (-2 1) • (1 2) (-2 1) • (3 1) 컴퓨터게임(DirectX)
항 등 행 렬(identity matrix) • 중심 대각선을 제외한 모든 항목이 0인 정방 행렬 • 중심 대각선의 항목들은 모두 1 • 2x2, 3x3, 4x4 항등행렬의 예 • 항등 행렬은 곱셈의 항등성을 가짐 • MI = IM = M 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 1 1 0 0 1 컴퓨터게임(DirectX)
역 행 렬 • 행렬에는 나누기와 비교할 수 있는 연산 없으나 곱하기와 반대의 의미를 가지는 역 연산이 존재 • 정방 행렬만이 역행렬을 가질 수 있다. • n x n 행렬 M의 역행렬 n x n은 M-1으로 표기 • 모든 정방행렬이 역행렬을 가지지는 않는다. • 행렬과 역행렬을 곱하면 항등 행렬을 얻는다. • MM = M · M-1 = I • 곱의 역에 대한 유용한 특성 • (AB)-1 = B-1 A-1 , A와 B가 모두 역성이며 동일한 차원의 정방 행렬이라고 가정 -1 컴퓨터게임(DirectX)
행렬의 전치(transpose) • 행렬의 열과 행을 교환하면 행렬의 전치를 수행 • mxn 행렬의 전치는 nxm 행렬 • 행렬 M 의 전치는 MT로 표시 • A = B = • AT = BT = • -1 8 • 3 6 -4 a, b, c d, e, f g, h, i • 3 • -1 6 • 8 -4 a, d, g b, e, h c, f, i 컴퓨터게임(DirectX)
D3DX 행렬 • Direct3D 애플리케이션 프로그래밍 할 때는 4 x 4 행렬과 1 x 4 행 벡터만을 이용 • 벡터-행렬곱 v 가 1 x 4 행렬이면, 곱 vT가 정의, 결과는 1 x 4 행 벡터가 된다. • 행렬-행렬곱 T가 4 x 4 행렬이고 R이 4 x 4 행렬이라면, 곱 TR과 RT가 모두 정의, 두 가지 모두 4 x 4행렬이 된다. • 행렬곱은 상호 교환적이지 않으므로 TR 곱이 RT와 같을 필요는 없다. • D3DX 에서 벡터를 나타내기 위해 D3DXVECTOR3 와 D3DXVECTOR4 벡터 클래스 이용 컴퓨터게임(DirectX)
D3DXMATRIX 클래스 typedef struct D3DXMATRIX : public D3DMATRIX { public : D3DXMATRIX() {}; D3DXMATRIX(CONST FLOAT*); D3DXMATRIX(CONST D3DXMATRIX&); D3DXMATRIX(FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14, FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24, FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34, FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44); 컴퓨터게임(DirectX)
// 접근 허가 FLOAT & operator() (UINT Row, UINT Col); FLOAT & operator() (UINT Row, UINT Col) const; // 형 변환 연산자 operator FLOAT* (); operator CONST FLOAT* () const; // 할당 연산자 D3DXMATRIX& operator *= (CONST D3DXMATRIX&); D3DXMATRIX& operator += (CONST D3DXMATRIX&); D3DXMATRIX& operator -= (CONST D3DXMATRIX&); D3DXMATRIX& operator *= (FLOAT); 컴퓨터게임(DirectX)
D3DXMATRIX& operator /= (FLOAT); // 단항 연산자 D3DXMATRIX operator + () const; D3DXMATRIX operator - () const; // 이항 연산자 D3DXMATRIX operator * (CONST D3DXMATRIX&) const; D3DXMATRIX operator - (CONST D3DXMATRIX&) const; D3DXMATRIX operator + (CONST D3DXMATRIX&) const; D3DXMATRIX operator * (FLOAT) const; D3DXMATRIX operator / (FLOAT) const; 컴퓨터게임(DirectX)
friend D3DXMATIRX operator * (FLOAT, CONST D3DXMATRIX&); BOOL operator == (CONST D3DXMATRIX&); BOOL operator != (CONST D3DXMATRIX&); } D3DXMATRIX, *LPD3DXMATRIX; • D3DXMATRIX 클래스는 다음과 같이 정의된 D3DMATRIX 구조체에서 데이터 항목을 상속 컴퓨터게임(DirectX)
typedef struct _D3DMATRIX{ union{ struct{ float _11, _12, _13, _14; float _21, _22, _23, _24; float _31, _32, _33, _34; float _41, _42, _43, _44; }; float m[4][4]; }; } D3DMATRIX; 컴퓨터게임(DirectX)
D3DXMATRIX 클래스 • 행렬의 동일함 확인 • 더하기, 빼기, 스칼라로 행렬 곱하기, 형 변환 • 두 개의 D3DXMATRIX를 곱하는 등의 유용한 연산자들을 다수 포함 • D3DX 라이브러리는 이외에도 항등행렬 지정, 전치, 역행렬 찾는 유용한 함수 포함. 컴퓨터게임(DirectX)
D3DXMATRIX * D3DXMatrixIdentity(D3DXMATRIX *pout); D3DXMATRIX M; D3DXMatrixIdentity(&M); // 항등행렬 지정 D3DXMATRIX *D3DXMatrixtranspose(D3DXMATRIX *pout, CONST D3DXMATRIX *pM); D3DXMATRIX A(…); D3DXMATRIX B; D3DXMatrixTranspose(&B, &A); D3DXMATRIX *D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM); // pM의 역행렬 리턴, 다음 인자는 행렬식, 다음, 뒤집을 행렬 컴퓨터게임(DirectX)
D3DXMATRIX A(…); D3DXMATRIX B; D3DXMatrixinverse(&B, 0, &A); // B = inverse(A); 컴퓨터게임(DirectX)
기본적인 변환 • Direct3D 에서는 변환을 표현 위해 4x4 행렬 이용 • 행렬의 4번째 인자(w)의 성분 • 1 x 4 벡터에 포인트를 배치할 때에는 W = 1 • 반면에 벡터는 위치를 가지지 않으므로 벡터의 이동은 정의될 수 없음 • W = 0 으로 표기되어야 함. • 포인트 이동이 바르게 처리되기 위해서는 w = 1 • 벡터 이동을 막기 위해서는w = 0 을 지정해야 함 컴퓨터게임(DirectX)
이동 행렬 • (x,y,z,1) 벡터를 다음과 같은 행렬로 곱하면 x,y,z로 px, py, pz만큼 이동할 수 있다. • T(p) = 이 동 1 0 0 0 0 1 0 0 0 0 1 0 px py pz 1 컴퓨터게임(DirectX)
이동 행렬 D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX* pOut, FLOAT x, // x 축으로 이동할 단위의 수 FLOAT y, // y 축으로 이동할 단위의 수 FLOAT z // z 축으로 이동할 단위의 수 ); 컴퓨터게임(DirectX)