2008. 2. 12. 04:21
프로그래밍/DirectX
1. Building a Quad
Quad라 함은 4각형을 말하는데 아래의 3개는 모두 4각형이다.
Image 7.1 - Various Quads
4. The Finished Program
완성된 코드를 보자... 간단하다.
Quad라 함은 4각형을 말하는데 아래의 3개는 모두 4각형이다.
Image 7.1 - Various Quads
앞서서 말했다 시피 사실 모든 물체는 삼각형으로 구성이 되는데 바로 다음 그림처럼 구성이 된다.
Image 7.2 - Quads Are Dual Triangles
자 그렇다면 주된 질문인 어떻게 그것을 만들어 내느냐에 대한 대답은... 살펴보자꾸나. 이전 프로그램에서 만든 삼각형 대신 이번에는 4각형을 만들어 볼것이다.
바뀐 부분을 보면 다만 점이 4개라는 것뿐, 그리고 VertexBuffer 사이즈가 하나 더 늘었다는 것 외에는 없다. 이제 바꿔줘야 할 중요한 부분이 있는데 바로 2개의 삼각형을 이용해서 사각형을 구성하라는 명령인 다음 명령이다.
보시다시피 바뀐 부분은 아래쪽 명령인데 첫 인자가 D3DPT_TRIANGLESTRIP으로 바뀌어 있다. 이것은 이전에 들어가 있던 인자인 D3DPT_TRIANGLELIST에서 바뀐 것으로 삼각형의 strip으로 구성하겠다는 의미이며 마지막 숫자인 2가 몇개의 strip이 들어가는지를 말해준다.
다음 그림이 간단한 설명을 해주는데 매우 간략하고 보기도 좋다.
Image 7.3 - Making Triangles
2. Combining Quads To Make a Cube
이제 요 사각형들을 조합해서 Cube를 만들어보자.
생각보다 복잡시럽다. 이것은 OpenGL에서도 마찬가지다. 상당히 번거롭다. 이제 이걸 그려줘야 하는데 하나의 명령을 쓱싹 그려질줄 알았는데 아니다. 왜냐면 중복되는 점들이 있기 때문이라는데... 그래서 각 면을 2개의 삼각형으로 그려내라는 명령을 따로 따로 각각의 면에 대해서 (총 6개 면) 삼각형을 두개씩 그리라는 명령을 다음과 같이 주면 효율적이다.
이 코드를 삽입해서 실행해 보면 다음과 같은 결과를 얻을수 있다.
Image 7.4 - A Rotating Cube
3. More Shapes
A Square Pyramid
Image 7.5 - A Square Pyramid
The Hypercraft
Image 7.6 - The Hypercraft
Image 7.2 - Quads Are Dual Triangles
자 그렇다면 주된 질문인 어떻게 그것을 만들어 내느냐에 대한 대답은... 살펴보자꾸나. 이전 프로그램에서 만든 삼각형 대신 이번에는 4각형을 만들어 볼것이다.
// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
// create the vertices using the CUSTOMVERTEX struct
CUSTOMVERTEX t_vert[] =
{
{ -3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(4*sizeof(CUSTOMVERTEX), // change to 4, instead of 3
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock t_buffer and load the vertices into it
t_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, t_vert, sizeof(t_vert));
t_buffer->Unlock();
return;
}
void init_graphics(void)
{
// create the vertices using the CUSTOMVERTEX struct
CUSTOMVERTEX t_vert[] =
{
{ -3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(4*sizeof(CUSTOMVERTEX), // change to 4, instead of 3
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock t_buffer and load the vertices into it
t_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, t_vert, sizeof(t_vert));
t_buffer->Unlock();
return;
}
바뀐 부분을 보면 다만 점이 4개라는 것뿐, 그리고 VertexBuffer 사이즈가 하나 더 늘었다는 것 외에는 없다. 이제 바꿔줘야 할 중요한 부분이 있는데 바로 2개의 삼각형을 이용해서 사각형을 구성하라는 명령인 다음 명령이다.
d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
보시다시피 바뀐 부분은 아래쪽 명령인데 첫 인자가 D3DPT_TRIANGLESTRIP으로 바뀌어 있다. 이것은 이전에 들어가 있던 인자인 D3DPT_TRIANGLELIST에서 바뀐 것으로 삼각형의 strip으로 구성하겠다는 의미이며 마지막 숫자인 2가 몇개의 strip이 들어가는지를 말해준다.
다음 그림이 간단한 설명을 해주는데 매우 간략하고 보기도 좋다.
Image 7.3 - Making Triangles
2. Combining Quads To Make a Cube
이제 요 사각형들을 조합해서 Cube를 만들어보자.
// create the vertices using the CUSTOMVERTEX struct
CUSTOMVERTEX t_vert[] =
{
// side 1
{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 2
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 3
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 4
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 5
{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 6
{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
CUSTOMVERTEX t_vert[] =
{
// side 1
{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 2
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 3
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 4
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 5
{ 3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// side 6
{ -3.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, -3.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 3.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.0f, -3.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 255), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
생각보다 복잡시럽다. 이것은 OpenGL에서도 마찬가지다. 상당히 번거롭다. 이제 이걸 그려줘야 하는데 하나의 명령을 쓱싹 그려질줄 알았는데 아니다. 왜냐면 중복되는 점들이 있기 때문이라는데... 그래서 각 면을 2개의 삼각형으로 그려내라는 명령을 따로 따로 각각의 면에 대해서 (총 6개 면) 삼각형을 두개씩 그리라는 명령을 다음과 같이 주면 효율적이다.
d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2);
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2);
이 코드를 삽입해서 실행해 보면 다음과 같은 결과를 얻을수 있다.
Image 7.4 - A Rotating Cube
3. More Shapes
A Square Pyramid
Image 7.5 - A Square Pyramid
// create the vertices using the CUSTOMVERTEX
struct CUSTOMVERTEX t_vert[] =
{
// base
{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// triangle 1
{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
// triangle 2
{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
// triangle 3
{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
// triangle 4
{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(16*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
struct CUSTOMVERTEX t_vert[] =
{
// base
{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 255, 255), },
// triangle 1
{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
// triangle 2
{ 3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
// triangle 3
{ 3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
// triangle 4
{ -3.0f, 0.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.0f, 0.0f, 3.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 0.0f, 7.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(16*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // base
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 1); // triangle 1
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 7, 1); // triangle 2
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 10, 1); // triangle 3
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 13, 1); // triangle 4
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // base
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 1); // triangle 1
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 7, 1); // triangle 2
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 10, 1); // triangle 3
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 13, 1); // triangle 4
The Hypercraft
Image 7.6 - The Hypercraft
// create the vertices using the CUSTOMVERTEX
struct CUSTOMVERTEX t_vert[] =
{
// fuselage
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
// left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// bottom of fuselage
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
// opposite side of left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
// opposite side of right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(20*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
struct CUSTOMVERTEX t_vert[] =
{
// fuselage
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
// left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// bottom of fuselage
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
// opposite side of left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
// opposite side of right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(20*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 1); // left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 7, 1); // right gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 10, 2); // bottom of fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 1); // other side of left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 17, 1); // other side of right gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 1); // left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 7, 1); // right gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 10, 2); // bottom of fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 1); // other side of left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 17, 1); // other side of right gun
4. The Finished Program
완성된 코드를 보자... 간단하다.
// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
// define the screen resolution and keyboard macros
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// include the Direct3D Library files
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL; // the pointer to the vertex buffer
// function prototypes
void initD3D(HWND hWnd); // sets up and initializes Direct3D
void render_frame(void); // renders a single frame
void cleanD3D(void); // closes Direct3D and releases memory
void init_graphics(void); // 3D declarations
struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL, L"WindowClass", L"Our Direct3D Program",
WS_EX_TOPMOST | WS_POPUP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
NULL, NULL, hInstance, NULL);
// set up and initialize Direct3D
initD3D(hWnd);
// enter the main loop:
MSG msg;
while(TRUE)
{
DWORD starting_point = GetTickCount();
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
render_frame();
// check the 'escape' key
if(KEY_DOWN(VK_ESCAPE))
PostMessage(hWnd, WM_DESTROY, 0, 0);
while ((GetTickCount() - starting_point) < 25);
}
// clean up DirectX and COM
cleanD3D();
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// create a device class using this information and the info from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
init_graphics(); // call the function to initialize the Hypercraft
d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE); // turn off the 3D lighting
d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
return;
}
// this is the function used to render a single frame
void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);
// set the view transform
D3DXMATRIX matView; // the view transform matrix
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (0.0f, 8.0f, 25.0f), // the camera position
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView
// set the projection transform
D3DXMATRIX matProjection; // the projection transform matrix
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45), // the horizontal field of view
(FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
1.0f, // the near view-plane
100.0f); // the far view-plane
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection
// set the world transform
static float index = 0.0f; index+=0.03f; // an ever-increasing float value
D3DXMATRIX matRotateY; // a matrix to store the rotation for each triangle
D3DXMatrixRotationY(&matRotateY, index); // the rotation matrix
d3ddev->SetTransform(D3DTS_WORLD, &(matRotateY)); // set the world transform
// select the vertex buffer to display
d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX));
// draw the Hypercraft
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 1); // left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 7, 1); // right gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 10, 2); // bottom of fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 1); // other side of left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 17, 1); // other side of right gun
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
return;
}
// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
t_buffer->Release(); // close and release the vertex buffer
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
return;
}
// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
// create the vertices using the CUSTOMVERTEX
struct CUSTOMVERTEX t_vert[] =
{
// fuselage
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
// left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// bottom of fuselage
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
// opposite side of left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
// opposite side of right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(20*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock t_buffer and load the vertices into it
t_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, t_vert, sizeof(t_vert));
t_buffer->Unlock();
return;
}
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
// define the screen resolution and keyboard macros
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// include the Direct3D Library files
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL; // the pointer to the vertex buffer
// function prototypes
void initD3D(HWND hWnd); // sets up and initializes Direct3D
void render_frame(void); // renders a single frame
void cleanD3D(void); // closes Direct3D and releases memory
void init_graphics(void); // 3D declarations
struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR;};
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL, L"WindowClass", L"Our Direct3D Program",
WS_EX_TOPMOST | WS_POPUP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
NULL, NULL, hInstance, NULL);
// set up and initialize Direct3D
initD3D(hWnd);
// enter the main loop:
MSG msg;
while(TRUE)
{
DWORD starting_point = GetTickCount();
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
render_frame();
// check the 'escape' key
if(KEY_DOWN(VK_ESCAPE))
PostMessage(hWnd, WM_DESTROY, 0, 0);
while ((GetTickCount() - starting_point) < 25);
}
// clean up DirectX and COM
cleanD3D();
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// create a device class using this information and the info from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
init_graphics(); // call the function to initialize the Hypercraft
d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE); // turn off the 3D lighting
d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
return;
}
// this is the function used to render a single frame
void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);
// set the view transform
D3DXMATRIX matView; // the view transform matrix
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (0.0f, 8.0f, 25.0f), // the camera position
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // the look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView
// set the projection transform
D3DXMATRIX matProjection; // the projection transform matrix
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45), // the horizontal field of view
(FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
1.0f, // the near view-plane
100.0f); // the far view-plane
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection
// set the world transform
static float index = 0.0f; index+=0.03f; // an ever-increasing float value
D3DXMATRIX matRotateY; // a matrix to store the rotation for each triangle
D3DXMatrixRotationY(&matRotateY, index); // the rotation matrix
d3ddev->SetTransform(D3DTS_WORLD, &(matRotateY)); // set the world transform
// select the vertex buffer to display
d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX));
// draw the Hypercraft
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 1); // left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 7, 1); // right gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 10, 2); // bottom of fuselage
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 1); // other side of left gun
d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 17, 1); // other side of right gun
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
return;
}
// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
t_buffer->Release(); // close and release the vertex buffer
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
return;
}
// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
// create the vertices using the CUSTOMVERTEX
struct CUSTOMVERTEX t_vert[] =
{
// fuselage
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
// left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
// bottom of fuselage
{ 0.0f, 3.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 0), },
{ -3.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 255, 255), },
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
// opposite side of left gun
{ 3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ 2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ 3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
// opposite side of right gun
{ -3.2f, -1.0f, -3.0f, D3DCOLOR_XRGB(0, 0, 255), },
{ -2.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0), },
{ -3.2f, -1.0f, 11.0f, D3DCOLOR_XRGB(0, 255, 0), },
};
// create a vertex buffer interface called t_buffer
d3ddev->CreateVertexBuffer(20*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&t_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock t_buffer and load the vertices into it
t_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, t_vert, sizeof(t_vert));
t_buffer->Unlock();
return;
}
'프로그래밍 > DirectX' 카테고리의 다른 글
[DX Tutorial] Lesson 9: Rendering WIth Vertex Lighting (0) | 2008.02.14 |
---|---|
[DX Tutorial] Lesson 8: Adding Textures (0) | 2008.02.14 |
[DX Tutorial] Lesson 6: Rendering Depth (0) | 2008.02.12 |
[DX Tutorial] Lesson 5: Transforming Vertices (0) | 2008.02.07 |
[DX Tutorial] Lesson 4: Drawing a Triangle (0) | 2008.02.06 |