D3DXCreateMeshFVF »ç¿ë


1) ¹öÅؽº ±¸Á¶Ã¼ ¹× ŸÀÔ ¼±¾ð 
struct Vertex
{
	Vertex(){}
	Vertex(float x, float y, float z, float nx, float ny, float nz, float u, float v)
	{
		 _x = x;   _y = y;   _z = z;
		 _nx = nx; _ny = ny; _nz = nz;
		 _u = u;   _v = v;
	}

	float _x, _y, _z, _nx, _ny, _nz, _u, _v;

	static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

±¸Á¶Ã¼µµ Ŭ·¡½ºÃ³·³ »ý¼ºÀÚ¸¦ °¡Áú ¼ö ÀÖ´Ù. ¶Ç, "Vertex"ÀÇ Å©±â¸¦ °Ë»çÇغ¸¸é, 24¹ÙÀÌÆ®°¡ ³ª¿Ã°ÍÀÌ´Ù.
28¹ÙÀÌÆ®°¡ ³ª¿Í¾ß ÇÏÁö¸¸, staticÀ¸·Î ¼±¾ðÇÑ º¯¼ö´Â ±¸Á¶Ã¼ÀÇ Å©±â¿¡ Æ÷ÇÔµÇÁö ¾Ê´Â´Ù.

À½, Àú·¸°Ô ÇÏ¸é º¸±â°¡ ÁÁ°Ú²Û....

2)¸Þ½Ã ¹öÆÛÀÇ ÃʱâÈ­

¸Þ½Ã¸¦ ¸¸µé¾î¼­ »ç¿ë ¹æ¹ýÀº ´ÙÀ½°ú °°´Ù.

-ºó ¸Þ½Ã ¸¸µé±â
-¸Þ½Ã¸¦ ¹öÅؽº¸¦ ä¿î´Ù.
-¸Þ½ÃÀÇ ¼­ºê¼ÂÀ» ÁöÁ¤ÇÑ´Ù.
-¸Þ½ÃÀÇ ÀÎÁ¢ Á¤º¸¸¦ ¸¸µç´Ù.
-¸Þ½Ã¸¦ ÃÖÀûÈ­ ÇÑ´Ù
-¸Þ½Ã¸¦ ·»µå¸µ ÇÑ´Ù.
 

bool RenderInit()
{
	HRESULT hr = 0;

	hr = D3DXCreateMeshFVF(
		12,
		24,
		D3DXMESH_MANAGED,
		Vertex::FVF,
		g_d3d_Device,
		&g_pMesh);

	if(FAILED(hr))
		return false;

	Vertex* v = 0;
	g_pMesh->LockVertexBuffer(0, (void**)&v);

	// fill in the front face vertex data
	v[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[1] = Vertex(-1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[2] = Vertex( 1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);
	v[3] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);

	// fill in the back face vertex data
	v[4] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
	v[5] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f);
	v[6] = Vertex( 1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
	v[7] = Vertex(-1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f);

	// fill in the top face vertex data
	v[8]  = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
	v[9]  = Vertex(-1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
	v[10] = Vertex( 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);
	v[11] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);

	// fill in the bottom face vertex data
	v[12] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f);
	v[13] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f);
	v[14] = Vertex( 1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f);
	v[15] = Vertex(-1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);

	// fill in the left face vertex data
	v[16] = Vertex(-1.0f, -1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
	v[17] = Vertex(-1.0f,  1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
	v[18] = Vertex(-1.0f,  1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
	v[19] = Vertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f);

	// fill in the right face vertex data
	v[20] = Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
	v[21] = Vertex( 1.0f,  1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
	v[22] = Vertex( 1.0f,  1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
	v[23] = Vertex( 1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f);

	g_pMesh->UnlockVertexBuffer();

	//
	// Define the triangles of the box
	//
	WORD* i = 0;
	g_pMesh->LockIndexBuffer(0, (void**)&i);

	// fill in the front face index data
	i[0] = 0; i[1] = 1; i[2] = 2;     
	i[3] = 0; i[4] = 2; i[5] = 3;

	// fill in the back face index data
	i[6] = 4; i[7]  = 5; i[8]  = 6;
	i[9] = 4; i[10] = 6; i[11] = 7;

	// fill in the top face index data
	i[12] = 8; i[13] =  9; i[14] = 10;
	i[15] = 8; i[16] = 10; i[17] = 11;

	// fill in the bottom face index data
	i[18] = 12; i[19] = 13; i[20] = 14;
	i[21] = 12; i[22] = 14; i[23] = 15;

	// fill in the left face index data
	i[24] = 16; i[25] = 17; i[26] = 18;
	i[27] = 16; i[28] = 18; i[29] = 19;

	// fill in the right face index data
	i[30] = 20; i[31] = 21; i[32] = 22;
	i[33] = 20; i[34] = 22; i[35] = 23;

	g_pMesh->UnlockIndexBuffer();


	DWORD* attributeBuffer = 0;
	g_pMesh->LockAttributeBuffer(0, &attributeBuffer);

	for(int a = 0; a < 4; a++)
		attributeBuffer[a] = 0;

	for(int b = 4; b < 8; b++)
		attributeBuffer[b] = 1;

	for(int c = 8; c < 12; c++)
		attributeBuffer[c] = 2;

	g_pMesh->UnlockAttributeBuffer();

	// Optimize the mesh to generate an attribute table.
	std::vector<DWORD> adjacencyBuffer(g_pMesh->GetNumFaces() * 3);
	g_pMesh->GenerateAdjacency(0.0f, &adjacencyBuffer[0]);

	hr = g_pMesh->OptimizeInplace(		
		D3DXMESHOPT_ATTRSORT |
		D3DXMESHOPT_COMPACT  |
		D3DXMESHOPT_VERTEXCACHE,
		&adjacencyBuffer[0],
		0, 0, 0);

	D3DXCreateTextureFromFile(g_d3d_Device, "brick0.jpg", &g_pTextures[0]);
	D3DXCreateTextureFromFile(g_d3d_Device, "brick1.jpg", &g_pTextures[1]);
	D3DXCreateTextureFromFile(g_d3d_Device, "checker.jpg", &g_pTextures[2]);

	g_d3d_Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	g_d3d_Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	g_d3d_Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
	g_d3d_Device->SetRenderState(D3DRS_LIGHTING, false);

#ifdef _DEBUG
	//½ÇÇà°ú´Â ¹«°üÇÏ´Ù.
	//subSetÀÇ °¹¼ö¸¦ ÆľÇÇϱâ À§Çؼ­ ÇÊ¿äÇÏ´Ù. 
	DWORD numSubsets = 0;
	g_pMesh->GetAttributeTable(0,  &numSubsets);
#endif
	return true;
}

-ºó ¸Þ½Ã ¸¸µé±â
¹öÅؚà ¼öÀÌ´Ù. ¾ÕÀÇ µÎÀÎÀÚ´Â Ç×»ó 0º¸´Ù Ä¿¾ß ÇÑ´Ù.

-¸Þ½Ã¸¦ ¹öÅؽº¸¦ ä¿î´Ù.
g_pMesh->LockVertexBuffer()¿Í g_pMesh->UnlockVertexBuffer() »çÀÌ¿¡ ¹öÅؽº¸¦ ä¿î´Ù.

-¸Þ½ÃÀÇ ¼­ºê¼ÂÀ» ÁöÁ¤ÇÑ´Ù.
g_pMesh->LockAttributeBuffer()¿Í g_pMesh->UnlockAttributeBuffer() »çÀÌ¿¡ ¼­ºê¼ÂÀ» ÁöÁ¤ÇÑ´Ù.
¿©±â¼­´Â 0, 1, 2 ÃÑ 3°³ÀÇ ¼­ºê¼ÂÀ» »ç¿ëÇÏ¿´´Ù 0, 1¸¸ ÁöÁ¤ÇÏ¸é ¼­ºê¼ÂÀº 2°³°¡ µÈ´Ù.

-¸Þ½ÃÀÇ ÀÎÁ¢ Á¤º¸¸¦ ¸¸µç´Ù.
OptimizeInplace()Çϱâ À§ÇØ ÀÎÁ¢ Á¤º¸¸¦ ¸¸µç´Ù.

std::vector<DWORD> adjacencyBuffer(g_pMesh->GetNumFaces() * 3);
g_pMesh->GenerateAdjacency(0.0f, &adjacencyBuffer[0]);

-¸Þ½Ã¸¦ ÃÖÀûÈ­ ÇÑ´Ù
g_pMesh->OptimizeInplace()

-¸Þ½Ã¸¦ ·»µå¸µ ÇÑ´Ù.
 

3)·»µå¸µ 

HRESULT Render3D (float timeDelta)
{
	HRESULT hr;
	D3DXMATRIX xRot;
	D3DXMatrixRotationX(&xRot, D3DX_PI * 0.2f);

	static float y = 0.0f;
	D3DXMATRIX yRot;
	D3DXMatrixRotationY(&yRot, y);
	y += timeDelta;

	if( y >= 6.28f )
		y = 0.0f;

	D3DXMATRIX world = xRot * yRot;
	g_d3d_Device->SetTransform(D3DTS_WORLD, &world);

    g_d3d_Device->Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB (0, 0, 0), 1.0f, 0);
    g_d3d_Device->BeginScene ();

	for(int i = 0; i < g_nNumSubsets; i++)
	{
		g_d3d_Device->SetTexture( 0, g_pTextures[i] );
		g_pMesh->DrawSubset( i );
	}

    g_d3d_Device->EndScene ();
    hr = g_d3d_Device->Present (NULL, NULL, NULL, NULL);
	return hr;
}

¸ÞÆ®¸®¾ó ¾øÀÌ ÅؽºÃĸ¸ »ç¿ëÇÏ°í ÀÖ´Ù.
¼­ºê ¼ÂÀÌ 3°³À̹ǷΠSetTexture(), DrawSubset()¼¼ ¹øÀ» ¹Ýº¹ÇÑ´Ù.

4)¼Ò¸ê 

void DestroyDirect3D8()
{
	_RELEASE_<ID3DXMesh*>(g_pMesh);
	_RELEASE_<IDirect3DTexture9*>(g_pTextures[0]);
	_RELEASE_<IDirect3DTexture9*>(g_pTextures[1]);
	_RELEASE_<IDirect3DTexture9*>(g_pTextures[2]);

	_RELEASE_<LPDIRECT3DDEVICE9>(g_d3d_Device);
	_RELEASE_<LPDIRECT3D9>(g_d3d);
}

g_pMesh¿Í g_pTextures[0], g_pTextures[1], g_pTextures[2]¸¦ ÇØÁ¦ ÇÑ´Ù.

 

etc)

DumpMesh()¿¡¼­ Mesh ±¸Á¶, °ªµîÀ» ¾Ë±â À§Çؼ­ Mesh Dump.txt ÆÄÀÏ·Î ´ýÇÁÅ°°í ÀÕ´Ù.

[Æß]
DirectX 9¸¦ ÀÌ¿ëÇÑ 3D GAME ÇÁ·Î±×·¡¹Ö ÀÔ¹® - Á¤º¸ ¹®È­»ç