¢Â3D °ÔÀÓ Á¦ÀÛ Auxiliary¢Â
±³À°±â°ü¿¡¼ 3D ±âÃÊ °úÁ¤ ¼ö¾÷ÀÌ ³¡³ª°í 2~3ÁÖ Á¤µµ ½Ã°£À» µÎ¾î °ÔÀÓ Á¦ÀÛ ½Ç½ÀÀ» ÁøÇàÇÕ´Ï´Ù. 3D ±âÃÊ
°úÁ¤¸¸À¸·Îµµ °ÔÀÓ Á¦ÀÛÀÌ °¡´ÉÇÏÁö¸¸ ÀǿܷΠÀÛÀº ºÎºÐµé¿¡¼ ½Ã°£À» ¸¹ÀÌ »©¾Ñ±â°Å³ª ¶Ç´Â ÄÚµå ¸î ÁÙ ´õ ³ÖÀ¸¸é °ÔÀÓ ºÐÀ§±â°¡ È® ´Þ¶óÁö´Â ÀϵéÀÌ
Á¾Á¾ ÀÖ½À´Ï´Ù. ÀÌ ÀåÀº 3D ±âÃÊ °úÁ¤À» ¹è¿ì°í °ÔÀÓ Á¦ÀÛÀ»
½ÃÀÛÇÏ´Â ºÐµé¿¡°Ô Ưº°ÇÑ ÁÖÁ¦µéÀ» ¸ð¾Æ¼ µµ¿òÀÌ µÉ¸¸ÇÑ ³»¿ëÀ» ¸ð¾Ò½À´Ï´Ù. 3DÀÇ Àü¹ÝÀûÀÎ ³»¿ëÀÌ ¾Æ´Ñ
Áö¿ªÀûÀÎ ³»¿ëÀÌ ¸¹¾Æ ÀÌ ÀåÀº ³Ñ¾î°¡µµ »ó°ü¾ø½À´Ï´Ù.
3.1 Æ÷±×(Fog)
D3D´Â 3DÀÇ Çö½Ç°¨(Reality)¸¦ ³ôÀ̱â À§Çؼ Anti-aliasing, ¹üÇÁ ¸ÅÇÎ(Bump Mapping), ¹Ý»ç³ª ±¼Àý¿¡ ´ëÇÑ È¯°æ ¸ÅÇÎ(Environment
Mapping), ½ºÅÙ½Ç, ¹öÅØ½º ºí·»µù(Vertex
Blending), Æ÷±×(Fog) µîÀ» Áö¿øÇÕ´Ï´Ù. ÀÌ
Áß¿¡¼ Æ÷±×´Â ÄÄÇ»ÅÍ ±×·¡ÇȽº¿¡¼ Çö½ÇÀÇ ¾È°³ È¿°ú¸¦ Ç¥ÇöÇÑ °ÍÀÔ´Ï´Ù. Æ÷±×¸¦ Àû¿ëÇϸé 3D Àå¸éÀ» ±¸¼ºÇÏ´Â °¡»ó Ä«¸Þ¶ó¿¡¼ ¸Ö¸® ÀÖ´Â ¿ÀºêÁ§Æ®´Â Æ÷±×ÀÇ »ö»ó¿¡ °¡±õ°Ô ¸¸µé°í °¡±î¿ï¼ö·Ï ¹°Ã¼¸¦ ¼±¸íÇϰÔ
º¸ÀÌ°Ô ÇÕ´Ï´Ù. ¶ÇÇÑ Æ÷±×¸¦ »ç¿ëÇÏ¸é ¸Ö¸® ÀÖ´Â ¹°Ã¼´Â µð¹ÙÀ̽º°¡ 'Àû´çÈ÷' ±×¸®°Ô µÇ¾î ·»´õ¸µ ¼Óµµ°¡ Çâ»óµÇ¸ç º¼·ý üÀûÀÇ Far Æò¸é°úÀÇ
°Å¸® °ªº¸´Ù ÀÛÀ» ¶§ ¿ÀºêÁ§Æ®°¡ °©ÀÚ±â Æ¢¾î³ª¿À´Â Çö»óµµ ¸·À» ¼ö ÀÖ½À´Ï´Ù.
D3D´Â Àå¸é¿¡ Æ÷±×¸¦ Àû¿ëÇÏ´Â Á¤Á¡ Æ÷±×, Çȼ¿ Æ÷±× µÎ °¡Áö ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù. ÀÌµé Æ÷±×´Â ´ÙÀ½°ú °°Àº ¼±Çü
°è»ê °ø½ÄÀ¸·Î Æú¸®°ï¿¡ Àû¿ëµË´Ï´Ù.
ÃÖÁ¾ Æú¸®°ï »ö»ó C = f * Æú¸®°ï »ö»ó + (1 - f)* Æ÷±× »ö»ó
f´Â Æ÷±× °è¼ö(Fog
Factor)·Î °Å¸®ÀÇ Á¤µµ¿¡ µû¶ó °è»êÇϴµ¥ ´ÙÀ½°ú °°ÀÌ ¼±Çü Æ÷±×(Linear Fog)¿Í
Áö¼ö Æ÷±×(Exponential Fog)·Î ºÐ·ù µË´Ï´Ù.
|

|
(¼±ÇüÆ÷±×: D3DFOG_LINEAR)
(Áö¼ö Æ÷±×: D3DFOG_EXP)
(Áö¼ö Æ÷±×: D3DFOG_EXP)
|
<Æ÷±× °ø½Ä°ú ±×·¡ÇÁ>
°ø½ÄÀÇ d´Â Ä«¸Þ¶ó¿¡¼ Á¤Á¡±îÁö °Å¸®À̰í e´Â ÀÚ¿¬ ´ë¼ö(exponential)ÀÔ´Ï´Ù. start´Â ¼±ÇüÆ÷±×°¡ Àû¿ëµÇ´Â ½ÃÀÛ °Å¸®, end´Â Æ÷±×ÀÇ È¿°ú°¡
´õ ÀÌ»ó Áõ°¡ÇÏÁö ¾Ê´Â ÃÖ´ë °Å¸®ÀÔ´Ï´Ù.
±×·¡ÇÁ¸¦ º¸¸é ¼±Çü Æ÷±×´Â ÀüüÀûÀ¸·Î ¼±ÇüÀûÀ¸·Î º¯ÈÇÏ´Â ¹Ý¸é¿¡ exp Æ÷±×´Â
±Þ°ÝÈ÷ º¯ÈÇß´Ù°¡ õõÈ÷ º¯ÈÇϰí exp2 Æ÷±×´Â õõÈ÷ º¯ÈÇÏ´Ù°¡ ±Þ°ÝÈ÷ º¯ÇÏ´Â °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù.

<Linear, Exp, Exp2>
¼±Çü Æ÷±×´Â end °ª ÀÌÈÄ¿¡´Â Æ÷±×»ö»óÀÌ 100%Àû¿ëÀÌ µÇ¾î ¿ÞÂÊó·³ £Àº Æ÷±× »ö»óÀÇ ¶ì¸¦ ¸¸µé±âµµ ÇÕ´Ï´Ù.
D3DÀÇ Æ÷±×´Â ´ÙÀ½ ±×¸²Ã³·³ ¿µ¿ª ±â¹Ý(Range-based)¸¦ ¼³Á¤Çϰųª ¶Ç´Â ÇØÁ¦(Plane-based) ÇÒ
¼ö ÀÖ½À´Ï´Ù.

<¿µ¿ª ±â¹Ý(Range-based)
Æ÷±× ¼³Á¤, ¹Ì ÁöÁ¤>

<¿µ¿ª ±â¹Ý ¼³Á¤ÀÌ ¾ÈµÈ Æ÷±×¿¡¼ÀÇ ¿ÀºêÁ§Æ®>
¿µ¿ª ±â¹ÝÀ¸·Î Çϸé Ä«¸Þ¶óÀÇ È¸Àü¿¡µµ Æ÷±×°¡ ÀÚ¿¬½º·´°Ô Àû¿ëÀÌ µË´Ï´Ù. ±×·¯³ª
¿µ¿ª ±â¹ÝÀ» ºñȰ¼ºÈ Çϸé Ä«¸Þ¶ó¿ÍÀÇ °Å¸®°¡ ¾Æ´Ñ z °ªÀ» °¡Áö°í Æ÷±×°è¼ö¸¦ °è»êÇϱ⠶§¹®¿¡ Ä«¸Þ¶óÀÇ
ȸÀü¿¡ ´ëÇØ¼ Æ÷±× Àû¿ëÀÌ µÉ ¼öµµ ÀÖ°í ¾ÈµÉ ¼öµµ ÀÖ½À´Ï´Ù.
Á¤Á¡ Æ÷±×´Â Á¤Á¡ º¯È¯°ú Á¶¸íÀ» Àû¿ëÇÒ ¶§ Æ÷±× ¶ÇÇÑ Àû¿ëÀÌ µÇ°í, Çȼ¿
Æ÷±×´Â Çϵå¿þ¾î¿¡ µû¶ó¼ ¹Ì¸® °è»ê µÈ ÂüÁ¶ Å×À̺íÀ» ÅëÇØ¼ Çȼ¿ÀÇ ±íÀÌ °ª¿¡ µû¶ó Æ÷±×°¡ Àû¿ëÀÌ µË´Ï´Ù. ÀÌ·±
ÀÌÀ¯·Î Çȼ¿ Æ÷±×¸¦ Å×ÀÌºí Æ÷±×¶ó Çϱ⵵ Çϸç Çȼ¿ Æ÷±×´Â ¿µ¿ª ±â¹Ý ¼³Á¤ÀÌ Á¦´ë·Î ¾ÈµË´Ï´Ù.
Â÷À̰¡ Ŭ °Í °°Áö¸¸ Á¤Á¡ Æ÷±×¿Í Çȼ¿ Æ÷±×´Â Àß º¸Áö ¾ÊÀ¸¸é Àå¸éÀÇ °á°ú¿¡¼´Â °ÅÀÇ Â÷À̰¡ ¾ø½À´Ï´Ù.
Æ÷±×ÀÇ ±âº»ÀûÀÎ ³»¿ëÀ» ´Ù »ìÆì º¸¾Ò°í ´ÙÀ½À¸·Î À̸¦ ±¸Çö ÇÏ´Â ¹æ¹ýÀÔ´Ï´Ù. ¸ÕÀú
´ÙÀ½°ú °°Àº ÇÔ¼ö¸¦ ÁغñÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù.
inline DWORD FtoDW(float& p) { return *((DWORD*)&p); }
À̰ÍÀº D3DÀÇ »óÅ °ª ¼³Á¤Àº °ÅÀÇ DWORDÇüÀ¸·Î µÇ¾î ÀÖ½À´Ï´Ù. ±×·±µ¥ Æ÷±×´Â FLOATÇüÀ» »ç¿ëÇϰí ÀÖ¾î¼ ´Ü¼øÈ÷ ÀڷḦ º¹»çÇÏ°Ô µÇ¸é Á¦´ë·Î 󸮰¡ ¾ÈµÇ¾î DWORDÇüÀ¸·Î ÀڷḦ ij½ºÆÃ ÇØ¾ß¸¸ ÇÕ´Ï´Ù. À§¿Í °°Àº ÇÔ¼ö¸¦ »ç¿ëÇϸé
ÀÚ·áÀÇ À¯½Ç ¾øÀÌ ¿Ã¹Ù·Î ³Ñ±æ ¼ö ÀÖ½À´Ï´Ù.
´ÙÀ½À¸·Î ´ÙÀ½°ú °°ÀÌ Æ÷±×ÀÇ »ö»ó, ½ÃÀÛ, ³¡, ¹Ðµµ(Density)¿¡
´ëÇÑ º¯¼ö¸¦ ÁغñÇÕ´Ï´Ù.
DWORD dFog =
D3DXCOLOR(0.2f, 1.f, 0.7f, 1.0f);
float fStart = 300.0f;
float fEnd =
700.0f;
float fDens =
0.0015f;
°ÔÀÓ¿¡¼´Â ÁÖ·Î ¼±Çü Æ÷±×(Linear
Fog)¸¦ »ç¿ëÇϰí ÀÖ¾î¼ EXP¿¡¼ »ç¿ëµÇ´Â ¹Ðµµ(Density)
º¯¼ö´Â °ÅÀÇ ¼³Á¤ ¾È ÇÕ´Ï´Ù.
µð¹ÙÀ̽ºÀÇ »óÅ ¼³Á¤ ÇÔ¼ö
RenderState()¸¦ ÀÌ¿ëÇØ¼ Æ÷±×¸¦ Ȱ¼ºÈÇÕ´Ï´Ù.
m_pDev->SetRenderState(D3DRS_FOGENABLE, TRUE);
Á¤Á¡ Æ÷±×ÀÌ¸é ´ÙÀ½°ú °°ÀÌ Çȼ¿ ±â¹Ý Æ÷±×¸¦ ¸·°í Á¤Á¡ Æ÷±×¿¡ Linear, Exp, Exp2Áß Çϳª¸¦ ¼³Á¤ÇÕ´Ï´Ù.
m_pDev->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
m_pDev->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_"LINEAR", "EXP", or"EXP2");
Çȼ¿ Æ÷±×¸é Á¤Á¡ Æ÷±×¸¦ ¸·°í Çȼ¿ Æ÷±× ¼³Á¤À» ÇÕ´Ï´Ù.
m_pDev->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
m_pDev->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_"LINEAR", "EXP", or"EXP2");
¸¶Áö¸·À¸·Î Æ÷±× º¯¼öµé°ú ¿µ¿ª ±â¹Ý Ȱ¼ºÈ¸¦ ¼³Á¤ÇÕ´Ï´Ù.
m_pDev->SetRenderState(D3DRS_RANGEFOGENABLE, "TRUE"? "FALSE");
m_pDev->SetRenderState(D3DRS_FOGCOLOR,
"Æ÷±×
»ö»ó");
m_pDev->SetRenderState(D3DRS_FOGSTART,
*((DWORD*)(&fStart)));
m_pDev->SetRenderState(D3DRS_FOGEND,
FtoDW(fEnd));
m_pDev->SetRenderState(D3DRS_FOGDENSITY,
FtoDW(fDens));
Àüü ÄÚµå´Â daux01_fog.zip
ÀÇ CMain::Render() ÇÔ¼ö¸¦ Âü°í Çϱ⠹ٶø´Ï´Ù.
3.2 ÆùÆ®(Font)
3.2.1 ID3DXFont
ID3DXFont´Â ¾ÆÁÖ ½±°Ô »ç¿ëÇÒ ¼ö ÀÖ´Â ÆùÆ® Ãâ·Â¿ë È®Àå À¯Æ¿¸®Æ¼ÀÔ´Ï´Ù. ÀϹÝÀûÀ¸·Î À©µµ¿ìÀÇ ÆùÆ®¸¦ ±âº»À¸·Î ¸¹ÀÌ »ç¿ëÇÕ´Ï´Ù. ±×·±µ¥ ¶§·Î´Â
°ÔÀÓ¿¡ ¸Â´Â ÆùÆ®¸¦ µû·Î ¸¸µé¾î »ç¿ëÇÒ ¶§µµ ÀÖ½À´Ï´Ù. ÀÌ·± °æ¿ì À©µµ¿ì Æú´õ¿¡ ÆùÆ®¸¦ µî·ÏÇØ »ç¿ëÇØ¾ß
ÇÏÁö¸¸ °£´ÜÈ÷ Platform SDK ÇÔ¼ö¸¦ »ç¿ëÇØ¼ ÇÁ·Î±×·¥ ³»ºÎ¿¡¼¸¸ »ç¿ëÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù.
AddFontResourceEx()/RemoveFontResourceEx() ÇÔ¼ö´Â
ÆùÆ®¸¦ ÇÁ·Î±×·¥ ³»ºÎ¿¡¼ »ç¿ëÇϰí ÇØÁ¦ ÇÒ ¶§ »ç¿ëÇÏ´Â ÇÔ¼öÀÔ´Ï´Ù. ÀÌ ÇÔ¼ö´Â Windows 2000 À̻󿡼¸¸ Áö¿øÀÌ µË´Ï´Ù. µû¶ó¼ "windows.h" Æ÷ÇÔÇÒ ¶§ ¸ÅÅ©·Î·Î »óÀ§¹öÀüÀÓÀ» Ç¥½ÃÇØ¾ß ÇÕ´Ï´Ù.
ÀÌ ÇÔ¼öµéÀ» »ç¿ëÇØ¼ ID3DXFont°´Ã¼ »ý¼º°ú ÇØÁ¦´Â ´ÙÀ½°ú °°ÀÌ
¿ä¾àÇÒ ¼ö ÀÖ½À´Ï´Ù.
#define _WIN32_WINNT 0x0500
#include <windows.h>
// ÆùÆ® µî·Ï
hr = AddFontResourceEx("font/08SeoulNamsanB.ttf", FR_NOT_ENUM, NULL);
hr = AddFontResourceEx("font/08SeoulHangangM.ttf", FR_NOT_ENUM, NULL);
¡¦
// ID3DXFont °´Ã¼ »ý¼º
hr = D3DXCreateFont(¡¦, "08¼¿ï³²»êü B", &m_pDXFont1);
¡¦
// ÆùÆ® ÇØÁ¦
RemoveFontResourceEx("font/08SeoulNamsanB.ttf", FR_NOT_ENUM, NULL);
RemoveFontResourceEx("font/08SeoulHangangM.ttf", FR_NOT_ENUM, NULL);

< AddFontResourceEx() ÇÔ¼ö·Î ÇÁ·Î±×·¥ ³»ºÎ¿¡¼¸¸
»ç¿ë: daux02_font1_dx2d.zip>
3.2.2 3D ¹®ÀÚ¿
D3D´Â È®Àå À¯Æ¿¸®Æ¼·Î 3D ÆùÆ®µµ
Áö¿øÇÕ´Ï´Ù. D3DXCreateText() ÇÔ¼ö¸¦ »ç¿ëÇϸé 3D·Î
¹®ÀÚ¿À» ¸¸µé ¼ö ÀÖ½À´Ï´Ù. ±×·¯³ª ÀÌ ÇÔ¼ö´Â ÇÑ±Û ¹®ÀÚ¿À» Ãâ·ÂÇÒ ¶§´Â À¯´ÏÄÚµå(Unicode)¸¦ »ç¿ëÇϰųª ´ÙÀ½°ú °°ÀÌ MultiByteToWideChar()
ÇÔ¼ö¸¦ »ç¿ëÇØ¼ ¹®ÀÚ¿À» À¯´ÏÄÚµå·Î ¸¸µé¾î¾ß Ãâ·ÂÀÌ µË´Ï´Ù.
D3DXCreateText() ÇÔ¼ö´Â ¶ÇÇÑ À©µµ¿ì DC(Device Context)¸¦ Àμö·Î ¹Þ°í ÀÖ¾î ¹®ÀÚ¿ Ãâ·ÂÀ» À§ÇØ
API ¹æ½ÄÀ¸·Î CreateFont() ÇÔ¼ö ¶Ç´Â CreateFontIndirect()
ÇÔ¼ö·Î ¼Ã¼¿¡ ´ëÇÑ FONT °´Ã¼¸¦ ¸¸µç ´ÙÀ½, DC¿¡
¿¬°áÇÑ ÈÄ¿¡ D3DXCreateText()¸¦ È£ÃâÇØ¾ß ÇÔÀ» ÀǹÌÇÕ´Ï´Ù.
´ÙÀ½ ÄÚµå´Â 3D ¹®ÀÚ¿À» Ãâ·ÂÇÏ´Â ¿¹ÀÔ´Ï´Ù.
// 3D ¹®ÀÚ¿ Ãâ·Â °´Ã¼
LPD3DXMESH m_pMshStr;
¡¦
// DC »ý¼º
HDC hdc = CreateCompatibleDC( NULL );
HFONT hFontNew = NULL;
HFONT hFontOld = NULL;
LOGFONT hfont={0};
hfont.lfHeight
= 32;
¡¦
_tcscpy(hfont.lfFaceName, _T("08¼¿ï³²»êü B"));
hFontNew = CreateFontIndirect(&hfont);
hFontOld = (HFONT)SelectObject(hdc,
hFontNew);
char sSrc[256] = "¾È³çÇϼ¼¿ä Hello world !!! \0";
WCHAR sDst[256]={0};
// ¸ÖƼ ¹ÙÀÌÆ®¸¦ À¯´ÏÄÚµå·Î º¯°æ
LcStr_AnsiToUnicode(sDst, sSrc, strlen(sSrc)+1);
// 3D ¹®ÀÚ¿À» »ý¼º
D3DXCreateTextW(m_pDev, hdc,
sDst, 200.f, 3.f, &m_pMshStr, 0, 0);
SelectObject(hdc, hFontOld);
DeleteObject( hFontNew);
// DC ÇØÁ¦
DeleteDC( hdc );
LcStr_AnsiToUnicode() ÇÔ¼ö´Â À¯´ÏÄÚµå·Î ¹®ÀÚ¿À»
¹Ù²Ù¾îÁÖ´Â »ç¿ëÀÚ Á¤ÀÇ ÇÔ¼ö ÀÔ´Ï´Ù.

<3D ¹®ÀÚ¿ Ãâ·Â: daux02_font2_dx3d.zip>
3.2.3 ÈÄ¸é ¹öÆÛ(Back Buffer) Ãâ·Â
ID3DXFont´Â »ç¿ëÀÌ Æí¸®ÇÕ´Ï´Ù. ±×·¯³ª ¹®ÀÚ¿ÀÌ ¸¹¾ÆÁö¸é ·»´õ¸µ ¼Óµµ°¡ »ó´çÈ÷ ´À·ÁÁý´Ï´Ù. ¸¸¾à
¹®ÀÚ¿ÀÌ È¸é °¡µæÇصµ ÃÖ´ë ¼Óµµ¸¦ ¿øÇÑ´Ù¸é ÈÄ¸é ¹öÆÛ¿¡ Á÷Á¢ Ãâ·ÂÇÏ´Â ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù.
D3D9Àº ¾ËÆÄ°¡ ¾ø´Â ºÒÅõ¸í ¼Çǽº(Surface), D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_R8G8B8, D3DFMT_X8R8G8B8
Çü½ÄÀ¸·Î ¸¸µç ¼Çǽº¿¡ ´ëÇØ¼ DC¸¦ °¡Á®¿Ã ¼ö ÀÖ°Ô Çß½À´Ï´Ù. D3DPRESENT_ PARAMETERS ±¸Á¶Ã¼ º¯¼ö BackBufferFormat¸¦
X8R8G8B8 ¶Ç´Â D3DFMT_R5G6B5·Î ÁöÁ¤Çϰí
Flags º¯¼ö ¶ÇÇÑ D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
À¸·Î ÁöÁ¤À» ÇØ¾ß¸¸ ÈÄ¸é ¹öÆÛ¿¡¼ DC¸¦ °¡Á®¿Ã ¼ö ÀÖ½À´Ï´Ù.
m_d3dpp. BackBufferFormat = D3DFMT_X8R8G8B8;
m_d3dpp.MultiSampleType
= D3DMULTISAMPLE_NONE;
m_d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
ÈÄ¸é ¹öÆÛÀÇ DC´Â ¾Æ¹« ¶§³ª »ç¿ëÇÒ ¼ö ÀÖ´Â °ÍÀÌ ¾Æ´Ï¶ó ´ÙÀ½°ú
°°ÀÌ BeginScene()/EndScene() ¹Û¿¡¼¸¸ »ç¿ëÇØ¾ß ÇÕ´Ï´Ù.
m_pd3dDevice->BeginScene();
¡¦
m_pd3dDevice->EndScene();
LPDIRECT3DSURFACE9 pBackBuffer
= NULL;
m_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
if(pBackBuffer)
{
HDC hDC = NULL;
pBackBuffer->GetDC(&hDC);
if(hDC)
{
HFONT hFontOld
= NULL;
hFontOld
= (HFONT)SelectObject(hDC, m_hFont);
¡¦
TextOut(hDC, 10, 200, "Ãâ·Â ¹®ÀÚ¿", strlen("Ãâ·Â ¹®ÀÚ¿"));
SelectObject(hDC, hFontOld);
DeleteDC( hDC );
pBackBuffer->ReleaseDC(hDC);
}
pBackBuffer->Release();

< ÈÄ¸é ¹öÆÛ DC¿¡
¹®ÀÚ¿ Ãâ·Â: daux02_font3_backbuffer.zip>
»ó´çÈ÷ ºü¸£°Ô µ¿ÀÛÇÏÁö¸¸ ¹®Á¦´Â Flags º¯¼ö¸¦ D3DPRESENTFLAG_LOCKABLE_BACKBUFFER À¸·Î ¼³Á¤Çϸé
Anti-AliasingÀÌ Áö¿øÀÌ ¾ÈµË´Ï´Ù. ¶ÇÇÑ
BeginScene()/EndScene() ¹Û¿¡¼ ó¸®ÇØ¾ß ÇϹǷΠ¹®ÀÚ¿ Ãâ·ÂÀ» À§Çؼ Àüü ½Ã½ºÅÛ ÀÚü¸¦ ¹Ù²Ù¾î¾ß ÇÏ´Â ¹®Á¦µµ ÀÖ½À´Ï´Ù. ÀÌ ¸ðµç °ÍÀ» °¨¼öÇØµµ °¡Àå Å« ¹®Á¦´Â Èĸé¹öÆÛ¿¡ Á÷Á¢ Ãâ·ÂÀÌ µÇ¾î °ÔÀÓ ¾È ¿©·¯ ÆË¾÷ âÀÇ Overlap¿¡¼ ¸ðµç ¹®ÀÚ°¡ ¾ÕÀ¸·Î º¸ÀÌ´Â ¹®Á¦¸¦ Á¦¾îÇϱⰡ ¾î·Æ½À´Ï´Ù.
3.2.4 ÅØ½ºÃ³¸¦ ÀÌ¿ëÇÑ Ãâ·Â
ID3DXFont´Â ¹®ÀÚ¿ÀÌ ¸¹¾ÆÁö¸é ³»ºÎ ¹öÆÛ¸¦ °»½ÅÇϴ Ƚ¼öµµ
Áõ°¡ÇØ ·»´õ¸µÀÌ ´À·ÁÁö´Â °ÍÀÔ´Ï´Ù. ¾Õ¼ ºÒÅõ¸íÇÑ ¼Çǽº¿¡ ´ëÇØ¼
D3D9´Â DC¸¦ °¡Á®¿Í »ç¿ëÇÒ ¼ö ÀÖ´Ù°í Çß½À´Ï´Ù. À̰ÍÀ»
Àß ÀÌ¿ëÇϸé ÀÚÁÖ °»½ÅÀÌ ¾È µÇ´Â ¹®ÀÚ¿À» ÅØ½ºÃ³¿¡ Ãâ·ÂÇØ °¡Áö°í ÀÖ´Ù¸é ·»´õ¸µÀÇ ¼Óµµ´Â ºÐ¸íÈ÷ Áõ°¡ÇÒ °ÍÀÔ´Ï´Ù.
ÅØ½ºÃ³¿¡ ¹®ÀÚ¿À» Ãâ·ÂÇϱâ À§ÇØ ´ÙÀ½°ú °°ÀÌ FONT °´Ã¼, ÅØ½ºÃ³, ¼Çǽº¸¦ ÁغñÇÕ´Ï´Ù.
HFONT m_hFont;
LPDIRECT3DTEXTURE9 m_pTex;
LPDIRECT3DSURFACE9 m_pSfc;
´ÙÀ½À¸·Î ÆùÆ® °´Ã¼¸¦ ¸¸µé°í ÅØ½ºÃ³´Â D3DFMT_X8R8G8B8 Çü½ÄÀ¸·Î
¸¸µì´Ï´Ù. ÅØ½ºÃ³ °´Ã¼¸¦ ¸¸µç ÈÄ¿¡ ¼Çǽº¸¦ ÅØ½ºÃ³¿¡¼ °¡Á® ¿É´Ï´Ù.
ÀÌ ºÎºÐÀº daux02_font4_tex.zipÀÇ CMain::Init()¿¡ ±¸ÇöµÇ¾î ÀÖ½À´Ï´Ù.
// 1. ÆùÆ® °´Ã¼ »ý¼º
LOGFONT logf={0};
logf.lfHeight =
32;
¡¦
_tcscpy(logf.lfFaceName, _T("±Ã¼"));
m_hFont = CreateFontIndirect(&logf);
// 2. ÅØ½ºÃ³ »ý¼º
hr = D3DXCreateTexture(¡¦, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &m_pTex);
// 3. ¼Çǽº °¡Á®¿È
m_pTex->GetSurfaceLevel(0, &m_pSfc);
ÅØ½ºÃ³¸¦ »ý¼ºÇÒ ¶§ ¹Ó(Mip) ·¹º§À» 1·Î Çϰí, À©µµ¿ì Àüȯ¿¡µµ ¹®Á¦ ¾øµµ·Ï ¸Þ¸ð¸® Ç®À» MANAGED·Î ¼³Á¤ÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. ÀÌÁ¦ ¼Çǽº¿¡¼ DC¸¦ ¾ò°í ¹®ÀÚ¿À» Ãâ·ÂÇÏ¸é µË´Ï´Ù. ´ÙÀ½ ÄÚµå´Â daux02_font4_tex.zipÀÇ CMain::FrameMove() ÇÔ¼ö¿¡ ±¸ÇöµÇ¾î ÀÖ½À´Ï´Ù.
// ÅØ½ºÃ³ ¼ÇǽºÀÇ DC¿¡ ¹®ÀÚ¿ Ãâ·Â
if(m_pSfc)
{
HDC hDC = NULL;
m_pSfc->GetDC(&hDC);
if(hDC)
{
TCHAR sMsg[256] = "";
sprintf( sMsg, "ÅØ½ºÃ³ DC¿¡ ¹®ÀÚ¿ Ãâ·ÂÀÔ´Ï´Ù");
HFONT hFontOld = (HFONT)SelectObject(hDC, m_hFont);
SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(255, 0, 255));
TextOut(hDC, 50, 50, sMsg, strlen(sMsg));
¡¦
SelectObject(hDC, hFontOld);
DeleteDC( hDC );
m_pSfc->ReleaseDC(hDC);
}
}

< ¼ÇǽºÀÇ DC¿¡
¹®ÀÚ Ãâ·Â: daux02_font4_tex.zip>
3.2.5 ÅØ½ºÃ³ Ãâ·Â¿¡ ´ëÇÑ ÆùÆ® Ŭ·¡½º
ÀÌÁ¦ ÅØ½ºÃ³¿¡ Ãâ·ÂÀÌ µÈ´Ù´Â °ÍÀ» ¾Ë¾Ò½À´Ï´Ù. ³²Àº °ÍÀº ÀÌ ³»¿ëÀ» ID3DXFontó·³ »ç¿ëÇÏ±â Æí¸®ÇÏ°Ô Å¬·¡½º·Î ¸¸µå´Â ÀÏÀÔ´Ï´Ù. daux02_lnfont_2d.zipÀÇ CLnFont2D
Ŭ·¡½º´Â ÅØ½ºÃ³¿¡ ¹®ÀÚ¿À» Ãâ·ÂÇϴ Ŭ·¡½º ÀÔ´Ï´Ù.
CLnFont2D Ŭ·¡½ºÀÇ ¼±¾ð¿¡ º¸¸é ¹®ÀÚ¿À» Æ÷ÇÔÇÏ´Â ÅØ½ºÃ³´Â
´ÙÀ½°ú °°ÀÌ ¼±¾ðµÇ¾î ÀÖ½À´Ï´Ù.
LPDIRECT3DTEXTURE9 m_pTxD; // Output Texture
º¸Åë ¹®ÀÚ¿ ÀÌ¿ÜÀÇ °ø°£Àº ÀüºÎ Åõ¸íÇÏ°Ô ÇØ¾ß ÇÕ´Ï´Ù. ±×·±µ¥ ¼Çǽº¿¡¼ DC¸¦ °¡Á®¿Ã ¼ö ÀÖ´Â °ÍÀº ºÒÅõ¸í ÅØ½ºÃ³ ¹Û¿¡ ¾ø½À´Ï´Ù. ¹®ÀÚ¿ÀÇ
¹è°æÀ» Åõ¸íÇÏ°Ô ¸¸µé±â À§Çؼ ¸ÕÀú Àӽ÷ΠºÒÅõ¸í ÅØ½ºÃ³¸¦ ¸¸µé°í ÀÌ ºÒÅõ¸í ÅØ½ºÃ³ÀÇ DC¿¡ ¹®ÀÚ¿À»
Ãâ·ÂÇÕ´Ï´Ù. ´ÙÀ½À¸·Î ¾ËÆÄ°¡ ÀÖ´Â Ãâ·Â¿ë ÅØ½ºÃ³¸¦ ¸¸µé¾î¼ ºÒÅõ¸í ÅØ½ºÃ³ ÀüºÎ¸¦ º¹»çÇÕ´Ï´Ù.
CLnFont2D::SetTexture() ÇÔ¼ö´Â ¹Ù·Î ÀÌ·± ÀÏÀ»
ó¸®ÇÕ´Ï´Ù. ÀÌ ÇÔ¼öÀÇ Äڵ带 ¼³¸íÇÏ¸é ¸ÕÀú ´ÙÀ½°ú °°ÀÌ ºÒÅõ¸í ÅØ½ºÃ³, ÀÌ ºÒÅõ¸í ÅØ½ºÃ³¿¡ ´ëÇÑ ¼Çǽº, Ãâ·Â¿ë ÅØ½ºÃ³¿¡ ´ëÇÑ ¼Çǽº¸¦
ÁغñÇÕ´Ï´Ù.
LPDIRECT3DTEXTURE9 pTxS =
NULL; // ºÒÅõ¸í ÅØ½ºÃ³
LPDIRECT3DSURFACE9 pSfTxtS =
NULL; // ºÒÅõ¸í ÅØ½ºÃ³ÀÇ ¼Çǽº
LPDIRECT3DSURFACE9 pSfTxtD =
NULL; // Ãâ·Â¿ë ÅØ½ºÃ³ m_pTxDÀÇ ¼Çǽº
´ÙÀ½À¸·Î ºÒÅõ¸í ÅØ½ºÃ³¸¦ ¹®ÀÚ¿ÀÇ Æø°ú ³ôÀ̸¸Å ÅØ½ºÃ³¸¦ ¸¸µé°í ¼Çǽº¸¦ °¡Á®¿É´Ï´Ù.
¹®ÀÚ¿ ³ôÀÌ¿Í ÆøÀº CLnFont2D::SetString(TCHAR* sStr)
ÇÔ¼ö¿¡¼ GetTextExtentPoint32() ÇÔ¼ö¿Í GetTextMetrics() ÇÔ¼ö¸¦ ÅëÇØ¼ °è»êÇÕ´Ï´Ù.
D3DXCreateTexture(¡¦, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED,
&pTxS); //
ºÒÅõ¸í Texture »ý¼º
pTxS->GetSurfaceLevel(0, &pSfTxtS);
ÀÌ ºÒÅõ¸í ÅØ½ºÃ³ÀÇ DC ¸¦
¾ò°í ¹®ÀÚ¿À» ¾¹´Ï´Ù.
pSfTxtS->GetDC(&hDC);
TextOut(hDC, ¡¦, m_sStr, m_iLen);
¸¶Áö¸· ´Ü°è¿¡¼ ¾ËÆÄ°¡ ÀÖ´Â Ãâ·Â¿ë ÅØ½ºÃ³¸¦ ´Ù½Ã »ý¼ºÇϰí
ºÒÅõ¸í ÅØ½ºÃ³¿¡¼ ¾ËÆÄ°¡ ÀÖ´Â Ãâ·Â¿ë ÅØ½ºÃ³·Î D3DXLoadSurfaceFromSurface() ÇÔ¼ö¸¦
ÀÌ¿ëÇØ¼ ÀüºÎ º¹»ç¸¦ ÇÕ´Ï´Ù. ÀÌ ¶§ ¿ÏÀü ºÒÅõ¸í °ËÁ¤»ö(0xFF000000)À»
Åõ¸í °ªÀ¸·Î ¼³Á¤ÇÕ´Ï´Ù.
D3DXCreateTexture(¡¦, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
&m_pTxD); // ¹ÝÅõ¸í ÅØ½ºÃ³ »ý¼º
¡¦
m_pTxD->GetSurfaceLevel(0, &pSfTxtD);
D3DXLoadSurfaceFromSurface(
pSfTxtD, ¡¦, pSfTxtS, D3DX_DEFAULT, 0xFF000000);
0xFF000000 »ö»ó °ªÀ» Åõ¸í Ű·Î ¸¸µé¾î¼ ÇϳªÀÇ »ö»ó(0xFF000000)À» »ç¿ëÇÒ ¼ö ¾øÁö¸¸ ÀüüÀûÀ¸·Î ÅØ½ºÃ³¸¦ ÀÌ¿ëÇϰí ÀÖ¾î¼ ¹®ÀÚ¿ÀÌ ÀÚÁÖ ¹Ù²îÁö ¾Ê´Â ÇÑ ´Ù¸¥
¾î¶² ¹æ¹ýº¸´Ù ·»´õ¸µ ¼Óµµ°¡ ¿ì¼öÇÏ´Ù°í ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¶ÇÇÑ ÀÚÁÖ º¯ÇÏ´Â ¹®ÀÚ¿À» µû·Î °ü¸®Çؼ ÀÌ¿¡
ÀÇÇÑ ·»´õ¸µ ¼Óµµ ÀúÇϸ¦ ¸·À» ¼ö ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¸é äÆÃ°ú °°Àº ÀÚÁÖ ¹®ÀÚ¿ÀÌ °»½ÅµÇ°í È¸é ½ºÅ©·ÑÀÌ
ÇÊ¿äÇÑ ¹®ÀÚ¿¿¡ ´ëÇØ¼ °¢ ¹®ÀÚ¿ ¶óÀÎ º°·Î ÅØ½ºÃ³¸¦ ¸¸µé¾î¼ ¹®ÀÚ¿À» Ãâ·ÂÇØ °ü¸®ÇÏ¸é ¹®ÀÚ¿¿¡ ÀÇÇÑ ¼Óµµ ÀúÇϸ¦ ¸·À» ¼ö ÀÖ½À´Ï´Ù.
¿Ü°û¼± ÃßÃâ ¾Ë°í¸®Áò ¾øÀÌ 9¹øÀ»
DC¿¡ ½á¼ °£´ÜÇÏ°Ô ¹®ÀÚ¿¿¡ Å׵θ®¸¦ ¸¸µé ¼öµµ ÀÖ½À´Ï´Ù. ±×¸®°í ÀÌ·± ¹æ½ÄÀ» Direct3DMobile¿¡ Àû¿ëÀ» Çϸé Çѱ۰ú °°Àº 2Byte ¹®ÀÚ¿À»
½±°Ô Ãâ·ÂÇÒ ¼ö ÀÖ½À´Ï´Ù.
´ÙÀ½ ±×¸²Àº ÅØ½ºÃ³¿¡ ¹®ÀÚ¿À» Ãâ·ÂÇØ¼ ¸¸µç ¿¹Á¦ ÀÔ´Ï´Ù.

<ÅØ½ºÃ³¿¡ ¹®ÀÚ¿ Ãâ·Â Ŭ·¡½º:
daux02_lnfont_2d.zip, daux02_lnfont_3d.zip>
DXSDK 2003 summer ¹öÀü±îÁö ¿¹Á¦ Áß¿¡ CD3DFont Ŭ·¡½º°¡ ÀÖ¾ú½À´Ï´Ù. ÀÌ Å¬·¡½º´Â ¾Æ½ºÅ° (ASCII) Äڵ忡 ´ëÇØ¼¸¸ Ãâ·ÂÇϰí ÀÖ½À´Ï´Ù. ±×·±µ¥ Àç¹ÌÀÖ´Â
°ÍÀº ¾Æ½ºÅ° ¹®ÀÚ¿ Áß¿¡¼ Ư¼ö ¹®ÀÚ¸¦ Á¦¿ÜÇÏ°í ¾Æ½ºÅ° ¹øÈ£ 32(space) ~ 126±îÁö ¹®ÀÚµéÀ»
ÅØ½ºÃ³¿¡ ¹Ì¸® ¸¸µé¾î ³õ°í, ¹®ÀÚ¿Ãâ·ÂÀ» ¿äûÇϸé ȸé À§Ä¡¿¡ ÇÑ ±ÛÀÚ¾¿ Ãâ·ÂÀ» ÇÕ´Ï´Ù. ÀÌ ¹æ¹ýÀº OpenGL¿¡¼µµ ºñ½ÁÇÏ°Ô ÀÌ¿ëÇÏ´Â ¹æ¹ýÀÌ´Ï ³ªÁß¿¡ ½Ã°£ÀÌ
ÀÖÀ¸¸é µé¿©´Ù º¸±â ¹Ù¶ø´Ï´Ù.
3.3 FPS (Frames Per
Second)
2D °ÔÀÓ ÇÁ·Î±×·¡¹Ö¿¡¼ Frame
°è»êÀ» ¹è¿ü½À´Ï´Ù. ÇÁ·¹ÀÓ °è»êÀº Æò±ÕÀ» ÀÌ¿ë 1ÃÊ
µ¿¾È ȸ鿡 ·»´õ¸µ Çϴ Ƚ¼ö¸¦ °è»ê ÇÕ´Ï´Ù. µû¶ó¼ °¡Àå Á¤È®ÇÑ ½Ã°£À» »ç¿ëÇØ¾ß ÇÁ·¹ÀÓµµ Á¤È®È÷ °è»ê
µÉ ¼ö ÀÖ½À´Ï´Ù.
À©µµ¿ì ½Ã½ºÅÛÀº ½Ã°£ ÃøÁ¤À» À§ÇØ GetTickCount()¿Í timeGetTime() ÇÔ¼ö°¡ Á¸Àç ÇÕ´Ï´Ù. ±×·±µ¥ ¸¸¾à À©µµ¿ì
½Ã½ºÅÛÀ» »ç¿ëÇÏÁö ¾Ê´Â ¸ð¹ßÀÏ ½Ã½ºÅÛ °°Àº °æ¿ì¿¡´Â C-Library¸¦ »ç¿ëÇÒ ¼ö ¹Û¿¡ ¾ø´Â °æ¿ìµµ
ÀÖ½À´Ï´Ù. ÀÌ ¶§ timeGetTime() ´ë½Å clock() ÇÔ¼ö¸¦ »ç¿ëÇÕ´Ï´Ù.
clock()ÇÔ¼ö´Â ´ë·« 1/CLOCKS_PER_SEC
Á¤µµÀÇ Á¤È®µµ¸¦ °¡Áö¸ç À©µµ¿ì ½Ã½ºÅÛ ½Ã°£ º¸´Ù Á¤È®µµ´Â ¸¹ÀÌ ¶³¾îÁö´Â ÆíÀÌÁö¸¸ C ¾ð¾î°¡
Áö¿øµÇ´Â ¾î¶² Ç÷§Æû¿¡¼µµ »ç¿ëÇÒ ¼ö ÀÖ°í ÇÁ·¹ÀÓÀÌ ³ôÁö ¾ÊÀº °æ¿ì¿¡´Â ´ë¾ÈÀ¸·Î »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.
´ÙÀ½Àº clock()ÇÔ¼ö¸¦ »ç¿ëÇØ¼ ÇÁ·¹ÀÓÀÇ Æò±ÕÀ» °è»êÇÏ´Â ÄÚµå
ÀÔ´Ï´Ù.
FLOAT UseClock()
{
static DOUBLE fFps = 0.;
static INT iCnt
= 0;
static clock_t dBgn = clock();
clock_t dCur = clock();
++iCnt;
if(iCnt>=MaxCount)
{
fFps
= DOUBLE(dCur
- dBgn);
fFps
= iCnt*1000./fFps;
iCnt
= 0;
dBgn
= dCur;
}
return (FLOAT)fFps;
}
°°Àº Äڵ忡 ½Ã°£ È£Ãâ ÇÔ¼ö¸¦ À©µµ¿ìÀÇ timeGetTime(), ¶Ç´Â GetTickCount()¸¦ clock() ÇÔ¼ö ÀÚ¸®¿¡ ¹Ù²Ù¾î ³õÀ¸¸é
À©µµ¿ì ½Ã½ºÅÛ¿¡¼ Àß µ¿ÀÛÇÏ´Â ÇÁ·¹ÀÓ °è»ê ÇÔ¼ö°¡ µË´Ï´Ù.
FLOAT UseTimeGetTime()
{
static DOUBLE fFps = 0.;
static INT iCnt
= 0;
static DWORD dBgn = timeGetTime();
DWORD dCur = timeGetTime(); // GetTickCount()
++iCnt;
if(iCnt>=MaxCount)
{
fFps
= DOUBLE(dCur-dBgn);
fFps
= iCnt*1000./fFps;
iCnt
= 0;
dBgn
= dCur;
}
return (FLOAT)fFps;
}
¸¸¾à Intel CPU¸¦
´ë»óÀ¸·Î ÇÑ´Ù¸é ´ÙÀ½ÀÇ GetIntelPrecisionTime() ÇÔ¼ö¿Í °°ÀÌ Inline Assembly¸¦ ÀÌ¿ëÇØ¼ 1/1,000,000 ÃÊ ´ÜÀ§ÀÇ
°íÇØ»óµµ(High-Resolution) ½Ã°£À» ÃøÁ¤ÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÌ
ÇÔ¼ö´Â clock() ¶Ç´Â GetTickCount() °ú
ºñ½ÁÇÑ µ¿ÀÛÀ» À§ÇØ ÀÛ¼º µÇ¾ú½À´Ï´Ù. ½Ã°£ÀÇ Á¤¹Ðµµ¸¦ À§ÇØ
double ÇüÀ» »ç¿ëÇϰí ÀÖÀ½À» ÁÖÀÇÇϱ⠹ٶø´Ï´Ù.
DOUBLE GetIntelPrecisionTime()
{
#define cpuid __asm __emit 0fh __asm __emit 0a2h
#define rdtsc __asm __emit 0fh __asm __emit 031h
static LARGE_INTEGER Freq
={0};
static BOOL bEnable
= 1;
LARGE_INTEGER dCur
={0};
DOUBLE dTime
=0;
if(0 == bEnable)
return -1;
if(0 == Freq.QuadPart)
{
bEnable
= QueryPerformanceFrequency(&Freq);
if(0 == bEnable)
return -1;
}
__asm
{
cpuid
rdtsc
mov dCur.LowPart, eax
mov dCur.HighPart, edx
}
dTime
= DOUBLE(dCur.QuadPart)/DOUBLE(Freq.QuadPart);
dTime
*=1000.;
return dTime;
}
ÀÌÀüÀÇ ÇÁ·¹ÀÓ °è»ê¿¡¼ clock(), ¶Ç´Â timeGetTime()À» GetIntelPrecisionTime () ÇÔ¼ö·Î
¹Ù²Ù¸é ÀÎÅÚ Ä¨ÀÇ °íÇØ»óµµ ŸÀ̸Ӹ¦ ÀÌ¿ëÇÑ ÇÁ·¹ÀÓ °è»ê ÇÔ¼ö°¡ µË´Ï´Ù.
FLOAT UseTimeGetPrecisionTime()
{
static DOUBLE fFps = 0.;
static INT iCnt
= 0;
static DOUBLE dBgn = GetIntelPrecisionTime();
DOUBLE dCur = GetIntelPrecisionTime();
++iCnt;
if(iCnt>=MaxCount)
{
fFps
= dCur-dBgn;
fFps
= iCnt*1000./fFps;
iCnt
= 0;
dBgn
= dCur;
}
return (FLOAT)fFps;
}
À©µµ¿ì ½Ã½ºÅÛ¿¡¼´Â °íÇØ»óµµ ŸÀ̸Ӹ¦ À§ÇÑ QueryPerformanceCounter()¿Í
QueryPerformance-Frequency() ÇÔ¼ö°¡ ÀÖ½À´Ï´Ù.
¸¸¾à CPU¿¡¼ °íÇØ»óµµ ŸÀ̸Ӹ¦ Áö¿øÀÌ µÇ¸é ÀÌ µÑÀÇ ÇÔ¼ö¸¦ »ç¿ëÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù.
¸ÕÀú QueryPerformanceFrequency() ÇÔ¼ö¸¦ °¡Áö°í
Áøµ¿¼ö¸¦ °¡Á® ¿É´Ï´Ù. ¸¸¾à °¡Á®¿À±â°¡ ½ÇÆÐÇϸé 0À» ¹ÝȯÇÕ´Ï´Ù. ´ÙÀ½À¸·Î QueryPerformanceCounter() ÇÔ¼ö¸¦ »ç¿ëÇØ¼
¼öÇàÇÑ Counter¸¦ ¾ò¾î ¿É´Ï´Ù. ÀÌ °ªÀ» ¾Õ¿¡¼ ±¸ÇÑ
Áøµ¿¼ö·Î ³ª´©¸é ÇÁ·¹ÀÓÀÌ µË´Ï´Ù. ´ÙÀ½ ÇÔ¼ö´Â ÀÌ µÎ ÇÔ¼ö¸¦ »ç¿ëÇØ¼ ÇÁ·¹ÀÓÀ» °è»êÇÏ´Â ÄÚµå ÀÔ´Ï´Ù.
FLOAT UsePerformanceCounter()
{
static DOUBLE fFps
= 0.;
static INT iCnt
= 0;
static LARGE_INTEGER Freq
= {0};
static LARGE_INTEGER dBgn
= {0};
static BOOL bEnable=1;
LARGE_INTEGER dCur
= {0};
if(0 == bEnable)
return -1.f; // Çϵå¿þ¾î Áö¿øÀÌ ¾ÈµÊ
if(0 == Freq.QuadPart) // ÃÖÃÊ ÇÔ¼ö È£Ãâ ½Ã
{
bEnable
= QueryPerformanceFrequency( &Freq);
if(0 == bEnable)
return -1.f;
QueryPerformanceCounter(&dBgn);
}
QueryPerformanceCounter(&dCur);
++iCnt;
if(iCnt>=MaxCount)
{
DOUBLE fElapsedTime =
DOUBLE(dCur.QuadPart - dBgn.QuadPart)/ DOUBLE(Freq.QuadPart);
fFps
= iCnt/fElapsedTime;
iCnt
= 0;
dBgn
= dCur;
}
return (FLOAT)fFps;
}
QueryPerformanceCounter() ¿¡¼ ¾òÀº °ªÀ» QueryPerformanceFrequency() ÇÔ¼ö¿¡¼ ¾òÀº Áøµ¿¼ö·Î ³ª´©¸é ½Ã°£ÀÌ µÇ¾î timeGetTime()À» ´ë½ÅÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÌ ¶§ ÁÖÀÇÇÒ °ÍÀº
°íÇØ»óµµ ŸÀÌ¸Ó´Â ÇØ»óµµ°¡ 1/1,000,000 ÃÊ ÀÔ´Ï´Ù.
timeGetTime()Àº 1/1,000 ÃÊ ´ÜÀ§À̹ǷΠÀÌ µÑÀ» ¸ÂÃß·Á¸é °íÇØ»óµµ ŸÀ̸Ӻκп¡ 1000.0À» °öÇØ¾ß ¼·Î°¡ µ¿ÀÏÇÑ ½Ã°£À» ¸¸µé¾î ÁÝ´Ï´Ù.
DOUBLE TimeGetPrecisionTime()
{
static LARGE_INTEGER Freq
={0};
static BOOL bEnable
= 1;
LARGE_INTEGER dCur
={0};
DOUBLE dTime
=0;
if(0 == bEnable)
return -1;
if(0 == Freq.QuadPart)
{
bEnable
= QueryPerformanceFrequency(&Freq);
if(0 == bEnable)
return -1;
}
QueryPerformanceCounter(&dCur);
dTime
= DOUBLE(dCur.QuadPart)/DOUBLE(Freq.QuadPart);
dTime
*=1000.;
return dTime;
}
´ÙÀ½ ±×¸²Àº À̵é ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼ ÇÁ·¹ÀÓ°ú ½Ã°£À» °è»êÇÑ °á°ú ÀÔ´Ï´Ù.

<30 ÇÁ·¹ÀÓ Æò±Õ, 4 ÇÁ·¹ÀÓ
Æò±Õ: daux03_frame.zip>
ÇÁ·¹ÀÓÀ» °è»êÇϴµ¥ ´ë·« 30À» Æò±Õ Ƚ¼ö·Î ¼³Á¤ÇÑ °æ¿ì¿¡´Â ¿ÞÂÊó·³
°íÇØ»óµµ ¶Ç´Â ÀúÇØ»óµµ ŸÀ̸Ӹ¦ »ç¿ëÇØµµ °ÅÀÇ Â÷À̰¡ ¾ø½À´Ï´Ù. ±×·±µ¥ Ƚ¼ö¸¦ ÁÙÀ̸é ÇØ»óµµ°¡ ³·Àº clock(), timeGetTime() ÇÔ¼ö´Â °è»êÀÌ ¾û¸ÁÀÌ µË´Ï´Ù. µû¶ó¼
¾ÆÁÖ ºü¸¥ ½Ã½ºÅÛÀ» ´ë»óÀ¸·Î °ÔÀÓÀ» ¸¸µé °æ¿ì¿¡´Â °íÇØ»óµµ ŸÀ̸Ӹ¦ ÀÌ¿ëÇÏ´Â °ÍÀÌ À¯¸®ÇÒ °Í °°Áö¸¸ ²À ±×·¸Áöµµ ¾ÊÀº °ÍÀÌ ½ÇÁ¦·Î °ÔÀÓÀÇ ·»´õ¸µ
¼Óµµ´Â ÇÁ·Î±×·¡¸ÓµéÀÌ 15~60 »çÀÌ¿¡ ¸ÂÃß´Â °æÇâÀÌ ÀÖ½À´Ï´Ù. °ÔÀÓÀÌ 1000 ÇÁ·¹ÀÓ ÀÌ»ó ¾È µÇ´Â °æ¿ì¿¡´Â ¿©ÀüÈ÷ timeGetTime()°ú
°°Àº ÇÔ¼ö·Î ÇÁ·¹ÀÓ °è»êÀ» ÇØµµ ÃæºÐÇÕ´Ï´Ù.
3.4 ÇÑ±Û IME
ÇÑ±Û ¹®ÀÚ¿Àº ID3DXFont µîÀ» ÀÌ¿ëÇØ Ãâ·ÂÇÒ ¼ö ÀÖ¾ú½À´Ï´Ù. ±×·±µ¥ ÇÑ±Û ÀÔ·ÂÀº ¾î¶»°Ô ó¸®ÇÒ±î¿ä? ¿µ¾î´Â ¾Æ½ºÅ° ÄÚµå·Î GetAsyncKeyState() ÇÔ¼ö µîÀ» ÀÌ¿ëÇØ Áï½Ã 󸮰¡ °¡´ÉÇÏÁö¸¸ ÇѱÛÀÇ °æ¿ì ±ÛÀÚ¸¦ Á¶ÇÕÇØ¾ß ÇÕ´Ï´Ù.
À©µµ¿ì ½Ã½ºÅÛÀº ÀԷ±⠶Ǵ ÀÔ·Â ¹æ½Ä ÆíÁý±â¶ó´Â IME(Input Method
Editor) ½Ã½ºÅÛÀ» ÀÌ¿ëÇØ¼ ¾Æ½ºÅ° ÄÚµå ÀÌ¿ÜÀÇ ¹®ÀÚµéÀ» Á¶ÇÕÇϸç, IME¸¦ »ç¿ëÇϱâ
À§Çؼ´Â À©µµ¿ìÀÇ ¸Þ½ÃÁö ½Ã½ºÅÛÀ» ÀÌ¿ëÇØ¾ß ÇÕ´Ï´Ù.
¼ø¼ö Çѱ۸¸ Ãâ·ÂÇÏ´Â °æ¿ì¿¡ À©µµ¿ì ¸Þ½ÃÁö WM_IME_STARTCOMPOSITION,
WM_IME_COMPOSITION, WM_CHAR ¼¼ °¡Áö¸¸ »ç¿ëÇÕ´Ï´Ù. WM_IME_STARTCOMPOSITION
¸Þ½ÃÁö´Â ÇÑ±Û ÀÔ·ÂÀ» ¸· ½ÃÀÛÇÒ ¶§, WM_IME_COMPOSITION´Â ±ÛÀÚ¸¦ Á¶ÇÕ ÁßÀÏ
¶§, WM_CHAR´Â ÇÑ±Û Á¶ÇÕ À̿ܿ¡ ¾Æ½ºÅ° Äڵ尡 ÀÔ·ÂµÉ ¶§ 󸮸¦ ÇÕ´Ï´Ù.
¸Þ½ÃÁö ÇÁ·Î½ÃÀú(Message Procedure) ÇÔ¼ö¿¡¼ ¸ÕÀú ´ÙÀ½°ú
°°ÀÌ WM_IME_STARTCOMPOSITION¿¡¼ Á¶ÇÕÀÌ ½ÃÀÛ µÆÀ½À» ÀÎÁö ÇÕ´Ï´Ù. Äڵ忡¼´Â ¾Æ¹« Àϵµ ¾È Çϰí Àִµ¥ ÇÊ¿äÇÏ´Ù¸é ¹º°¡¸¦ ³Ö¾îÁÖ´Â °Íµµ ÁÁ½À´Ï´Ù.
LRESULT CLcHangul::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
¡¦
INT len
= 0;
HIMC hIMC=
0;
WPARAM wLo = LOWORD(wParam);
if(WM_IME_STARTCOMPOSITION == uMsg)
return TRUE;
´ÙÀ½À¸·Î ±ÛÀÚ¸¦ Á¶ÇÕ ÁßÀÎ WM_IME_COMPOSITION ¸Þ½ÃÁö
ó¸® ÀÔ´Ï´Ù. ±ÛÀÚ°¡ Á¶ÇÕ Áß ¶Ç´Â Á¶ÇÕÀÌ ¿Ï·á µÇ¸é ÀÌ ¸Þ½ÃÁö·Î ¿É´Ï´Ù. ¸ÕÀú IME ÇÚµéÀ» ImmGetContext()ÇÔ¼ö¸¦
ÅëÇØ¼ °¡Á®¿É´Ï´Ù. ¹°·Ð ´Ù »ç¿ëÇßÀ¸¸é ImmReleaseContext()
ÇÔ¼ö·Î ÀÚ¿øÀ» ¹Ý³³ ÇØ¾ß ÇÕ´Ï´Ù.
else if(WM_IME_COMPOSITION == uMsg) // ±Û¾¾ Á¶ÇÕ Áß
¡¦
hIMC
= ImmGetContext(hWnd); // Get IME Handle
¼ø¼»óÀ¸·Î ±ÛÀÚÀÇ Á¶ÇÕ ÁßÀÎ °ÍÀ» ¸ÕÀú ó¸® ÇÏÁö ¾Ê°í Á¶ÇÕÀÌ
¿Ï·áµÈ °ÍÀ» ¸ÕÀú ó¸®ÇÕ´Ï´Ù. ¿Ï·á¿¡ ´ëÇÑ ÆÇ´ÜÀº LPARAM °ªÀ»
GCS_RESULTSTR °ªÀ¸·Î ºñÆ® ¿¬»êÀ» ÅëÇØ¼ ÆÇº°ÇÕ´Ï´Ù. ¿Ï·áµÈ
¹®ÀÚ¿Àº ImmGetCompositionString() ÇÔ¼ö¸¦ µÎ ¹ø »ç¿ëÇØ¼ ¾ò´Âµ¥ ¸ÕÀú IME ÇÚµé°ú GCS_RESULTSTR Àμö ¸¸À» ³Ö¾î¼ ¹®ÀÚ¿ÀÇ
±æÀ̸¦ ¾ò¾î ¿À°í ´ÙÀ½À¸·Î ÀÌ ±æÀÌ¿Í ¹öÆÛ¸¦ ¿¬°áÇØ¼ ¹öÆÛ¸¦ ÅëÇØ¼ ¹®ÀÚ¿À» °¡Á® ¿É´Ï´Ù.
if (lParam & GCS_RESULTSTR)
¡¦
len
= ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0); // Á¶ÇÕÀÌ ¿Ï·áµÈ ±æÀÌ
if( 0 < len)
{
ImmGetCompositionString(hIMC, GCS_RESULTSTR, "¿Ï¼ºµÈ ¹®ÀÚ¿ ¹öÆÛ", len);
¡¦
Á¶ÇÕ ÁßÀÎ ¹®ÀÚ¿µµ ȸ鿡 Ãâ·ÂÀ» ÇØ¾ß ÇÕ´Ï´Ù. LPARAM °ª¿¡ GCS_COMPSTR °ªÀ¸·Î ºñÆ® ¿¬»êÀ» Çϸé Á¶ÇÕ ÁßÀÎÁö ¾Ë ¼ö ÀÖ½À´Ï´Ù. ¾ÕÀÇ
¿Ï·áµÈ ¹®ÀÚ¿À» ¾òµíÀÌ ImmGetCompositionString() ÇÔ¼ö¸¦ µÎ ¹ø »ç¿ëÇØ¼ Á¶ÇÕ ÁßÀÎ
¹®ÀÚ¿À» ¾ò¾î ¿É´Ï´Ù. ÀÌ ¶§´Â GCS_RESULTSTR ´ë½Å
GCS_COMPSTR °ªÀ» »ç¿ëÇØ¾ß ÇÕ´Ï´Ù.
±ÛÀÚ¸¦ ¹é ½ºÆäÀ̽º(Back Space) Ű·Î Áö¿ö¼ Á¶ÇÕ ÁßÀÎ ±æÀ̸¦ 0À¸·Î ¸¸µé ¶§°¡ ÀÖ½À´Ï´Ù. ÀÌ °æ¿ì¿¡´Â Á¶ÇÕÁßÀÎ ¹öÆÛ¸¦ ¸»²ûÈ÷ ºñ¿ì´Â
°ÍÀÌ ÁÁ½À´Ï´Ù.
else if (lParam & GCS_COMPSTR)
¡¦
len
= ImmGetCompositionString(hIMC, GCS_COMPSTR, NULL, 0); // Á¶ÇÕÁßÀÎ ±æÀÌ
if(0==len) // Á¶ÇÕ Áß¿¡ Back space°¡ ¿Â °æ¿ì
EraseWord();
else
ImmGetCompositionString(hIMC, GCS_COMPSTR, m_sWrd, len);
ÇÑ±Û ÀÔ·ÂÀ» ´Ù ó¸® ÇßÀ¸¸é
IME ÇÚµéÀ» ¹ÝȯÇÕ´Ï´Ù.
ImmReleaseContext(hWnd, hIMC);
Çѱ۰ú °°ÀÌ ¿µ¹®µµ Ãâ·ÂÇØ¾ß ÇϹǷΠIME ÀÛµ¿ÀÌ ¾Æ´Ò ¶§ ¾Æ½ºÅ° ¹®Àڵ鿡 ´ëÇØ¼ WM_CHAR ¸Þ½ÃÁö¿¡¼
ó¸®ÇÕ´Ï´Ù.
else if(WM_CHAR == uMsg)
¡¦
if(wParam>=32 && wParam<127)
m_sStr[strlen(m_sStr)] = wParam;
¾Æ½ºÅ° ¹®ÀÚµµ 0~31 ¹ø±îÁö´Â
Åë½Å, Á¦¾î¿¡ °ü·ÃµÈ ¹®ÀÚÀÔ´Ï´Ù. À̵éÀº ȸ鿡 Ãâ·ÂÇÒ Çʿ䰡
¾øÀ¸¹Ç·Î 32~126 »çÀÌÀÇ ¹®ÀÚ¸¸ Ãâ·ÂÇÏ°Ô ÇÕ´Ï´Ù.

<IME ÇѱÛ: daux04_IME_hangul.zip>
¿¹Á¦ daux04_IME_hangul.zipÀº
IME¸¦ »ç¿ëÇØ¼ ÇѱÛÀ» Ãâ·ÂÇÏ´Â ¿¹Á¦ ÀÔ´Ï´Ù. ÇѱÛÀ» ÀÔ·ÂÇÏ°í ¿£ÅÍ Å°¸¦ ´©¸£¸é À©µµ¿ì
ŸÀÌÆ²¿¡ ÇØ´ç ¹®ÀÚ¿À» Ãâ·ÂÇØ ÁÝ´Ï´Ù. ´Ù½Ã ÇÑ±Û ÀÔ·ÂÀ» »ç¿ëÇÏ·Á¸é ¿£ÅÍ Å°¸¦ ÇÑ ¹ø ´õ ´©¸£¸é µË´Ï´Ù.
3.5 Texture
3.5.1 ¹Ó¸Ê »ç¿ë ºñ±³
ÅØ½ºÃ³¸¦ ÆÄÀÏ¿¡¼ ÀÐ¾î ¿À´Â ÇÔ¼ö´Â D3DXCreateTextureFromFileEx()
ÇÔ¼ö¿Í D3DXCreateTexture-FromFile() ÇÔ¼ö¸¦ °¡Àå ¸¹ÀÌ »ç¿ëÇϰí ÀÖ½À´Ï´Ù. ¾Õ¼ 2D °ÔÀÓ °ÀÇ¿¡¼ 2D °ÔÀÓÀÇ
ÅØ½ºÃ³´Â D3DXCreateTextureFromFileEx() ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù°í Çß½À´Ï´Ù.
µµ¿ò¸»À» º¸¸é D3DXCreateTextureFromFile() ÇÔ¼ö´Â
D3DXCreateTextureFromFileEx(pDevice, pSrcFile, D3DX_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT,
D3DX_DEFAULT, 0, NULL, NULL, ppTexture)¿Í °°´Ù°í µÇ¾î ÀÖ½À´Ï´Ù.
ÅØ½ºÃ³ÀÇ ÇÊÅ͸µ¿¡¼ ¿ì¸®´Â ¹Ó¸ÊÀ» ¹è¿ü½À´Ï´Ù. ¹Ó¸ÊÀº Anti-AliasingÀ» À§ÇØ ¿øº» ÅØ½ºÃ³¸¦ 2ÀÇ ½Â¼ö·Î ÇÏÀ§ ÅØ½ºÃ³ÀÇ
Å©±â´Â 1/4¾¿ ÁÙ¿© ³ª°¡¸é¼ ¸¸µç´Ù°í Çß½À´Ï´Ù. ¿øº» ÅØ½ºÃ³¿Í
ÇÏÀ§ ÅØ½ºÃ³·Î ÀÎÇØ ´Ã¾î³ ¸Þ¸ð¸®´Â µîºñ ¼ö¿ÀÌ µÇ¾î ´ë·« ´ÙÀ½°ú °°ÀÌ °è»êÀÌ µË´Ï´Ù.
~ 1.33
ÀÌ °è»êÀº ¾à 33 %ÀÇ ¸Þ¸ð¸® Áõ°¡¸¦ º¸À̰í ÀÖ½À´Ï´Ù. ½ÇÁ¦·Îµµ ºñ½ÁÇÑ °á°ú°¡ µÇ´ÂÁö »ìÆì º¾½Ã´Ù.
daux05_texture1_mipmap.zip
´Â ¹Ó¸Ê°ú ¹Ó¸Ê ·¹º§À» 1·Î ÇÒ ¶§¿¡ »ç¿ëÇÏ´Â ¸Þ¸ð¸®¸¦ ºñ±³ Çϰí ÀÖ½À´Ï´Ù. ¸Þ¸ð¸® ºñ±³¸¦ À§Çؼ MEMORYSTATUS ŸÀÔÀÇ Àü¿ª º¯¼ö¸¦
¼³Á¤Çϰí ÅØ½ºÃ³¸¦ »ý¼ºÇϱâ Àü¿¡ ÀÌ Àü¿ª º¯¼ö¿¡ ½Ã½ºÅÛÀÇ »ç¿ë ¸Þ¸ð¸®¸¦ GlobalMemoryStatus() ÇÔ¼ö¸¦
ÀÌ¿ëÇØ¼ ±â·ÏÇÕ´Ï´Ù.
MEMORYSTATUS g_MmSt; // Àü¿ª º¯¼ö
¡¦
GlobalMemoryStatus(&g_MmSt);
´ë·« 100 Á¤µµ D3DXCreateTextureFromFileEx(),
D3DXCreateTextureFromFile() ÇÔ¼ö·Î °°Àº ÆÄÀÏÀ» È£ÃâÇØ¼ ÀÌ µÑÀÇ ¸Þ¸ð¸® »ç¿ëÀ» ºñ±³ÇØ º¸¸é ¹Ó¸Ê ·¹º§À» Ç®¾î
³õÀ¸¸é ¾à 30%Á¤µµ Áõ°¡ Çϰí ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.
3D´Â ¹Ó¸ÊÀÌ ÇÊ¿äÇÏÁö¸¸ 2D´Â
¹Ó¸ÊÀÌ ÀüÇô Çʿ䰡 ¾ø½À´Ï´Ù. µû¶ó¼ ¹Ó¸Ê ·¹º§À» Á¶Á¤ÇÒ ¼ö ÀÖ´Â D3DXCreateTextureFromFileEx()
ÇÔ¼ö¸¦ »ç¿ëÇϸé D3DXCreateTextureFrom-File() ÇÔ¼ö¸¦ »ç¿ëÇÒ ¶§º¸´Ù
¸Þ¸ð¸®¸¦ 30% Á¤µµ Àý¾àÇÒ ¼ö ÀÖ°Ô µË´Ï´Ù.
3.5.2 ÅØ½ºÃ³ ÆÄÀÏ Merge
ÆÄÀÏÀÇ º¸È£¸¦ À§ÇØ ¸ÓÁö(Merge: ÇÕº´)ÇÒ Çʿ䵵 ÀÖ½À´Ï´Ù. °£´ÜÇÑ ¸ÓÁö ¹æ¹ýÀº Àüü ÅØ½ºÃ³ÀÇ ¼ýÀÚ¸¦ ÆÄÀÏ¿¡
±â·ÏÇÏ°í ¼øÂ÷ÀûÀ¸·Î ÆÄÀÏÀÇ À̸§, Å©±â, ½ÃÀÛ Æ÷ÀÎÅÍ, Á¾·á Æ÷ÀÎÅÍ ÅØ½ºÃ³ µ¥ÀÌÅ͸¦ ¹Ýº¹Çؼ ±â·ÏÇÕ´Ï´Ù.

<¿©·¯ °¡Áö ¸ÓÁö ¹æ¹ý>
Á» ´õ Çâ»óµÈ ±â¼úÀº ÆÄÀÏÀÇ À̸§, Å©±â, ½ÃÀÛÆ÷ÀÎÅÍ, Á¾·á Æ÷ÀÎÅÍ Á¤º¸¸¦ ¸ÕÀú ±â·ÏÇÑ ÈÄ¿¡ ÅØ½ºÃ³ÀÇ ÆÄÀÏÀ»
Çì´õ¿¡ ±â·ÏµÈ ¼ø¼´ë·Î ¸ÓÁö ÇÕ´Ï´Ù. ¾Æ´Ï¸é ÅØ½ºÃ³ ÆÄÀÏÀ» ¸ÕÀú ¸ÓÁö ÇÑ ÈÄ¿¡ ¸¶Áö¸·¿¡ ÆÄÀÏ Á¤º¸¸¦
±â·ÏÇÏ´Â ¹æ¹ýµµ ÀÖ½À´Ï´Ù.
¾î¶² ¹æ½ÄÀ¸·Î ¸ÓÁö¸¦ ÇÏµç ´Ù½Ã ÀÌ ÆÄÀϵéÀ» Ç®¾î¼ ÅØ½ºÃ³¸¦ »ý¼ºÇØ¾ß ÇÕ´Ï´Ù.
±×·±µ¥ ÅØ½ºÃ³¸¦ Àӽà Æú´õ¿¡ Ç®¾î¼ D3DXCreateTextureFromFile(0 ÇÔ¼ö
µîÀ¸·Î ÅØ½ºÃ³¸¦ »ý¼ºÇÏ°Ô µÇ¸é ÇÏµå µð½ºÅ©¸¦ »ç¿ëÇÏ°Ô µÇ¾î ÆÄÀÏÀÌ ¸¹Àº °æ¿ì ·Îµù¿¡ ½Ã°£ÀÌ ¸¹ÀÌ µì´Ï´Ù.
D3D´Â ÆÄÀÏ À̿ܿ¡ ¸Þ¸ð¸®, ¸®¼Ò½º¿¡¼
ÅØ½ºÃ³¸¦ »ý¼ºÇÏ´Â ÇÔ¼ö°¡ ÀÖ½À´Ï´Ù.
D3DXCreateTextureFromFileInMemoryEx(),D3DXCreateTextureFromFileInMemory()
ÇÔ¼ö´Â ¸Þ¸ð¸®¿¡¼ ÅØ½ºÃ³¸¦ »ý¼ºÇϸç, D3DXCreateTextureFromResourceEx(),D3DXCreateTextureFromResource()
ÇÔ¼ö´Â ÇÁ·Î±×·¥ÀÇ ¸®¼Ò½º¿¡¼ ÅØ½ºÃ³¸¦ »ý¼ºÇÕ´Ï´Ù.
daux05_texture2_merge_file.zip˼
¸ÓÁö¸¦ ÇÑ ÈÄ¿¡ 3DXCreateTextureFromFileInMemoryEx() ÇÔ¼ö·Î ¸Þ¸ð¸®¿¡¼
ÅØ½ºÃ³¸¦ »ý¼ºÇÏ´Â ¿¹Á¦ ÀÔ´Ï´Ù.
¸ÓÁö¸¦ À§Çؼ °¢ ÆÄÀÏ¿¡ ´ëÇÑ Á¤º¸¸¦ ±â·ÏÇÒ ¼ö ÀÖµµ·Ï ´ÙÀ½°ú °°ÀÌ ÆÄÀÏ À̸§,
Å©±â, ½ÃÀÛ Æ÷ÀÎÅÍ, ³¡ Æ÷ÀÎÅ͸¦ ÀúÀåÇÒ ¼ö
Àִ Ŭ·¡½º°¡ ÇÊ¿äÇÕ´Ï´Ù.
struct MrgTx
{
char sFile[256]; // File Name
int iSize; // File Size
int iBgn; // Starting point
int iEnd; // End point
};
typedef std::vector<MrgTx* > lsTx;
¸ÓÁö¸¦ ½ÇÇàÇÏ¸é ÆÄÀÏÀÇ Á¤º¸¸¦ ¸ÕÀú ¸ðÀ¸°í ±× ´ÙÀ½À¸·Î ÇϳªÀÇ ÆÄÀÏ¿¡ ±â·ÏÀ» ÇÕ´Ï´Ù. ¿©±â¼´Â ¾ÕÀÇ ¸ÓÁö ¹æ¹ý ±×¸² Áß¿¡ °¡¿îµ¥ ºÎºÐ ±×¸²Ã³·³ ÆÄÀÏÀÇ °³¼ö, ÆÄÀÏÀÇ
Á¤º¸, ÆÄÀÏ ³»¿ëÀ» ±â·ÏÇϰڽÀ´Ï´Ù. CMain::MergeFile()
ÇÔ¼ö°¡ ´ÙÀ½°ú °°ÀÌ À̸¦ ±¸ÇöÇϰí ÀÖ½À´Ï´Ù.
¸ÕÀú ÆÄÀÏÀÇ Á¤º¸¸¦ Àоî¿Í ¸ÓÁö Á¤º¸¸¦ °¡Áö°í ÀÖ´Â º¤ÅÍ¿¡ ³Ö½À´Ï´Ù.
void CMain::MergeFile()
¡¦
lsTx vTx;
// 1. Merge File Information
vTx.push_back(new MrgTx("Texture/seatosky1.jpg"));
vTx.push_back(new MrgTx("Texture/seatosky2.jpg", vTx[vTx.size()-1]));
¡¦
´ÙÀ½À¸·Î ¸ÓÁö ÆÄÀÏÀ» »ý¼ºÇÏ°í ÆÄÀÏÀÇ °³¼ö¸¦ ±â·ÏÇÑ ´ÙÀ½, º¤ÅÍ¿¡ ÀúÀåµÇ¾î ÀÖ´Â ÆÄÀϵéÀÇ Á¤º¸¸¦ ±â·ÏÇÕ´Ï´Ù.
int iN=vTx.size();
BYTE* pSrc;
FILE* fpDst = fopen("Texture/Merge.mrg", "wb");
¡¦
// 2. Write File Counter
fwrite(&iN, 1, sizeof(iN), fpDst);
// 3. Write File Information
for(i=0; i<iN; ++i)
{
MrgTx* pTxF = vTx[i];
fwrite(pTxF->sFile, 1, sizeof(pTxF->sFile),
fpDst);
¡¦
}
´ÙÀ½À¸·Î ÆÄÀÏÀ» Åë°·Î Àоî¿Í¼ ¸ÓÁö ÆÄÀÏ¿¡ ±â·ÏÇÕ´Ï´Ù.
// 5. Write File Data
for(i=0; i<iN; ++i)
{
MrgTx* pTxF = vTx[i];
fpSrc
= fopen(pTxF->sFile,
"rb");
pSrc
= new BYTE[pTxF->iSize];
fread(pSrc, 1, pTxF->iSize, fpSrc);
fclose(fpSrc);
fwrite(pSrc, 1, pTxF->iSize, fpDst);
¡¦
}
ÀÌ·¸°Ô ¸ÓÁö ÆÄÀÏÀ» ¸¸µé¾úÀ¸¸é À̰ÍÀ» ´Ù½Ã Ç®¾î¼ È®ÀÎÇØ ºÁ¾ß ÇÕ´Ï´Ù. CMain::GetFileData()
ÇÔ¼ö´Â new ¿¬»êÀÚ·Î Àӽà ¹öÆÛ¸¦ ¸¸µé°í ¸ÓÁö ÆÄÀÏ¿¡¼ ÆÄÀÏ µ¥ÀÌÅ͸¦ Àоî¿À´Â ¿ªÇÒÀ»
ÇÕ´Ï´Ù.
BYTE* CMain::GetFileData(int idx, int* iSize)
¡¦
FILE* fp = fopen("Texture/Merge.mrg", "rb");
// 3. Read File Information
for(i=0; i<iN; ++i)
{
MrgTx* pTxF = new MrgTx;
vTx.push_back(pTxF);
pTxF =
vTx[i];
fread(pTxF->sFile, 1, sizeof(pTxF->sFile),
fp);
fread(&pTxF->iSize, 1, sizeof(pTxF->iSize),
fp);
¡¦
}
MrgTx* pTxF = vTx[idx];
// 4. Move File Point
fseek(fp, pTxF->iBgn, SEEK_SET);
¡¦
// 6. Read File Data
pBuf = new BYTE[pTxF->iSize];
fread(pBuf, 1, pTxF->iSize, fp);
fclose(fp);
¡¦
return pBuf;
CMain::GetFileData() ÇÔ¼ö·Î ÀÐÀº ÆÄÀÏÀÇ µ¥ÀÌÅÍ¿¡¼
D3DXCreateTextureFromFileInMemoryEx()ÇÔ¼ö·Î ÅØ½ºÃ³¸¦ »ý¼ºÇÕ´Ï´Ù. ÀÌ ¿¹´Â CMain::FrameMove()¿¡ ±¸ÇöµÇ¾î ÀÖ½À´Ï´Ù.
HRESULT CMain::FrameMove()
¡¦
int iIdx = rand()%10;
INT iSize=0;
BYTE* pSrc = GetFileData(iIdx,
&iSize);
¡¦
D3DXCreateTextureFromFileInMemoryEx(¡¦);
¡¦
Àüü ÄÚµå´Â daux05_texture2_merge_file.zip¸¦
Âü°í Çϱ⠹ٶø´Ï´Ù.

< ÇÕº´ÇÑ ÆÄÀÏ¿¡¼ ÅØ½ºÃ³ »ý¼º: daux05_texture2_merge_file.zip>
3.5.3 Private Data
Private Data´Â ´Ü¾î ¶æ ±×´ë·Î ³»ºÎÀûÀÎ µ¥ÀÌÅÍ·Î D3D¿¡¼ IDirect3DResource9,
IDirect3DBaseTexture9, IDirect3DCubeTexture9, IDirect3DTexture9,
IDirect3DVolumeTexture9, IDirect3DIndexBuffer9, IDirect3DVertexBuffer9 µîÀÇ
ÀÚ¿ø¿¡ ¾î¶² ¸ñÀûÀ» À§ÇØ º¸Á¶ÀûÀ¸·Î ÇÒ´çÇÑ ÀÚ¿øÀ» ÀúÀåÇÏ´Â °ø°£ÀÔ´Ï´Ù.
¿¹¸¦ µé¾î D3D´Â ÅØ½ºÃ³¸¦ 2ÀÇ
½Â¼ö·Î ¸¸µé¾î ¹ö¸³´Ï´Ù. 2ÀÇ ½Â¼ö°¡ ¾Æ´Ñ ÅØ½ºÃ³´Â ¿øº» Á¤º¸¸¦ ¾î¶² ½ÄÀ¸·ÎµçÁö ÀúÀåÀ» ÇØ¾ß¸¸ ·»´õ¸µ¿¡¼
Á¤È® À̹ÌÁö ¿µ¿ªÀ» Ç¥½ÃÇÒ ¼ö ÀÖ½À´Ï´Ù. ±×·±µ¥ ¸¸¾à ¿øº» Á¤º¸¸¦ ³Ñ±æ ¼ö ¾ø´Â »óȲÀÌ ÀÖ´Ù¸é ¾î¶»°Ô
ÇÒ±î¿ä?
¹°·Ð ¿øº» À̹ÌÁö Á¤º¸¸¦ ¹ÞÀ» ¼ö ÀÖµµ·Ï ½Ã½ºÅÛÀ» ¼öÁ¤ÇØ¾ß ÇÏ´Â °ÍÀÌ °¡Àå Çö¸íÇÑ ¹æ¹ýÀÔ´Ï´Ù. ÀÌ ¸¶ Àúµµ ¾ÈµÉ ¶§´Â Private Data¸¦ »ç¿ëÇÕ´Ï´Ù.
´ÙÀ½°ú °°ÀÌ ÅØ½ºÃ³¸¦ »ý¼ºÇÏ°í ¿øº» À̹ÌÁöÀÇ Á¤º¸¸¦ new ¿¬»êÀÚ·Î
µ¿Àû ÇÒ´çÇÑ ´ÙÀ½¿¡ ÇØ´ç ÅØ½ºÃ³¿¡ SetPrivateData() ÇÔ¼ö·Î ¿¬°áÇÕ´Ï´Ù.
GUID IID_ILcTexInfo ={0x85c31227, 0x3de5, 0x4f00, 0x9b
, 0x3a, 0xf1, 0x1a, 0xc3, 0x8c, 0x18, 0xb5};
INT LcUtil_TextureLoad(¡¦, LPDIRECT3DTEXTURE9* pTx, TCHAR* sFile,¡¦)
¡¦
D3DXIMAGE_INFO* pImg = new D3DXIMAGE_INFO;
¡¦
D3DXCreateTextureFromFileEx(pDev,
sFile, ¡¦, pImg, NULL, pTx);
(*pTx)->SetPrivateData( IID_ILcTexInfo,
&pImg, sizeof(pImg), 0);
¡¦
ÀÌ·¸°Ô ¿¬°áÇÏ°í ³ª¼ ´ÙÀ½°ú °°ÀÌ GetPrivateData() ÇÔ¼ö¸¦
ÅëÇØ¼ À̹ÌÁö Á¤º¸¸¦ °¡Á®¿Í »ç¿ëÇÕ´Ï´Ù.
HRESULT CMain::Render()
¡¦
DWORD dSize=
0;
DWORD dData=
0;
D3DXIMAGE_INFO* pData;
m_pTex1->GetPrivateData(IID_ILcTexInfo,
&dData, &dSize);
pData = (D3DXIMAGE_INFO*)dData;
RECT rc1={0,0, pData->Width, pData->Height};
m_pd3dSprite->Draw(m_pTex1, &rc1, ¡¦);
¡¦
ÀÌ·¸°Ô µ¿Àû ÇÒ´çÀ¸·Î ¸¸µç Private Data´Â ÇÁ·Î±×·¥ ÇØÁ¦ÇÒ
¶§ °°ÀÌ ¼Ò¸ê½ÃÄÑ¾ß ÇÏ´Â °ÍÀº ´ç¿¬ÇÕ´Ï´Ù. ¶ÇÇÑ FreePrivateData()
ÇÔ¼ö¸¦ È£ÃâÇØ¼ Private Data »ç¿ëÀ» ÇØÁ¦ÇÕ´Ï´Ù.
HRESULT CMain::Destroy()
¡¦
DWORD dData=
0;
D3DXIMAGE_INFO* pData;
m_pTex1->GetPrivateData( IID_ILcTexInfo,
&dData, &dSize);
m_pTex1->FreePrivateData(IID_ILcTexInfo);
pData = (D3DXIMAGE_INFO*)dData;
delete pData;
Àüü ÄÚµå´Â daux05_texture3_privatedata.zip ÆÄÀÏÀ»
Âü°í Çϱ⠹ٶø´Ï´Ù.

<Private Data: daux05_texture3_privatedata.zip>
SetPrivateData() ÇÔ¼ö¸¦ È£ÃâÇÒ ¶§ ù ¹øÂ° Àμö´Â ±¸À̵å
¹øÈ£(Guid Number) ¶ó´Â °ªÀ¸·Î À©µµ¿ì ½Ã½ºÅÛ¿¡¼ ¸¸µç À¯ÀÏ °ªÀ» º¸ÀåÇÏ´Â ¼öÀÔ´Ï´Ù. Visual Studio´Â ±¸ÀÌµå ¹øÈ£¸¦ »ý¼ºÇÏ´Â ÇÁ·Î±×·¥ÀÌ
GuidGen.exe ¶Ç´Â uuidGen.exe °¡ ÀÖ½À´Ï´Ù. 2005 ¹öÀüÀÇ GuidGen.exe¸¦ ã¾Æ¼ ½ÇÇàÇÏ¸é ´ÙÀ½ À©µµ¿ì°¡
½ÇÇàÀÌ µÇ¸ç Copy ¹öưÀ» ´·¯ ±¸ÀÌµå ¹øÈ£¸¦ º¹»ç ÇÕ´Ï´Ù. New
GUID ¹öưÀ» ´©¸¦ ¶§¸¶´Ù Àü¼¼°è¿¡¼ Çϳª ¹Û¿¡ ¾ø´Â ¹øÈ£¸¦ ¸¸µé¾î ³À´Ï´Ù.

<GuidGen.exe>
ÀÌ ¹øÈ£¸¦ º¹»ç ÇØ¼ ´ÙÀ½°ú °°ÀÌ GUID ±¸Á¶Ã¼¿¡ ä¿ö¼ SetPrivateData(), GetPrivateData()
ÇÔ¼ö È£ÃâÀÇ Àμö·Î »ç¿ëÇÕ´Ï´Ù.
GUID IID_ILcTexInfo ={0x85c31227, 0x3de5, 0x4f00
, 0x9b, 0x3a, 0xf1, 0x1a, 0xc3, 0x8c, 0x18, 0xb5};
3.5.4 Targa ¿Í PNG
D3D´Â DXSDK¿¡¼
À̹ÌÁö¸¦ ºÒ·¯¿À´Â ÇÔ¼ö°¡ Áö¿øÀÌ ÀÖ¾î À̹ÌÁö¸¦ ÀÐ°í ¾²´Â ÀϵéÀ» °í¹Î ¾È ÇØµµ µË´Ï´Ù. ±×·±µ¥ ¸¸¾à D3D·Î ¸ð¹ÙÀÏ µîÀÇ ±â±â¿¡ À̽ÄÇϱâ À§ÇÑ Emulator¸¦ ¸¸µç´Ù°í
ÇÑ´Ù¸é ÀÌ ±â±âÀÇ È¯°æ¿¡ ¸Â´Â À̹ÌÁö Çü½ÄÀ¸·Î ÄÚµùÀ» ÇØ¾ß ÇÕ´Ï´Ù.
¿©·¯ À̹ÌÁö Æ÷¸Ë Áß¿¡¼ °¡Àå ¸¹ÀÌ »ç¿ëÇÏ´Â Æ÷¸ËÀº Targa Çü½ÄÀÔ´Ï´Ù. Targa ÆÄÀÏÀº ÀÐ°í ¾²±â°¡ Æí¸®Çؼ ´ëºÎºÐÀÇ °ÔÀÓ ÇÁ·Î±×·¡¹Ö Ã¥¿¡ ¼Ò°³°¡ µÇ¾î ÀÖ½À´Ï´Ù. D3D¸¦ °øºÎÇÏ´Â ¿©·¯ºÐµµ Targa ÆÄÀÏ ¸¸ÅÀº DXSDK ÇÔ¼ö¸¦ »ç¿ëÇÏÁö ¾Ê°í ÀÐ°í ¾²´Â ¹ýÀ» ³ªÁß¿¡¶óµµ ¿¬½ÀÇϱ⠹ٶø´Ï´Ù.
daux05_texture4_ToTarga.zip
ÆÄÀÏÀº PNG ÆÄÀÏÀ» D3D ÇÔ¼ö·Î ÀÐÀº ÈÄ¿¡
¼ÇǽºÀÇ Çȼ¿À» ¾ò¾î¿Í Targa·Î ÀúÀåÇÏ´Â ¿¹Á¦ ÀÔ´Ï´Ù. TargaÀÇ
ÀÐ°í ¾²´Â ¹æ¹ýÀº °ÅÀÇ ÀÏÁ¤ÇÕ´Ï´Ù. µû¶ó¼ ¼Ò½º Äڵ常 º¸´õ¶óµµ ´©±¸³ª ½±°Ô ÀÌÇØ ÇÒ ¼ö ÀÖ½À´Ï´Ù. ±×·¡¼ Targa¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ¼³¸íÀº »ý·«Çϰí ÁÖÀÇÁ¡ Á¤µµ¸¸ º¸°Ú½À´Ï´Ù.
Targa ÆÄÀÏÀ» Àд ¹æ¹ýÀº °íÁ¤ÀÌ µÇ¾î ÀÖ¾î¼ ¾î¶² Äڵ带 ¾ò´õ¶óµµ
°ÅÀÇ °°Àº ¹æ½ÄÀ¸·Î ±¸¼ºµÇ¾î ÀÖ½À´Ï´Ù. ±×·±µ¥ ÁÖÀÇÇÒ Á¡Àº Çȼ¿À» ÀÐ¾î ¿À°í ³ª¼ ÀÌ Çȼ¿ÀÌ 24ºñÆ® À̸é 32 ºñÆ®·Î ¹Ù²Ù¾î »ç¿ëÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù.
´ÙÀ½ ÄÚµåÀÇ for ¹®¿¡¼ ÀÌ·¯ÇÑ ÀÏÀ» ó¸®Çϰí ÀÖ½À´Ï´Ù.
INT LoadTGAFile()
¡¦
fp = fopen(filename, "rb");
¡¦
// read bit depth
fread(&ImgBit, sizeof(BYTE), 1, fp);
¡¦
// colormode -> 3 = BGR, 4 = BGRA
colorMode = ImgBit / 8;
// bgr ->bgra
if(3
== colorMode)
{
BYTE* pPixel4 = new BYTE[ImgWidth * ImgHeight
* 4];
for (INT i = 0; i < imageSize/3; ++i)
{
INT idx1 = i*3;
INT idx2 = i*4;
pPixel4[idx2+0] = pPixel[idx1 + 0];
pPixel4[idx2+1] = pPixel[idx1 + 1];
pPixel4[idx2+2] = pPixel[idx1 + 2];
pPixel4[idx2+3] = 0xFF;
}
¡¦
D3D´Â »ö»ó 32 ºñÆ®ÀÇ
¼ø¼°¡ ³·Àº ¹ÙÀÌÆ®ºÎÅÍ B->G->R->A ¼øÀ¸·Î µÇ¾î ÀÖ½À´Ï´Ù. ¸¸¾à »ö»óÀÇ ¼ø¼°¡ A->R->G->B·Î ±¸¼ºµÇ¾î
ÀÖ´Â ½Ã½ºÅÛ¿¡¼´Â ¾ÕÀÇ ÄÚµå for ¹®¿¡¼ ÀÌ ¼ø¼¸¦ ¹Ù²Ù¾î ÁÖ¸é µË´Ï´Ù.
pPixel4[idx2+3] = pPixel[idx1 + 0];
pPixel4[idx2+2] = pPixel[idx1 + 1];
pPixel4[idx2+1] = pPixel[idx1 + 2];
pPixel4[idx2+0] = pPixel[idx1 + 2] ¶Ç´Â 0xFF;
ÀÌ·¸°Ô Çȼ¿ÀÇ ¼ø¼¸¦ ¹Ù²Ù´Â ÀÏÀº ´Ù¸¥ Ç÷§Æû¿¡ À̽ÄÇÒ ¶§ ¶Ç´Â ÆÄÀÏ Çü½ÄÀÌ ´Ù¸¥ °æ¿ì¿¡ Á¾Á¾ ¹ß»ýÇÕ´Ï´Ù. ´ÙÀ½ÀÇ ¿¹´Â DXSDK ÇÔ¼ö·Î »ý¼ºÇÑ ÅØ½ºÃ³¸¦ Targa°¡ Çü½ÄÀ¸·Î ÀúÀåÇÏ´Â ÇÔ¼ö ÀÔ´Ï´Ù. Çȼ¿À» ÆÄÀÏ¿¡ ÀúÀåÇÒ ¶§
Targa ÆÄÀÏÀº for ¹® ¾È¿¡¼ ARGB Çü½ÄÀ» BGRA·Î ¹Ù²Ù°í ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.
INT SaveTGAFile(¡¦)
¡¦
// ARGB -> BGRA
BYTE *b, *g, *r, *a;
for(int j=0; j<imageHeight; ++j)
{
for(int i=0; i<imageWidth; ++i)
{
BYTE* pData = pPixel +
( (imageHeight-1-j)*RealWidth + i)*4;
a
= pData + 3;
r
= pData + 2;
g
= pData + 1;
b
= pData + 0;
¡¦
fwrite(b, sizeof(BYTE), 1, fp);
fwrite(g, sizeof(BYTE), 1, fp);
fwrite(r, sizeof(BYTE), 1, fp);
fwrite(a, sizeof(BYTE), 1, fp);
}
}
daux05_texture4_ToTarga.zip
ÀÇ ¾ÐÃàÀ» Ç®¸é ´ÙÀ½ ±×¸²ÀÇ ¿ÞÂÊó·³ PNG ÆÄÀÏÀ» ºÒ·¯¿Í¼ Targa·Î ÀúÀåÇÑ ÇÁ·Î±×·¥ Mck.exe°¡ ÀÖ½À´Ï´Ù. PNG ÆÄÀÏÀÇ ¾ÐÃà¿¡ ´ëÇÑ ¾Ë°í¸®Áò°ú ÄÚµå´Â °ø°³µÇ¾î ÀÖ½À´Ï´Ù. ¿À¸¥ÂÊ
±×¸²Àº http://zlib.net/
»çÀÌÆ®¿¡¼ PNG ÆÄÀÏÀÇ ÀÔÃâ·Â Äڵ带 ¾ò¾î¿Í ¶óÀ̺귯¸®¸¦ ¸¸µé¾î DC¿¡ Àû¿ë½ÃŲ ȸéÀÔ´Ï´Ù. wn_56_ReadPng Æú´õ¿¡ Çì´õ, ¶óÀ̺귯¸®, ½ÇÇà ÆÄÀÏ
McApi.exe°¡ ÀÖ½À´Ï´Ù.

< Targa ÆÄÀÏ ÀúÀå°ú
PNG ·Îµå: daux05_texture4_ToTarga.zip>
3.6 Anti-Aliasing
AliasingÀº °íÇØ»óµµ µ¥ÀÌÅͰ¡ ÀúÇØ»óµµ µ¥ÀÌÅÍ·Î »ùÇøµ µÇ´Â
°ÍÀ» AliasingÀ̶ó Çß½À´Ï´Ù. ÀÌ ¹®Á¦¸¦ ÇØ°áÇÏ´Â Anti-AliasingÁß¿¡¼ ¼öÆÛ »ùÇøµ ¶Ç´Â ¸ÖƼ »ùÇøµ 󸮸¦ °£´ÜÈ÷ ¹è¿ü½À´Ï´Ù.
Çϵå¿þ¾î°¡ ¾ó¸¶¸¸ÅÀÇ ¸ÖƼ »ùÇøµ ŸÀÔÀ» Áö¿øÇÏ´ÂÁö ¾Ë¾Æº¸·Á¸é ´ÙÀ½°ú °°ÀÌ ÃÖ´ë °ªºÎÅÍ ¼º°øÇÒ ¶§±îÁö °Ë»çÇϸé
µË´Ï´Ù.
DWORD dQualityLevels;
for(int nType=D3DMULTISAMPLE_16_SAMPLES;
nType>=0;
--nType)
{
if(SUCCEEDED(m_pD3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT
,
D3DDEVTYPE_HAL
,
m_d3dpp.BackBufferFormat
,
TRUE
,
(D3DMULTISAMPLE_TYPE)nType
,
&dQualityLevels)))
{
m_d3dpp.MultiSampleType
= (D3DMULTISAMPLE_TYPE)nType;
m_d3dpp.MultiSampleQuality
= dQualityLevels-1;
break;
}
}
ÀÌ·¸°Ô ãÀº ÈÄ¿¡ µð¹ÙÀ̽º¸¦ »ý¼ºÇÏ¸é µÇ¸ç ÀÚµ¿À¸·Î Anti-aliasingÀÌ
Àû¿ëÀÌ µË´Ï´Ù. ȸéÀÇ Àüȯ¿¡¼ µð¹ÙÀ̽º´Â ¸®¼ÂÀÌ µÇ¹Ç·Î ´ÙÀ½°ú °°ÀÌ
Anti-aliasingÀ» Ȱ¼ºÈ ½ÃÄÑ¾ß ÇÕ´Ï´Ù.
m_pd3dDevice->SetRenderState (D3DRS_MULTISAMPLEANTIALIAS, TRUE);
m_pd3dDevice->SetRenderState (D3DRS_ANTIALIASEDLINEENABLE, TRUE);
Àüü ÄÚµå´Â daux06_antialias1.zipÀ»
Âü°í Çϱ⠹ٶø´Ï´Ù. ´ÙÀ½ ±×¸²Àº Anti-aliasing¿¡
´ëÇÑ ¿¹Á¦ ÀÔ´Ï´Ù. F2, F3 ۸¦ ´©¸£¸é Anti-aliasingÀÇ
ºñȰ¼ºÈ/Ȱ¼ºÈ¸¦ ¼³Á¤ ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¿À¸¥ÂÊ ±×¸²À» º¸¸é Anti-aliasingÀ» Ȱ¼ºÈ ÇÏ¸é ·»´õ¸µ ¼Óµµ°¡ °¨¼ÒµÈ °ÍÀ» º¼ ¼ö ÀÖ½À´Ï´Ù.

<Anti-aliasing: daux06_antialias1.zip, daux06_antialias2.zip>
3.7 ID3DXMesh ¿Í X-file
3.7.1 ID3DXMesh
Tutorial ¿¹Á¦¿Í ÁÖÀüÀÚ, ¿øÅë
µî È®Àå À¯Æ¿¸®Æ¼¸¦ ÅëÇØ¼ ID3DXMeshÀÇ »ç¿ëÀ» ¹è¿ü½À´Ï´Ù.
ID3DXMesh´Â Àå¸éÀÇ ¿¬Ãâ¿¡ ÇÊ¿äÇÑ ±âº»ÀûÀÎ Á¤Á¡ ¹öÆÛ¿Í À妽º ¹öÆÛ¸¦ °¡Áö°í ÀÖ°í, ·»´õ¸µ
¼Óµµ¸¦ ¿Ã¸®±â À§Çؼ »ï°¢ÇüÀÇ À妽º¸¦ ±×·ì(Group)À¸·Î ¹¾î ³õÀº ¼Ó¼º ¹öÆÛ¸¦ °¡Áö°í ÀÖ½À´Ï´Ù.
º¸Åë ÇϳªÀÇ »ï°¢Çü¿¡ ÀçÁú(Material) ¶Ç´Â ÅØ½ºÃ³(°°Àº ´Ü°è(stage)ÀÏ °æ¿ì)´Â 1°³ ¹Û¿¡ ¼³Á¤ÀÌ ºÒ°¡´ÉÇÕ´Ï´Ù. ¸¸¾à ÇϳªÀÇ ·»´õ¸µ ¿ÀºêÁ§Æ®¿¡ ÀçÁúÀÌ
¿©·¯ °³ÀÇ °æ¿ì¶ó¸é °¢ Á¤Á¡À» ÀçÁú¿¡ ¸Â°Ô ºÐ·ùÇØ¾ß ÇÕ´Ï´Ù. ÀÌ·¸°Ô µÇ¸é ÀçÁú¸¸ ´Ù¸¥ °°Àº »ï°¢ÇüÀ̶óµµ
º¹»ç¸¦ ÇØ¾ß ÇÕ´Ï´Ù.
¼Ó¼º ¹öÆÛ´Â ÀçÁúÀÌ ¿©·¯ °³ÀÎ °æ¿ì¿¡ Á¤Á¡ ¹öÆÛ¸¦ °¢°¢ ºÐ¸®ÇÏÁö ¾Ê°í, °¢
ÀçÁú¿¡ µû¸¥ »ï°¢ÇüÀÇ À妽º¸¦ ¸ð¾Æ ³õÀº ÀÚ·á ±¸Á¶ÀÔ´Ï´Ù. ¼Ó¼º ¹öÆÛ¸¦ »ç¿ëÇϸé Á¤Á¡ ¹öÆÛ¿Í À妽º
¹öÆÛ¸¦ ±×´ë·Î À¯ÁöÇÏ¸é¼ ¼·Î ´Ù¸¥ ÀçÁú ¶Ç´Â ÅØ½ºÃ³¸¦ Àû¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.

<¼Ó¼º Å×À̺í, ¼Ó¼º
¹öÆÛ, À妽º ¹öÆÛ, Á¤Á¡ ¹öÆÛ>
ID3DXMesh °´Ã¼¸¦ ·»´õ¸µ ÇÒ ¶§ DrawSubset() ÇÔ¼ö¸¦ È£ÃâÇÑ ÀûÀÌ ÀÖ½À´Ï´Ù. DrawSubset() ÇÔ¼öÀÇ
Àμö¿¡ Àü´ÞÇÏ´Â À妽º°¡ ¼Ó¼º Å×ÀÌºí¿¡ ±â·ÏµÈ À妽º ÀÔ´Ï´Ù. ¼Ó¼º Å×ÀÌºí¿¡´Â ¾ÆÀ̵ð, Face ½ÃÀÛ À妽º, Face °³¼ö, Á¤Á¡ÀÇ ½ÃÀÛ À妽º Á¤Á¡ÀÇ °³¼ö°¡ ±â·ÏµÇ¾î ÀÖ½À´Ï´Ù.
À妽º ¹öÆÛ¸¦ ¸¸µé ¶§ WORD ¶Ç´Â DWORDÇüÀÇ ÀÚ·á ±¸Á¶¸¦ ±×´ë·Î »ç¿ëÇÏÁö ¾Ê°í ´ÙÀ½°ú °°Àº ±¸Á¶Ã¼¸¦ »ç¿ëÇÑ´Ù¸é Face À妽º¿Í ÀÌ ±¸Á¶Ã¼ÀÇ À妽º¸¦ µ¿ÀÏÇÏ°Ô ¸ÂÃâ ¼ö ÀÖ½À´Ï´Ù.
struct VtxIdx
{
WORD a;
WORD b;
WORD c;
};
»ï°¢ÇüÀÇ ¸é(Face)¸¦ ±¸¼ºÇÏ´Â ±¸Á¶Ã¼°¡ ¾ø´Ù¸é ¿©·¯ºÐÀº ÇÁ·Î±×·¥À»
ÀÛ¼ºÇÒ ¶§ °è»êÀ» Àß ÇØ¾ß ÇÕ´Ï´Ù.
¿¬½ÀÀ» À§ÇØ ÅØ½ºÃ³°¡ ¸ÅÇÎ µÈ 6 ¸éü ID3DXMesh °´Ã¼·Î ·»´õ¸µ ÇØº¾½Ã´Ù. ¸ÕÀú ´ÙÀ½ °°Àº ID3DXMesh °´Ã¼¸¦ ¼±¾ðÇÕ´Ï´Ù. ±×¸®°í 6¸é¿¡ ´ëÇØ¼ 6ÀåÀÇ ÅØ½ºÃ³¸¦ ¸ÅÇÎ ÇÏ´Â °ÍÀ¸·Î ÇϰڽÀ´Ï´Ù.
ID3DXMesh* m_pMsh;
INT m_nMtl;
LPDIRECT3DTEXTURE9 m_pTex[6];
´ÙÀ½ ´Ü°è¿¡¼ FaceÀÇ °³¼ö, Á¤Á¡
°³¼ö, FVF µîÀ» D3DXCreateMeshFVF() ÇÔ¼öÀÇ
Àμö·Î Àü´ÞÇÏ°í ¸Þ½¬ °´Ã¼¸¦ »ý¼ºÇÕ´Ï´Ù.
D3DXCreateMeshFVF("Á¤Á¡ÀÇ °³¼ö",
"FaceÀÇ °³¼ö", ¡¦,
FVF, ¡¦,
&m_pMsh);
ÀÌ ÇÔ¼ö´Â ¸Þ½¬ °´Ã¼ÀÇ Á¤Á¡°ú À妽ºÀÇ °ø°£À» ¸¸µì´Ï´Ù. ´ÙÀ½À¸·Î Lock()/Unlock() ÇÔ¼ö·Î Á¤Á¡ ¶Ç´Â À妽ºÀÇ µ¥ÀÌÅ͸¦ º¯°æÇÕ´Ï´Ù.
VtxUV1 pVtxS[24];
pVtxS[ 0] = VtxUV1(-6.F, -6.F, -6.F, 0.f, 0.f);
pVtxS[ 1] = VtxUV1(-6.F, 6.F, -6.F, 0.f, 1.f);
¡¦
VtxIdx pIdxS[12];
pIdxS[ 0] = VtxIdx( 0, 1, 2);
pIdxS[ 1] = VtxIdx( 0, 2, 3);
// Á¤Á¡, À妽º
º¹»ç
VtxUV1* pVtx = NULL;
m_pMsh->LockVertexBuffer(0, (void**)&pVtx);
memcpy(pVtx, pVtxS, sizeof(VtxUV1) * 24);
m_pMsh->UnlockVertexBuffer();
VtxIdx* pIdx = NULL;
m_pMsh->LockIndexBuffer(0, (void**)&pIdx);
memcpy(pIdx, pIdxS, sizeof(VtxIdx) * 12);
m_pMsh->UnlockIndexBuffer();
Á¤Á¡°ú À妽º ¼³Á¤ ¸¸À¸·Îµµ ·»´õ¸µÀº °¡´ÉÇÕ´Ï´Ù. ¸ÅÇÎ ¿©·¯ °³¶ó¸é
´ÙÀ½°ú °°ÀÌ ¼Ó¼º ¹öÆÛÀÇ ³»¿ëÀ» °»½ÅÇÕ´Ï´Ù.
DWORD* attBuf = NULL;
m_pMsh->LockAttributeBuffer(0, &attBuf);
attBuf[ 0] = 0;
attBuf[ 1] = 1;
¡¦
m_pMsh->UnlockAttributeBuffer();
¾Õ¼ À妽º ¹öÆÛ¸¦ ±¸¼ºÇÒ ¶§ VtxIdx¿Í °°Àº ±¸Á¶Ã¼¸¦ »ç¿ëÇÏ´Â
°ÍÀÌ ÁÁ´Ù°í Çß½À´Ï´Ù. »ï°¢Çü¿¡ ´ëÇØ¼ ¼Ó¼º ¹öÆÛ¿¡ ±â·ÏÇÏ´Â À妽º´Â
VtxIdx À妽º¿Í °°½À´Ï´Ù.
¸¶Áö¸· ´Ü°è¿¡¼ ¼Ó¼º ¹öÆÛ¿¡ ÀúÀåµÈ »ï°¢ÇüÀÇ À妽º¿¡ ¸ÂÃß¾î ·»´õ¸µ ¼Óµµ¸¦ À§ÇØ ÃÖÀûȸ¦ ÇÕ´Ï´Ù. ÀÌ ´Ü°è´Â ¼±Åà »çÇ×ÀÌ¸ç ¸¸¾à »ç¿ëÀÚ°¡ ¼Ó¼º ¹öÆÛ¸¦ Àß ±¸¼º Çß´Ù¸é ÇÒ ÇÊ¿ä´Â ¾ø½À´Ï´Ù.
DWORD* pAdjacencyBuf = new DWORD[12 * 3];
m_pMsh->GenerateAdjacency(0.f, pAdjacencyBuf);
m_pMsh->OptimizeInplace(
D3DXMESHOPT_ATTRSORT |
D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE
,
pAdjacencyBuf, 0, 0, 0);
delete [] pAdjacencyBuf;
OptimizeInplace() ÇÔ¼öÀÇ ÃÖÀûÈ ¿É¼ÇÀº ´ÙÀ½°ú °°½À´Ï´Ù.
D3DXMESHOPT_COMPACT: »ç¿ëÇÏÁö ¾Ê´Â Á¤Á¡°ú À妽º¸¦ Áö¿ì°í Àç ±¸¼º ÇÕ´Ï´Ù.
D3DXMESHOPT_ATTRSORT: ¼Ó¼º ¹öÆÛÀÇ ³»¿ëÀ» Âü°íÇØ¼ Face(»ï°¢Çü) Á¤·Ä ÇÕ´Ï´Ù.
D3DXMESHOPT_VERTEXCACHE: Face¸¦ À籸¼ºÇؼ ¹öÅØ½º ij½Ã¿¡ ´ëÇÑ ÀûÁß·üÀ» ³ôÀÔ´Ï´Ù.
D3DXMESHOPT_STRIPREORDER: °¡´ÉÇÑ ÇÑ Ä¿´Ù¶õ ½ºÆ®¸³À¸·Î ±¸¼ºÇϵµ·Ï À妽º¸¦ Àç ±¸¼ºÇÕ´Ï´Ù.
D3DXMESHOPT_IGNOREVERTS: ¹öÅØ½º Á¤º¸´Â ¹«½ÃÇϰí À妽º Á¤º¸¸¸ ÃÖÀûÈ ÇÕ´Ï´Ù
D3DXMESHOPT_DONOTSPLIT: ¼Ó¼ºÀÇ Á¤·Ä Áß¿¡¼ ¼Ó¼º ±×·ì »çÀÌ¿¡ °øÀ¯µÇ°í ÀÖ´Â Á¤Á¡µéÀº ºÐÇÒ ¾È ÇÕ´Ï´Ù.
D3DXMESHOPT_DEVICEINDEPENDENT´Â
Á¤Á¡ ij½ÃÀÇ »çÀÌÁî¿¡ ¿µÇâÀ» ÁÖ¸ç Çϵå¿þ¾î¿¡¼ ¹®Á¦ ¹ß»ýÀ» ¾ø¾Ö±â À§ÇØ µðÆúÆ® Á¤Á¡ ij½Ã »çÀÌÁî°¡ ÁöÁ¤µË´Ï´Ù.
¼Ó¼º Å×À̺íÀÇ ³»¿ëÀ» ¾Ë±â À§Çؼ GetAttributeTable() ÇÔ¼ö¸¦
»ç¿ëÇÕ´Ï´Ù. ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇÏ·Á¸é ¸ÕÀú ´ÙÀ½°ú °°ÀÌ ¸ÕÀú Å×ÀÌºí ¼ö¸¦ °¡Á®¿À°í Å×ÀÌºí ³»¿ëÀ» ±â·ÏÇÒ
¹öÆÛ¸¦ µ¿ÀûÀ¸·Î ¸¸µç ´ÙÀ½ ÀÌ ¹öÆÛ¿Í Å×ÀÌºí ¼ö¸¦ Àμö·Î GetAttributeTable() ÇÔ¼ö¸¦
È£ÃâÇÏ¸é ³»¿ëÀ» °¡Á®¿Ã ¼ö ÀÖ½À´Ï´Ù.
DWORD nNumSubset=0;
hr= m_pMsh->GetAttributeTable(0, &nNumSubset);
D3DXATTRIBUTERANGE* attTable= new D3DXATTRIBUTERANGE[nNumSubset];
hr= m_pMsh->GetAttributeTable(attTable,
&nNumSubset);
delete [] attTable;
m_nMtl = nNumSubset;
Àüü ³»¿ëÀº daux07_mesh01.zipÀ»
Âü°í Çϱ⠹ٶø´Ï´Ù.

<»ç¿ëÀÚ Á¤ÀÇ¿¡ ÀÇÇÑ
ID3DXMesh: daux07_mesh01.zip>
ID3DXMesh¸¦ ÀÌ¿ëÇØ¼ Àå¸éÀ» ¿¬ÃâÇÏÁö ¾Ê°í ¸Þ½¬ µ¥ÀÌÅ͸¦ º¹»çÇØ¼
»ç¿ëÇÒ °æ¿ìµµ ÀÖ½À´Ï´Ù. ÀÌ ¶§ ¸Þ½¬ °´Ã¼ ³»ºÎÀÇ µ¥ÀÌÅ͸¦ °¡Á®¿À±â À§Çؼ ÃÖ¼ÒÇÑ ´ÙÀ½°ú °°Àº Áö¿À¸ÞÆ®¸®
±¸Á¶Ã¼¿Í ¸â¹ö º¯¼ö¸¦ °¡Áö°í ÀÖ¾î¾ß ÇÕ´Ï´Ù.
Áö¿À¸ÞÆ®¸®(Geometry) ±¸Á¶Ã¼´Â ID3DXMesh °´Ã¼ÀÇ Subset°ú 1:1 °ü°èÀÔ´Ï´Ù. ·»´õ¸µ¿¡ ÇÊ¿äÇÑ
Face ¼ýÀÚ¿Í, Face ¸®½ºÆ®°¡ ÇÊ¿äÇÕ´Ï´Ù.
struct McGeo // Geometry
{
UINT nFce; // Face ¼ýÀÚ
UINT nVtx; // Á¤Á¡ ¼ýÀÚ
VtxIdx* pIdx; // Face ¸®½ºÆ®
};
Áö¿À¸ÞÆ®¸®¸¦ °¡Áö°í ÀÖÀ» Ŭ·¡½ºÀÇ ¸â¹ö º¯¼ö´Â Áö¿À¸ÞÆ®¸®ÀÇ ¼ýÀÚ¿Í µ¥ÀÌÅ͸¦ °¡Á®¾ß Çϰí, ID3DXMesh °´Ã¼¿¡¼ Á¤Á¡ ¹öÆÛ¸¦ º¹»çÇØ¿Í¾ß ÇϹǷΠÁ¤Á¡ÀÇ ¼ö, Á¤Á¡
ÇϳªÀÇ Å©±â, FVF, Á¤Á¡ ¹öÆÛ¸¦ ÀÖ¾î¾ß ÇÕ´Ï´Ù.
INT m_nGeo; // Áö¿À¸ÞÆ®¸® ¼ö
McGeo* m_pGeo; // Áö¿À¸ÞÆ®¸®
UINT m_nVtx; // Á¤Á¡ÀÇ °³¼ö
UINT m_dVtx; // Á¤Á¡ ÇϳªÀÇ Å©±â
DWORD m_dFVF; // FVF
void* m_pVtx; // Á¤Á¡ ¹öÆÛ
ID3DXMesh °´Ã¼¿¡¼ µ¥ÀÌÅ͸¦ ²¨³»¿À´Â ¹æ¹ýÀº ´ÙÀ½°ú °°ÀÌ ¸ÕÀú
Á¤Á¡ÀÇ ¼ö, À妽º(Face)ÀÇ ¼ö¸¦ ¾ò¾î ¿É´Ï´Ù.
ID3DXMesh* pMeshSrc = "ID3DXMesh °´Ã¼ »ý¼º
ÇÔ¼ö";
¡¦
INT nVtxS=
pMeshSrc->GetNumVertices();
INT nFceS=
pMeshSrc->GetNumFaces();
·»´õ¸µ¿¡ ÇÊ¿äÇÑ Á¤Á¡ ÇϳªÀÇ Å©±â, FVF, Á¤Á¡ ¹öÆÛ¸¦ »ý¼ºÇÕ´Ï´Ù. Á¤Á¡ÀÇ Æ÷¸ËÀº ¾ËÁö ¸øÇϱ⠶§¹®¿¡ malloc() ÇÔ¼ö µîÀ¸·Î ¸Þ¸ð¸®¸¸ È®º¸ÇÕ´Ï´Ù.
m_nVtx =
nVtxS;
m_dVtx =
(UINT)pMeshSrc->GetNumBytesPerVertex();
m_dFVF =
pMeshSrc->GetFVF();
m_pVtx = malloc(m_nVtx *
m_dVtx);
ID3DXMesh °´Ã¼¿¡¼
Á¤Á¡À» º¹»çÇÕ´Ï´Ù.
VtxUV1* pVtxS=NULL;
pMeshSrc->LockVertexBuffer(0, (void**)&pVtxS);
memcpy(m_pVtx, pVtxS, sizeof(VtxUV1) * nVtxS);
pMeshSrc->UnlockVertexBuffer();
À妽º´Â Áö¿À¸ÞÆ®¸®¿¡ ±â·ÏµÉ °ÍÀÔ´Ï´Ù. µû¶ó¼ ID3DXMesh¿¡ ÀÖ´Â À妽º´Â Àӽà ¹öÆÛ¸¦ ¸¸µé°í ¿©±â¿¡
º¹»çÇÕ´Ï´Ù.
VtxIdx* pFce = new VtxIdx[nFceS];
VtxIdx* pIdxS=NULL;
pMeshSrc->LockIndexBuffer(0, (void**)&pIdxS);
memcpy(pFce, pIdxS, sizeof(VtxIdx) * nFceS);
pMeshSrc->UnlockIndexBuffer();
Áö¿À¸ÞÆ®¸® °´Ã¼ÀÇ ³»¿ëÀ» ¼³Á¤Çϱâ À§Çؼ ¼Ó¼º Å×À̺íÀÇ °³¼ö¿Í
³»¿ëÀ» °¡Á®¿É´Ï´Ù. ¼Ó¼º Å×À̺íÀÇ ¼ýÀÚ´Â Áö¿À¸ÞÆ®¸®ÀÇ ¼ýÀÚ¿Í µ¿ÀÏÇÏ°Ô Çϰí ÀÌ °³¼ö¸¸Å Áö¿À¸ÞÆ®¸®¸¦
¸¸µì´Ï´Ù.
DWORD nNumSubset=0;
hr=
pMeshSrc->GetAttributeTable(0,
&nNumSubset);
// Geometry ¼ýÀÚ¸¦ ¼³Á¤ÇÑ´Ù.
m_nGeo =
nNumSubset;
m_pGeo = new McGeo[m_nGeo];
D3DXATTRIBUTERANGE* attTable = new D3DXATTRIBUTERANGE[nNumSubset];
hr=
pMeshSrc->GetAttributeTable(attTable, &nNumSubset);
¼Ó¼º Å×À̺íÀÇ ³»¿ëÀ» °¡Áö°í Áö¿À¸ÞÆ®¸®ÀÇ À妽º(Face)¸¦ ±¸¼ºÇÕ´Ï´Ù.
for(i=0; i<m_nGeo; ++i)
{
McGeo* pGeo =
&m_pGeo[i];
pGeo->nFce =
attTable[i].FaceCount;
pGeo->nVtx =
attTable[i].VertexCount;
pGeo->nFceB =
attTable[i].FaceStart;
// GeometryÀÇ À妽º
¹öÆÛ »ý¼º
pGeo->pIdx =
new VtxIdx[pGeo->nFce];
// Index Buffer º¹»ç
VtxIdx* pIdxDst = pFce +
pGeo->nFceB;
memcpy(pGeo->pIdx,
pIdxDst, sizeof(VtxIdx) * pGeo->nFce);
}
Àå¸éÀ» ±¸¼ºÇÒ Á¤Á¡ ¹öÆÛ, Áö¿À¸ÞÆ®¸®ÀÇ
³»¿ëÀ» ´Ù ä¿ü½À´Ï´Ù. ID3DXMesh°´Ã¼¿Í Àӽ÷Π»ç¿ëÇÑ À妽º ¹öÆÛ, ¼Ó¼ºÅ×À̺íÀº ÇØÁ¦ÇÕ´Ï´Ù. ·»´õ¸µÀº ´ÙÀ½°ú °°ÀÌ Á¤Á¡ ¹öÆÛ¿Í Áö¿À¸ÞÆ®¸®ÀÇ
Á¤º¸¸¦ ÀÌ¿ëÇÕ´Ï´Ù.
for(i = 0; i < m_nGeo; i++)
{
McGeo* pGeo = &m_pGeo[i];
m_pDev->SetTexture( 0, m_pTex[i] );
m_pDev->SetFVF(m_dFVF);
m_pDev->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, m_nVtx
, pGeo->nFce, pGeo->pIdx,
D3DFMT_INDEX16, m_pVtx, m_dVtx);
}
Àüü ÄÚµå´Â daux07_mesh02.zipÀ»
Âü°íÇϱ⠹ٶø´Ï´Ù.

<ID3DXMesh °´Ã¼ÀÇ ³»¿ëÀ» º¹»çÇÑ Áö¿À¸ÞÆ®¸®·Î ·»´õ¸µ: daux07_mesh02.zip>
DXSDK´Â ¿¬¼ÓµÈ Á¤Á¡ µ¥ÀÌÅÍ¿¡ ´ëÇØ¼ Ãæµ¹¿¡ ´ëÇÑ °æ°è»óÀÚ(Bounding Box)¿Í °æ°è ±¸(Bounding Sphere)¸¦
±¸ÇØÁÖ´Â ÇÔ¼ö°¡ ÀÖ½À´Ï´Ù. ¸¸¾à ID3DXMesh °´Ã¼¿¡
´ëÇÑ Bounding Box, Sphere´Â ´ÙÀ½°ú °°ÀÌ ÇÕ´Ï´Ù.
D3DXVECTOR3* pVtx=NULL;
D3DXVECTOR3 vcMax; D3DXVECTOR3 vcMin; D3DXVECTOR3 vcCenter; FLOAT fRadius;
DWORD nVtx =
m_pMsh->GetNumVertices();
DWORD dFVF =
m_pMsh->GetFVF();
DWORD dStride = D3DXGetFVFVertexSize(dFVF);
pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&pVtx);
D3DXComputeBoundingBox((D3DXVECTOR3*)pVtx, nVtx, dStride,
&vcMin, &vcMax);
D3DXComputeBoundingSphere((D3DXVECTOR3*)pVtx, nVtx, dStride, &vcCenter, &fRadius);
pMesh->UnlockVertexBuffer();
3.7.2 X-file
3D ±âÃÊ Tutorial¿¡¼
È£¶ûÀÌ X-fileÀ» ¿ì¸®´Â ȸ鿡 ¿Ã·Á º¸¾Ò½À´Ï´Ù. X-file Àå¸é¿¡
´ëÇÑ ·»´õ¸µ ¿ÀºêÁ§Æ®ÀÇ Á¤º¸¸¦ °¡Áö°í ÀÖ´Â X-file¿¡ ´ëÇÑ ÇØ¼®Àº
DXSDK¿¡¼ Áö¿ø µÇ¾î º°µµÀÇ ³ë·ÂÀÌ ÇÊ¿ä ¾ø½À´Ï´Ù. ´Ù·ç±â°¡ ½¬¿ö¼ °ÔÀÓ °³¹ß ±â°£
Áß¿¡ Å×½ºÆ® ÆÄÀÏ·Î °¡Àå ¸¹ÀÌ »ç¿ëµÇ´Â Æ÷¸ËÀÔ´Ï´Ù. °ÔÀÓ È¸»ç´Â ¿ÀºêÁ§Æ®¿¡ ´ëÇÑ ÀÚü Æ÷¸ËÀÌ ÀÖ½À´Ï´Ù. ±×·±µ¥ ÀÌ Æ÷¸ËÀ» °³¹ßÇÏ´Â ´Ü°è¿¡¼ Á¦´ë·Î ÀÛµ¿ÇÏ´ÂÁö ºñ±³¸¦ Çϱâ À§Çؼ X-fileÀ»
°¡Àå ¸¹ÀÌ »ç¿ëÇÕ´Ï´Ù. °ÔÀÓ ÇÁ·Î±×·¡¹ÖÀ» óÀ½ ¹è¿ì´Â »ç¶÷µéµµ °ÔÀÓ ¿ÀºêÁ§Æ®¸¦ X-file·Î ¸¹ÀÌ °¡Á®°©´Ï´Ù. µû¶ó¼ X-file¿¡ ´ëÇÑ Å¬·¡½º¸¦ ¸¸µé¾î ³õ´Â °ÍÀº ÇÊ ¼ö ÀÔ´Ï´Ù.
Ŭ·¡½º¸¦ ¸¸µé±â À§ÇØ ÇÊ¿äÇÑ ÀڷᱸÁ¶¸¦ ¸ðÀ¸´Ï ´ÙÀ½°ú °°ÀÌ ¸Þ½¬, ÀçÁú, ÅØ½ºÃ³ °´Ã¼·Î ¸ð¾ÆÁý´Ï´Ù.
class CMcXFile
LPDIRECT3DDEVICE9 m_pDev;
char m_sFile[MAX_PATH];
ID3DXMesh* m_pMsh;
D3DMATERIAL9* m_pMtl;
LPDIRECT3DTEXTURE9* m_pTex;
INT m_nMtl;
ÆÄÀÏ¿¡¼ D3DXLoadMeshFromX() ÇÔ¼ö·Î ¸Þ½¬¸¦ Àоî¿À´Â
°ÍÀº È£¶ûÀ̸¦ ¿Ã·Á º¸¾ÒÀ¸¸é ÀÌ¹Ì ¾Ë°í ÀÖ´Â ³»¿ëÀÔ´Ï´Ù.
ID3DXBuffer* AdjBuf = NULL;
ID3DXBuffer* MtlBuf = NULL;
hr = D3DXLoadMeshFromX(sFile,
D3DXMESH_SYSTEMMEM, m_pDev
,
&AdjBuf, &MtlBuf, 0, &nMtl, &m_pMsh);
´ÙÀ½À¸·Î ID3DXMesh¿¡¼
¹è¿î »ï°¢ÇüÀÇ ÀÎÁ¢ Á¤º¸¸¦ ÀÌ¿ëÇÑ ÃÖÀûȸ¦ ÁøÇàÇÕ´Ï´Ù.
DWORD dOpt = D3DXMESHOPT_ATTRSORT |
D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE;
DWORD* pAdj = (DWORD*)AdjBuf->GetBufferPointer();
hr = m_pMsh->OptimizeInplace(dOpt, pAdj,
0, 0, 0);
DXSDKÀÇ ID3DXBuffer ÀÎÅÍÆäÀ̽º´Â
ÀڷḦ ¿¬¼ÓÀûÀÎ ¸Þ¸ð¸® °ø°£¿¡ ÀúÀåÇϱâ À§Çؼ ¹ü¿ëÀûÀ¸·Î ¸¸µç ÀÚ·á ±¸Á¶ÀÔ´Ï´Ù. ID3DXBuffer ÀÎÅÍÆäÀ̽º´Â
ÀÚ·á ÀÚü¸¦ °¡Á®¿À´Â GetBufferPointer()¿Í ÀúÀåµÈ ÀÚ·áÀÇ Å©±â(Byte)¸¦ °¡Á®¿À´Â GetBufferSize() ÇÔ¼ö°¡ ÀÖ½À´Ï´Ù.
GetBufferPointer() ÇÔ¼ö·Î ÀÚ·áÀÇ ½ÃÀÛ ÁÖ¼Ò¸¦ °¡Á®¿Í¼
ÇÊ¿äÇÑ °æ¿ì¿¡ ij½ºÆÃÇØ¼ »ç¿ëÇÕ´Ï´Ù. ID3DXBuffer °´Ã¼ÀÇ
Release() ÇÔ¼ö¸¦ È£ÃâÇϸé ID3DXBuffer °´Ã¼ ³»ºÎ¿¡ ÀúÀåµÈ ÀÚ·áµéµµ °°ÀÌ
¼Ò¸êÇÕ´Ï´Ù. ÀÌ °´Ã¼´Â ÀÌÈÄ ½¦ÀÌ´õ¿¡¼ ¿¡·¯ µîÀÇ ¸Þ½ÃÁö¸¦ ¹Ýȯ ¹ÞÀ» ¶§µµ »ç¿ëµË´Ï´Ù.
D3DXCreateBuffer() ¶ó´Â ÇÔ¼ö¸¦ »ç¿ëÇØ¼ Á÷Á¢ ¿¬¼ÓµÈ
¸Þ¸ð¸®¸¦ È®º¸ÇÒ ¼ö ÀÖ½À´Ï´Ù.
»ï°¢Çü ÃÖÀûȰ¡ ³¡³ª¸é ÀçÁú°ú ÅØ½ºÃ³¸¦ »ý¼ºÇϰí ÀçÁú ¸ÕÀú º¹»ç ÇÕ´Ï´Ù.
// ÀçÁú°ú ÅØ½ºÃ³ »ý¼º
m_pMtl = new D3DMATERIAL9[m_nMtl];
m_pTex = new LPDIRECT3DTEXTURE9[m_nMtl];
// ÅØ½ºÃ³ Æ÷ÀÎÅÍ ÃʱâÈ
memset(m_pTex, 0, sizeof(LPDIRECT3DTEXTURE9) *m_nMtl);
// ÀçÁú µ¥ÀÌÅÍ °¡Á®¿È
D3DXMATERIAL* pMtl = (D3DXMATERIAL*)MtlBuf->GetBufferPointer();
// ÀçÁú º¹»ç.
for(i=0; i<m_nMtl; ++i)
memcpy(&(m_pMtl[i]),
&(pMtl[i].MatD3D), sizeof(D3DMATERIAL9));
ÅØ½ºÃ³´Â Á¶±Ý ÁÖÀÇÇØ¾ß ÇÕ´Ï´Ù. X-file ³»ºÎ¿¡ ÀúÀåµÈ À̹ÌÁö °æ·Î¿Í ½ÇÁ¦ À̹ÌÁöÀÇ À§Ä¡°¡ ´Ù¸¦ ¼ö ÀÖ½À´Ï´Ù. °¡Àå ÁÁÀº ¹æ¹ýÀº ÇØ´ç X-file¿¡ ÅØ½ºÃ³¸¦ °°ÀÌ ³õ°Å³ª ¾Æ´Ï¸é
X-fileÀÌ ÀÖ´Â Æú´õÀÇ Æ¯Á¤À̸§ÀÌ ÀÖ´Â ÇÏÀ§ Æú´õ¿¡ ÅØ½ºÃ³¸¦ °¡Áö°í ÀÖÀ¸¸é ÄÚµùÀÇ Àϰü¼ºÀÌ »ý±é´Ï´Ù.
¿©±â¼´Â °°Àº °æ·Î¿¡ ÀÖ´Ù°í »ý°¢ÇÏ°í ´ÙÀ½°ú °°ÀÌ _splitpath() ÇÔ¼ö¿Í _makepath() ÇÔ¼ö·Î À̹ÌÁö
°æ·Î¸¦ Á¶Á¤Çؼ ÅØ½ºÃ³°¡ »ý¼ºµÉ ¼ö°Ô ÀÖ°Ô ÇÕ´Ï´Ù.
char sParentPath[MAX_PATH]={0}; char dir[_MAX_DIR]={0};
_splitpath( sFile, NULL, dir, NULL, NULL);
_makepath(sParentPath, NULL, dir, NULL, NULL);
// ÅØ½ºÃ³ »ý¼º
for(i=0; i<m_nMtl; ++i)
{
char sTexFile[MAX_PATH]={0};
char fname[_MAX_FNAME]={0};
char ext[_MAX_EXT]={0};
char* sTexSrc = pMtl[i].pTextureFilename;
if(NULL == sTexSrc || strlen(sTexSrc)<3)
continue;
_splitpath( sTexSrc, NULL, NULL, fname, ext);
_makepath(sTexFile, NULL, sParentPath, fname,
ext);
IDirect3DTexture9* pTx = NULL;
D3DXCreateTextureFromFile(m_pDev, sTexFile, &pTx);
m_pTex[i]
= pTx;
Àüü ÄÚµå´Â daux07_xfile01.zipÀ»
Âü°íÇϰí CMcScene::Create() ÇÔ¼öÀÇ ÁÖ¼®À» ¹Ù²Ù¾îº¸¸é ´ÙÀ½°ú °°Àº Dwarf¿Í °Ç¹°À» º¼ ¼ö ÀÖ½À´Ï´Ù.

<x-file: daux07_xfile01.zip>
daux07_xfile01.zipÀÇ Dwarf¸¦ ½ÇÇàÇÏ¸é °Ç¹°º¸´Ù »ó´çÈ÷ ÀÛ°Ô ³ª¿É´Ï´Ù. ¿ùµå Çà·ÄÀ»
¹Ù²Ù¾î¼ ¹Ù²Ù¸é Å©°Ô Ãâ·ÂÇÒ ¼ö ÀÖÀ» °ÍÀÔ´Ï´Ù.
ÀÌ·¸°Ô X-fileÀÇ Å¬·¡½º ÀÛ¾÷Àº ³¡ÀÌ ³ª º¸ÀÔ´Ï´Ù. ±×·±µ¥ ¿©±â¼ Àá±ñ »ý°¢ÇغÁ¾ß ÇÒ °ÍÀÌ ÀÖ½À´Ï´Ù. ¸¸¾à °°Àº ¸ðµ¨ÀÇ Dwarf¸¦ ¿©·¯ °³ Ãâ·ÂÇÏ°Ô µÈ´Ù¸é ¸Å ¹ø ÆÄÀÏ¿¡¼ Àоî¿Í¾ß ÇÒ±î¿ä?
¸Å¹ø ÆÄÀÏ¿¡¼ ºÒ·¯¿Í »ý¼ºÇÏ¸é º¸Á¶ ±â¾ï ÀåÄ¡¸¦ Á¢±ÙÇÏ´Â °ÍÀ̹ǷΠ·»´õ¸µ ¼ÓµµÀÇ ÀúÇÏ´Â ºÒÀ» º¸µí »·ÇÕ´Ï´Ù. ±×·¸´Ù¸é ÇϳªÀÇ ¸ðµ¨À» °¡Áö°í º¹Á¦Çؼ »ç¿ëÇÏ´Â ¹æ¹ýÀ» »ý°¢ÇÒ ¼ö ÀÖ½À´Ï´Ù.
¸Þ½¬ÀÇ ±âÇÏ Á¤º¸¸¦ º¹»çÇÏ´Â CloneMeshFVF() ÇÔ¼ö¸¦ ÅëÇØ¼
Á¤Á¡°ú À妽º µîÀ» º¹»ç Çϰí ÅØ½ºÃ³´Â º¯ÇÏ´Â ÀÏÀÌ ¾øÀ¸¹Ç·Î ¿øº»¿¡¼ ÂüÁ¶Çϵµ·Ï ÇÏ¸é µÉ °Í °°½À´Ï´Ù. ±×·±µ¥
ÀÌ ¹æ¹ýµµ ´õ »ý°¢ÇØ ºÁ¾ß ÇÕ´Ï´Ù. ÆÄƼŬ°ú °°ÀÌ Á¤Á¡ÀÇ À§Ä¡¸¦ ÆÄÀÌÇÁ¶óÀο¡ ¿Ã¸®±â Àü¿¡ ¹Ù²Ù¾î¾ß ÇÏ´Â
°ÍÀº ±âÇÏ Á¤º¸¸¦ ¹Ýµå½Ã º¹»ç¸¦ ÇØ¾ß ÇÏÁö¸¸ ·»´õ¸µ ÆÄÀÌÇÁ¶óÀÎÀÇ ¿ùµå Çà·Ä¸¸ ¹Ù²Ù¾îµµ µÇ´Â ¿ÀºêÁ§Æ®´Â º¹»ç°¡ ¾Æ´Ñ ¿øº»À» ÂüÁ¶ÇÏ´Â ¹æ¹ýÀ¸·Î ¿ÀºêÁ§Æ®¸¦
±¸¼ºÇØ¾ß ÇÕ´Ï´Ù.
ÀÌ·± ÁÁÀº ¾ÆÀ̵ð¾î°¡ À־ ¸·»ó ÄÚµå·Î Ç¥Çö ÇÏ´Â °ÍÀÌ
¾î·Á¿ï ¼öµµ ÀÖ½À´Ï´Ù. ÀÌ·² ¶§ ¹«Á¶°Ç ÀÌÀüÀÇ Äڵ带 ´Ù ¹Ù²ÙÁö ¸»°í Àß ±¸¼ºµÇ¾î ÀÖ´Ù¸é »õ·Î¿î Ŭ·¡½º¸¦
Ãß°¡Çؼ °ü°è¸¦ ¸¸µé¾î °¡´Â °ÍÀÌ ´õ ÁÁ½À´Ï´Ù.
±×¸²Ã³·³ IMcXFile¸¦ ¼ø¼ö °¡»óÇÔ¼öµé·Î ±¸¼ºµÈ ÀÎÅÍÆäÀ̽º¸¦ Çϳª¸¦
¸¸µé°í CMcXFile Ŭ·¡½º´Â À̸¦ »ó¼ÓÇÕ´Ï´Ù. ±×¸®°í
·»´õ¸µ ¿ÀºêÁ§Æ®ÀÎ CMcXFileIns Ŭ·¡½º´Â IMcXFile Ŭ·¡½º¸¦
»ó¼Ó ¹Þ°í CMcXFile Ŭ·¡½º¸¦ Æ÷ÇÔÇÕ´Ï´Ù.
¿©±â¼ ¿øÄ¢À» Çϳª ¸¸µé¸é CMcXFileÀº ·»´õ¸µÀÌ °¡´ÉÇØµµ ±×
¿ªÇÒÀ» ÇÏÁö ¾Ê°í ¿ÀÁ÷ CMcXFileIns Ŭ·¡½º¸¸ Àå¸éÀ» ·»´õ¸µ ÇÏ°Ô Çϸé CMcXFileÀÇ ÀνºÅϽº´Â ¸Þ¸ð¸® º¹Á¦¿ëÀ¸·Î¸¸ »ç¿ëÇÏ°Ô µË´Ï´Ù.

<X-file °´Ã¼¸¦ Ç¥ÇöÇϱâ À§ÇÑ Å¬·¡½º ±¸Á¶>
À̰ÍÀ» ÄÚµå·Î ±¸ÇöÇØ º¸¸é ¸ÕÀú IMcXFileÀÇ ÀÎÅÍÆäÀ̽º¸¦ ´ÙÀ½°ú
°°ÀÌ ¸¸µì´Ï´Ù.
#define interface struct
interface IMcXFile
{
virtual INT Create(¡¦, char* sFileName=NULL, void* pOriginal=NULL)=0;
virtual void Destroy()=0;
virtual INT FrameMove()=0;
virtual void Render()=0;
virtual IMcXFile* GetOrigin()=0;
virtual void SetWorldMatrix(const D3DXMATRIX*)=0;
virtual D3DXMATRIX* GetWorldMatrix()=0;
};
Create(), Destroy(), FrameMove(), Render()ÇÔ¼ö´Â
°´Ã¼ÀÇ »ý¼º, ¼Ò¸ê, µ¥ÀÌÅÍ °»½Å, ·»´õ¸µ¿¡ ´ëÇÑ ÇÔ¼ö ÀÔ´Ï´Ù. GetOrigin() ÇÔ¼ö´Â X-fileÀÇ ³»¿ëÀ» °®°í ÀÖ´Â CMcXFileÀÇ °´Ã¼¸¦ ¹ÝȯÇÏ´Â
ÇÔ¼ö ÀÔ´Ï´Ù. °¢ ·»´õ¸µ ¿ÀºêÁ§Æ®´Â ¿ùµå Çà·ÄÀÌ ÀÖ¾î¾ß ÇϹǷΠ¿ùµå Çà·ÄÀ» ¼³Á¤Çϰųª °¡Á®¿Ã ¼ö ÀÖ´Â
ÇÔ¼ö¸¦ ÁغñÇÕ´Ï´Ù.
°´Ã¼ÀÇ »ý¼ºÀº ´ÙÀ½°ú °°Àº ÇÔ¼ö·Î Ŭ·¡½ºÀÇ ÀνºÅϽº¸¦ ¸¸µì´Ï´Ù.
INT McXCreate_Xfile(IMcXFile** pOut, LPDIRECT3DDEVICE9 pDev, char* sFile, void* pOriginal)
{
IMcXFile* pObj=
NULL;
if(sFile)
pObj
= new CMcXFile;
else if(pOriginal)
pObj
= new CMcXFileIns;
else{ *pOut =
NULL; return -1; }
if(FAILED(pObj->Create(pDev, sFile, pOriginal)))
{
delete pObj; return -1;
}
*pOut
= pObj;
return 0;
}
ÀÌ ÇÔ¼ö´Â ÇØ´ç ÀνºÅϽº¸¦ ¾î´À Ŭ·¡½º¿¡¼ ¸¸µéÁö °áÁ¤ÇÕ´Ï´Ù. ¸¸¾à
ÆÄÀÏ À̸§ÀÌ ÁÖ¾îÁö¸é CMcXFile Ŭ·¡½ºÀÇ °´Ã¼¸¦ ¸¸µé°í ÆÄÀÏ À̸§ ´ë½Å CMcXFile °´Ã¼¿¡ ´ëÇÑ Original Æ÷ÀÎÅͰ¡ ÁÖ¾îÁö¸é º¹Á¦¿¡
´ëÇÑ ¿ä±¸·Î ¹Þ¾Æ µé¿© CMcXFileIns Ŭ·¡½ºÀÇ °´Ã¼¸¦ ¸¸µì´Ï´Ù.
CMcXFile Ŭ·¡½º´Â ´ÙÀ½°ú °°ÀÌ IMcXFile ÀÎÅÍÆäÀ̽º¸¦ »ó¼Ó ¹Þ°í º¹Á¦¿¡ ÇÊ¿äÇÑ Á¤º¸¸¦ Àü´Þ ÇÒ ¼ö ÀÖµµ·Ï ¸î °³ÀÇ ¸Þ¼Òµå¸¦ Ãß°¡Çß½À´Ï´Ù.
class CMcXFile : public IMcXFile
¡¦
public:
ID3DXMesh* GetMesh() { return m_pMsh; }
D3DMATERIAL9* GetMaterial() { return m_pMtl; }
LPDIRECT3DTEXTURE9* GetTexture() { return m_pTex; }
INT GetNumMaterial(){ return m_nMtl; }
·»´õ¸µ ¿ªÇÒÀ» ÇÏ°Ô µÉ CMcXFileIns´Â ¿øº» CMcXFile Ŭ·¡½ºÀÇ °´Ã¼¿Í Àå¸é ±¸¼º¿¡ ÇÊ¿äÇÑ ¿ùµå Çà·ÄÀ» ¸â¹ö·Î ±¸¼ºÇÕ´Ï´Ù. ¶ÇÇÑ ¿ÜºÎ¿¡¼ ¿ùµé Çà·ÄÀ» ¼³Á¤Çϰųª °¡Á®¿Ã ¼ö ÀÖ´Â ¸â¹ö ÇÔ¼ö¸¦ ±¸ÇöÇÕ´Ï´Ù.
class CMcXFileIns : public IMcXFile
¡¦
CMcXFile* m_pOrg; // Original X-file Instance
D3DXMATRIX m_mtWld;
public:
virtual IMcXFile* GetOrigin() { return m_pOrg; }
virtual void SetWorldMatrix(const D3DXMATRIX* v){ m_mtWld
= *v; }
virtual D3DXMATRIX* GetWorldMatrix() { return &m_mtWld; }
³²Àº °ÍÀº CMcXFileIns Ŭ·¡½º¿¡¼ ·»´õ¸µ¿¡ ÇÊ¿äÇÑ µ¥ÀÌÅÍ
ÃʱâÈ ÀÔ´Ï´Ù. CMcXFileIns:: Create() ÇÔ¼ö¸¦ º¸¸é ´ÙÀ½°ú °°ÀÌ °£´ÜÇÏ°Ô Ã³¸®Çϰí
ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.
INT CMcXFileIns::Create(¡¦, void* pOriginal)
¡¦
m_pOrg
= (CMcXFile*)pOriginal;
m_pMsh
= m_pOrg->GetMesh();
m_pMtl
= m_pOrg->GetMaterial();
m_pTex
= m_pOrg->GetTexture();
m_nMtl
= m_pOrg->GetNumMaterial();
¸Þ½¬, ÀçÁú, ÅØ½ºÃ³¿¡
´ëÇÑ ÁÖ¼Ò¸¦ °¡Áú ÇÊ¿ä´Â ¾øÁö¸¸ ·»´õ¸µ ÇÔ¼ö¿¡¼ ¸Å¹ø ¿øº»¿¡¼ È£ÃâÇÏ´Â ºÎ´ãÀ» ´ú±â À§ÇؼÀÔ´Ï´Ù.
ÀÌ Å¬·¡½ºÀÇ Render()ÇÔ¼ö´Â ´ÙÀ½°ú °°ÀÌ ¿ùµå Çà·ÄÀ» ¼³Á¤Çϰí
¿øº»ÀÇ ¸Þ½¬, ÀçÁú µîÀÇ ÁÖ¼Ò¸¦ ÀúÀåÇÑ Æ÷ÀÎÅÍ·Î ·»´õ¸µ ÇÕ´Ï´Ù.
void CMcXFileIns::Render()
¡¦
m_pDev->SetTransform(D3DTS_WORLD, &m_mtWld);
for(i=0; i<m_nMtl; ++i)
{
m_pDev->SetMaterial( &m_pMtl[i]
);
m_pDev->SetTexture( 0, m_pTex[i] );
m_pMsh->DrawSubset( i );
}
static D3DXMATRIX mtI(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1);
m_pDev->SetTransform(D3DTS_WORLD, &mtI);
¸¶Áö¸·À¸·Î Å×½ºÆ®°¡ ³²¾Ò½À´Ï´Ù. daux07_xfile02.zipÀÇ CMcScene
Ŭ·¡½º ¼±¾ðÀ» º¸¸é ´ÙÀ½°ú °°ÀÌ ¿øº»°ú ¿øº»ÀÇ µ¥ÀÌÅ͸¦ ÂüÁ¶ÇÏ´Â 3°³ÀÇ ·»´õ¸µ ¿ÀºêÁ§Æ®
ÀνºÅϽº¸¦ º¼ ¼ö ÀÖ½À´Ï´Ù.
class CMcScene
¡¦
IMcXFile* m_pXOrg;
IMcXFile* m_pXClone1;
IMcXFile* m_pXClone2;
IMcXFile* m_pXClone3;
3°³ÀÇ ·»´õ¸µ ¿ÀºêÁ§Æ®µéÀº CMcScene::Create()
ÇÔ¼ö¿¡¼ ´ÙÀ½°ú °°ÀÌ ¿øº»À» ¸ÕÀú »ý¼ºÇÑ ´ÙÀ½ ÀÌ ÀνºÅϽº¸¦ ÀÌ¿ëÇØ¼ »ý¼ºÇÕ´Ï´Ù.
INT CMcScene::Create(LPDIRECT3DDEVICE9 pDev)
¡¦
hr
= McXCreate_Xfile(&m_pXOrg, m_pDev, "xfile/dwarf/dwarf.x");
hr
= McXCreate_Xfile(&m_pXClone1, m_pDev, NULL, m_pXOrg);
hr
= McXCreate_Xfile(&m_pXClone2, m_pDev, NULL, m_pXOrg);
hr
= McXCreate_Xfile(&m_pXClone3, m_pDev, NULL, m_pXOrg);
¿ùµå Çà·Ä °»½Å°ú ·»´õ¸µÀº CMcScene::FrameMove() ÇÔ¼ö¿Í CMcScene::Render() ÇÔ¼ö¿¡¼ ±¸ÇöµÇ¾î
ÀÖÀ¸´Ï Âü°í Çϱ⠹ٶø´Ï´Ù.
daux07_xfile02.zip¸¦
½ÇÇàÇÏ¸é ´ÙÀ½°ú °°ÀÌ Dwarf 3°³°¡ Àִ ȸéÀ» º¼ ¼ö ÀÖ½À´Ï´Ù.

<X-file Ŭ·¡½º¿¡ ´ëÇÑ Ãß»óÈ: daux07_xfile02.zip>
3.8 X-file
Animation
3.8.1 Skinning
Animation ±âÃÊ
Á¤ÀûÀÎ ¸ðµ¨ÀÇ DXSDKÀÇ
Sample Æú´õ¿¡ SkinnedMesh ¿¹Á¦°¡ ÀÖ½À´Ï´Ù.
ÀÌ ¿¹Á¦´Â ¾Ö´Ï¸ÞÀÌ¼Ç Á¤º¸°¡ Æ÷ÇԵǾî ÀÖ´Â X-fileÀ» ȸ鿡 Ãâ·ÂÇØ ÁÝ´Ï´Ù.

<DXSDK Skinning ¿¹Á¦>
3D °ÔÀÓ¿¡¼ ¾Ö´Ï¸ÞÀ̼ÇÀ̶ó´Â °ÍÀº °£´ÜÇÏ°Ô ½Ã°£¿¡ ´ëÇÑ Á¤Á¡ÀÇ À̵¿À̶ó
ÇÒ ¼ö ÀÖ°Ú½À´Ï´Ù. ÀÌ Á¤Á¡À» À̵¿ ½ÃŰ´Â ¹æ¹ýÀº ½Ã°£¿¡ ´ëÇØ¼ ¿ÀºêÁ§Æ®ÀÇ ¸ðµç À§Ä¡¸¦ ÀúÀåÇÑ µ¥ÀÌÅÍ¿¡¼
°¡Á®¿À´Â ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù. ÀÌ ¹æ¹ýÀº °¡Àå ºü¸£°í Á¤È®ÇÑ ¾Ö´Ï¸ÞÀ̼ÇÀ» ¸¸µé¾î ³»Áö¸¸ ¹®Á¦´Â Á¤Á¡ÀÇ ¼ýÀÚ¿Í
¾Ö´Ï¸ÞÀ̼ÇÀÇ ½Ã°£¿¡ °ö¿¡ ¸Þ¸ð¸®¸¦ ¾öû³ª°Ô ÇÊ¿ä·Î ÇÕ´Ï´Ù.
ÀÌÀÇ °³¼± Ã¥À¸·Î ¸¹ÀÌ ¼±ÅÃÇÏ´Â °ÍÀÌ ÀÚ·á ±¸Á¶ Áß ³ª¹« ±¸Á¶(tree
structure)ó·³ ¿ÀºêÁ§Æ®¸¦ ±¸¼ºÇϰí ÀÖ´Â °³º°ÀûÀÎ Geometry¸¦ ºÎ¸ð¿Í Àڽİ£ÀÇ
°ü°è·Î ¼³Á¤Çϰí, ½Ã°£¿¡ ´ëÇÑ º¯È¸¦ °¢ GeometryÀÇ
Çà·Ä·Î ÀúÀåÇØ¼ ÇØ´ç ½Ã°£¿¡ ºÎ¸ðÀÇ Çà·ÄÀ» ÀÚ½ÅÀÇ Áö¿ª Çà·Ä¿¡ °öÇØ ¾Ö´Ï¸ÞÀ̼ÇÀ» ÇÏ´Â ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù. ÀÌ
¹æ¹ýÀ» »ç¿ëÇÏ¸é ½Ã°£ÀÌ ´Ã¾î³ªµµ ¾Ö´Ï¸ÞÀÌ¼Ç Á¤º¸ÀÇ Çà·Ä ¸¸ Ä¿Áú »Ó Á¤Á¡ÀÇ °³¼ö¿Í´Â ¹«°üÇÏ°Ô µÇ¾î È¿À²ÀûÀÎ ÇÁ·Î±×·¥ÀÌ µÇ°í ÇöÀç ´ëºÎºÐÀÇ °ÔÀÓÀº
ÀÌ ¹æ¹ýÀ» ä¿ëÇϰí ÀÖ½À´Ï´Ù
3D¿¡¼ ÇϳªÀÇ Çà·ÄÀ» ÇϳªÀÇ ¿ÀºêÁ§Æ®¿¡ °¡ÇÏ¸é ¿ÀºêÁ§Æ®¸¦ ±¸¼ºÇÏ´Â
Á¤Á¡ »çÀÌÀÇ °ü°è ƯÈ÷, °Å¸®ÀÇ ºñÀ²Àº ÀÌÀü°ú º¯ÇÔÀÌ ¾ø½À´Ï´Ù. ÀÌ·¸°Ô
ÀÌÀüÀÇ Æ¯¼ºÀÌ À¯ÁöµÇ´Â ¾Ö´Ï¸ÞÀ̼ÇÀ» µüµüÇÑ ¾Ö´Ï¸ÞÀ̼Ç(Rigid body: °Ã¼)¶ó ºÎ¸£´Â °Ã¼ ¾Ö´Ï¸ÞÀ̼ÇÀÔ´Ï´Ù. °Ã¼¶ó´Â °ÍÀº ¼øÀüÈ÷ ¹°¸®Çп¡¼
¿Â ¿ë¾î·Î ¾î¶² ¿ÜºÎÀÇ ÈûÀ» °¡Çصµ ±× ¼ºÁúÀÌ º¯ÇÏÁö ¾Ê´Â ½Ç ¼¼°è´Â Á¸ÀçÇÏÁö ¾Ê´Â °¡»óÀÇ ¹°Ã¼ÀÔ´Ï´Ù. °Ã¼
¾Ö´Ï¸ÞÀ̼ÇÀ» ȸ鿡 Ç¥ÇöÇÏ¸é µ¿ÀÛÀÌ ·Îº¿Ã³·³ µüµüÇÕ´Ï´Ù.
Mechatronics¸¦ ¹è°æÀ¸·Î °ÔÀÓÀ» ¸¸µç´Ù¸é °Ã¼ ¾Ö´Ï¸ÞÀ̼Ç
¸¸À¸·Îµµ ÃæºÐÇÕ´Ï´Ù. ±×·±µ¥ ÀÌ °Ã¼ ¾Ö´Ï¸ÞÀ̼ÇÀ» »ç¶÷À̳ª µ¿¹°À» ÁÖ¿ä ¼ÒÀç·Î ÇÏ´Â °ÔÀÓ¿¡ Àû¿ëÇϸé
ÆÈ°ú °°Àº °üÀý ºÎÀ§¿¡¼ ÇǺΰ¡ ´Ù¸¥ ÇǺθ¦ ÆÄ°í µé°Å³ª ¹ú¾îÁö´Â Çö»óÀÌ ¸¸µé¾îÁ® ÀÚ¿¬½º·¯¿òÀÌ ¸¹ÀÌ °¨¼ÒµË´Ï´Ù.
ƯÈ÷ °ÝÅõ °ÔÀÓó·³ ij¸¯ÅͰ¡ È¸é °¡µæ ä¿ì´Â »óȲÀ̶ó¸é °Ã¼ ¾Ö´Ï¸ÞÀ̼ÇÀº Á¶±Ý ºÎÁ·ÇÕ´Ï´Ù. °ú°Å¿¡´Â ÀÌ·± ¹®Á¦¸¦ ÆÈÀ̳ª ´Ù¸®¿¡ º¸È£´ë ¶Ç´Â °©¿ÊÀ» µ¡¾º¿ö¼ ÇØ°áÀ» ÇßÀ¸¸ç Áö±Ýµµ ¸¹ÀÌ »ç¿ëÇÏ´Â ¸ÚÁø ¹æ¹ýÀÔ´Ï´Ù. ÃÖ±Ù¿¡´Â Skinning À̶ó´Â ¹æ½ÄÀÌ µµÀÔµÇ¾î °üÀý ºÎÀ§ÀÇ ºÎ
ÀÚ¿¬½º·¯¿î ¸ð½ÀÀ» ¾ø¾Ý½À´Ï´Ù. ÀÌ·Î ÀÎÇØ °ÔÀÓ Ä³¸¯ÅÍÀÇ À°°¨ÀûÀÌ°í ¾ß¼ºÀûÀÎ ¸ð½ÀÀ» ³ªÅ¸³»±â À§ÇØ °ÉÄ¡´Â
¿Ê°¨ÀÇ ¾çÀÌ ¸¹ÀÌ ÁÙ¾ú½À´Ï´Ù.

<°Ã¼ ¾Ö´Ï¸ÞÀ̼ǰú Skinning
¾Ö´Ï¸ÞÀ̼Ç>
Skinning ¾Ö´Ï¸ÞÀÌ¼Ç ±¸ÇöÀº ÀǿܷΠ°£´ÜÇÕ´Ï´Ù. Á¤Á¡À» ±¸¼ºÇÏ´Â Geometry Áß¿¡¼ °üÀý ºÎÀ§¿¡ ÇØ´çÇÏ´Â Á¡µéÀº
ÇØ´ç GeometryÀÇ Çà·Ä»Ó¸¸ ¾Æ´Ï¶ó ÀÎÁ¢ÇÑ GeometryÀÇ
Çà·Äµµ °°ÀÌ Àû¿ëÇÏ´Â °ÍÀÔ´Ï´Ù.
±×¸²¿¡¼ °Ã¼ ¾Ö´Ï¸ÞÀ̼ÇÀÇ Á¤Á¡ p´Â Geometry AÀÇ Çà·Ä¿¡¸¸ ¿µÇâÀ» ¹ÞÁö¸¸ Skinning ¾Ö´Ï¸ÞÀ̼ÇÀÇ
Á¤Á¡ p´Â Geometry BÀÇ Çà·Ä¿¡µµ ¿µÇâÀ» ¹Þ½À´Ï´Ù. Á¤Á¡¿¡ ¿µÇâÀ» ÁÖ´Â Á¤µµ¸¦ ºñÁß(Weight)·Î ¼³Á¤Çؼ ¼ö½ÄÀ¸·Î
Ç¥Çö ÇÏ¸é ´ÙÀ½°ú °°½À´Ï´Ù.
Á¤Á¡ pÀÇ º¯È¯ = (p *
Geometry A Çà·Ä) * Geometry AÀÇ ºñÁß
+ (p *
Geometry B Çà·Ä) * Geometry BÀÇ ºñÁß
´Ü¼øÇÏ°Ô 2°³ÀÇ Çà·Ä ¸¸ °üÀýºÎÀ§ÀÇ Á¤Á¡¿¡ Àû¿ëÇÏ¸é ¹ú¾îÁö°Å³ª °ãÄ¡´Â
¹®Á¦´Â ÇØ°áÀÌ µÇÁö¸¸ ºÎµå·¯¿î °î¸éÀ» ¸¸µé±â°¡ ¾î·Æ½À´Ï´Ù. À̸¦ À§ÇØ ¿©·¯ °³ÀÇ Çà·ÄÀ» ÀûÁ¤¿¡ Àû¿ëÀ»
ÇÕ´Ï´Ù.
Á¤Á¡ pÀÇ º¯È¯ = (p *
Geometry A Çà·Ä) * Geometry AÀÇ ºñÁß
+ (p *
Geometry B Çà·Ä) * Geometry BÀÇ ºñÁß
+ ¡¦
+ (p *
Geometry M Çà·Ä) * Geometry MÀÇ ºñÁß
¼öÇÐ ±âÈ£¸¦ »ç¿ëÇØ¼ Ç¥ÇöÇÏ¸é ¿µÇâÀ» ÁÖ´Â Çà·ÄÀ»
, ºñÁßÀ»
¶ó ÇÏ¸é º¯È¯ ÈÄÀÇ Á¤Á¡ À§Ä¡
´Â ´ÙÀ½°ú °°ÀÌ Ç¥Çö µË´Ï´Ù.

°ýÈ£ ¾ÈÀÇ Á¡
Àº ¥Ò¹ÛÀ¸·Î »©³»¿Ã ¼ö ÀÖÀ¸¹Ç·Î ¼ö½ÄÀ»
Á¤¸®Çϸé
,
, 
ÀÌ µË´Ï´Ù. ¿ìÃøÀÇ ½ÄÀº ÀÌÀüÀÇ ½Äó·³ °¢ Çà·Ä¸¶´Ù Á¤Á¡À» º¯È¯ ½ÃŰ´Â
°ÍÀÌ ¾Æ´Ï¶ó °¢ Çà·Ä¿¡ ´ëÇØ¼
°è»êÀ» ¸ÕÀúÇϰí À̵éÀ» ´õÇÑ ÀüºÎ ´õÇÑ ´ÙÀ½¿¡
Á¤Á¡ÀÇ º¯È¯À» ¼öÇàÇϱ⠶§¹®¿¡ ó¸® ¼Óµµ¿¡ À̵æÀÔ´Ï´Ù. ±×¸®°í ¸ðµç ºñÁßÀÇ ÇÕÀ» 1·Î À¯ÁöÇÕ´Ï´Ù. ¸¸¾à 1º¸´Ù
Å©°Å³ª ÀÛÀ¸¸é Á¤Á¡ÀÇ À§Ä¡¿¡ Å©±â º¯È¯ÀÌ Àû¿ëµÈ °Í°ú °°Àº »óȲÀ» ¸¸µì´Ï´Ù. Á¤Á¡¿¡ ÇϳªÀÇ ºñÁ߸¸ ÀÖ°í
°ªÀÌ 1À̶ó¸é ÀÌ ¾Ö´Ï¸ÞÀ̼ÇÀº °Ã¼ ¾Ö´Ï¸ÞÀ̼ǰú °°½À´Ï´Ù. µû¶ó¼
°Ã¼ ¾Ö´Ï¸ÞÀ̼ÇÀº Skinning ¾Ö´Ï¸ÞÀ̼ÇÀÇ ºÎºÐ ÁýÇÕÀ̶ó ÇÒ ¼ö ÀÖ½À´Ï´Ù.
ÀÌ·¸°Ô °£´ÜÇÑ ¼ö½Ä Á¶Â÷µµ Çϵå¿þ¾î¿¡¼ Áö¿øµÇ±â ½ÃÀÛÇÑ °ÍÀº ÃÖ±ÙÀÇ ÀÏÀÔ´Ï´Ù.
°íÁ¤ ±â´É ÆÄÀÌÇÁ¶óÀο¡¼ D3D´Â ÇϳªÀÇ Á¤Á¡¿¡ ÃÖ´ë 4°³±îÁö ¿µÇâÀ» ÁÖ´Â Çà·ÄÀ» ¼³Á¤ ÇÒ ¼ö ÀÖ°í ÃÖ´ë 255°³±îÁö ¿µÇâÀ»
ÁÖ´Â Çà·ÄµéÀ» ¸¸µé ¼ö ÀÖ½À´Ï´Ù. (½¦ÀÌ´õ¸¦ »ç¿ëÇϸé ÀÌ Á¦ÇÑÀº °ÅÀÇ ¾ø½À´Ï´Ù.) ÇÏÁö¸¸ Çϵå¿þ¾î´Â D3D ¶æ´ë·Î Á¤Á¡¿¡ 4°³ÀÇ Çà·ÄÀ» ¿¬°áÇÒ ¼ö ÀÖÁö¸¸ ¿µÇâÀ» ÁÙ ¼ö ÀÖ´Â Çà·ÄµéÀÇ ÃÑ ¼ö°¡ 255°³°¡
¾ÈµÉ ¼ö ÀÖ½À´Ï´Ù.
±×·¡¼ ¸ÕÀú ÇÁ·Î±×·¥À» Àû¿ëÇϱâ Àü¿¡ Çϵå¿þ¾î¿¡¼ Áö¿øµÇ´Â Çà·ÄÀÇ ÃÖ´ë ¼ýÀÚ¸¦ ´ÙÀ½°ú °°ÀÌ È®ÀÎ ÇÕ´Ï´Ù.
D3DCAPS9 d3dCaps;
m_pDev->GetDeviceCaps(
&d3dCaps );
m_nMaxMatrixSize =
d3dCaps.MaxVertexBlendMatrixIndex;
°£´ÜÇÑ Skinning ¿¹Á¦·Î
"űرâ ÈÖ³¯¸®¸ç" ¸¦ ¸¸µé¾î º¾½Ã´Ù.
¸ÕÀú ´ÙÀ½°ú °°ÀÌ È¸é¿¡ űر⸦ Çϳª Ãâ·ÂÇÕ´Ï´Ù.

<űرâ Á¤Á¡>
űرⰡ ¹Ù¶÷¿¡ Á¦´ë·Î ÆÞ·°À̵µ·Ï Á¤Á¡ ¹öÆÛ¸¦ ±×¸²ÀÇ ¿ÞÂÊó·³ »ï°¢ÇüÀ» 40°³
Á¤µµ »ý¼ºÇÕ´Ï´Ù.
¿ì¸®ÀÇ ¸ñÇ¥´Â ¿ÞÂÊ¿¡ Ç¥½ÃµÈ »ï°¢ÇüÀ» ¿òÁ÷ÀÌ´Â °ÍÀ¸·Î Á¤Á¡ ¸¶´Ù Çà·ÄÀ» °¢°¢ µû·Î ¼³Á¤ÇÒ °ÍÀÔ´Ï´Ù. ¿À¸¥ÂÊ È¸é°ú °°Àº Á¤Á¡À» Ãâ·ÂÇϱâ À§Çؼ °¡Áö´Â ±¸Á¶Ã¼´Â ´ÙÀ½°ú °°À» °ÍÀÔ´Ï´Ù.
struct VtxUV1
{
D3DXVECTOR3 p;
FLOAT u,
v;
enum { FVF = (D3DFVF_XYZ |D3DFVF_TEX1), };
};
ÀÌ ±¸Á¶Ã¼¸¦ °³·®Çؼ Çà·ÄÀÇ À妽º¿Í ºñÁßÀ» ¼³Á¤ÇÕ´Ï´Ù. ¿¹¸¦ µé¾î
Á¤Á¡ Çϳª¿¡ ¿µÇâÀ» ÁÖ´Â Çà·ÄÀ» µÎ °³·Î ¼³Á¤ÇÑ´Ù¸é Á¤Á¡ ±¸Á¶Ã¼´Â ´ÙÀ½°ú °°ÀÌ ¸¸µé¾î¾ß ÇÕ´Ï´Ù.
struct VtxUV1
{
D3DXVECTOR3 p;
FLOAT g; // ºñÁß(Weight)
BYTE m[4]; // Çà·ÄÀÇ À妽º
¡¦
enum { FVF = (D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4 | ¡¦), };
};
±¸Á¶Ã¼¸¦ º¸¸é ºñÁßÀº floatÇü
1°³·Î ¼³Á¤µÇ¾î ÀÖ½À´Ï´Ù. À̰ÍÀº Çϳª¸¦ ¼³Á¤ÇÏ¸é ³ª¸ÓÁö Çϳª´Â ÆÄÀÌÇÁ¶óÀο¡¼ 1.0f - g °ªÀ¸·Î ÀÚµ¿ °è»ê µË´Ï´Ù. Çà·ÄÀÇ À妽º´Â m º¯¼ö¿¡ ÀúÀåÇÕ´Ï´Ù.
FVF¿¡¼ XYZ µÚ¿¡ B2°¡ ºÙ¾ú½À´Ï´Ù. À̰ÍÀº
Blending À妽ºÀÇ °³¼ö°¡ 2¸¦ ÀǹÌÇϸç Çà·ÄÀÇ À妽º 4¹ÙÀÌÆ® m¸¦ ÇÏÀ§ ¹ÙÀÌÆ®ºÎÅÍ index0,
index 1 µÎ °³ÀÇ À妽º »ç¿ëÀ» ¶æÇÕ´Ï´Ù.
D3DFVF_LASTBETA_UBYTE4´Â ¾ÕÀÇ ±¸Á¶Ã¼Ã³·³ ºñÁß°ú
À妽º¸¦ µ¿½Ã¿¡ °¡Áö°í ÀÖÀ» ¶§ ¸¶Áö¸· °ªÀ» unsigned byte 4°³¸¦ À妽º·Î »ç¿ëÇÔÀ» ÀǹÌÇÕ´Ï´Ù. °ÅÀÇ ÀÌ Æ÷¸ËÀ» »ç¿ëÇϱ⠶§¹®¿¡ ¹öÅØ½º¿¡ Çà·ÄÀ» ¿©·¯ °³ ¼³Á¤ÇÒ ¶§´Â ÀÌ Ç÷¡±×´Â °íÁ¤À̶ó »ý°¢ÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù.
ÀÌ·¸°Ô Á¤Á¡¿¡ Çà·ÄÀÇ À妽º¸¦ Àû¿ëÇØ¼ SkinningÀ» ±¸ÇöÇϱâ
¶§¹®¿¡ (Matrix) Indexed ¹æ½Ä ¶Ç´Â Matrix
Palette ¹æ½ÄÀÇ Á¤Á¡ ºí·»µù(Blending) À̶ó ºÎ¸¨´Ï´Ù.
¾ÆÁ÷ Àͼ÷ÇÏÁö ¾ÊÀ¸´Ï ºñ½ÁÇÑ ¿¹¸¦ Çϳª ´õ ¸¸µé¾îº¾½Ã´Ù. Á¤Á¡¿¡ ¿µÇâÀ»
ÁÖ´Â Çà·ÄÀÌ 3°³ÀÎ Á¤Á¡ ±¸Á¶Ã¼¿Í FVF´Â ±¸¼ºÇÒ±î¿ä?
struct VtxUV1
{
D3DXVECTOR3 p;
D3DXVECTOR2 g; // ºñÁß(Weight)
DWORD m;
// Çà·ÄÀÇ À妽º
¡¦
enum { FVF = (D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4 | ¡¦), };
};
´Ù½Ã űر⠹®Á¦·Î µ¹¾Æ°¡¼ Çà·ÄÀ» 4°³ ¼³Á¤À» ÇÒ ¼ö ÀÖ°í, ÅØ½ºÃ³ÀÇ ÁÂÇ¥°¡ Àû¿ëµÇ´Â ±¸Á¶Ã¼´Â ´ÙÀ½°ú °°À» °ÍÀÔ´Ï´Ù.
struct VtxBlend
{
D3DXVECTOR3 p; // Á¤Á¡ÀÇ º¯È¯µÈ ÁÂÇ¥
FLOAT g[3]; // blend weight
BYTE m[4]; // Index
FLOAT u,
v; // UV
¡¦
enum { FVF = (D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4
| D3DFVF_TEX1), };
};
ÀÌ ±¸Á¶Ã¼¸¦ ¹Þ¾ÆµéÀÌ´Â ÆÄÀÌÇÁ¶óÀÎÀº Çà·ÄÀ» ´ÙÀ½°ú °°ÀÌ °è»êÀ» ÇÑ ´ÙÀ½ Á¤Á¡ÀÇ À§Ä¡¸¦ º¯È¯ÇÕ´Ï´Ù.

´ÙÀ½À¸·Î űرâÀÇ Á¤Á¡¿¡ ¿µÇâÀ» ÁÖ´Â Çà·Ä ¹è¿ÀÇ Å©±â¸¦ D3D°¡
Áö¿øÇÏ´Â ÃÖ´ë °ªÀ¸·Î ¼³Á¤ÇÕ´Ï´Ù.
D3DXMATRIX m_mtWld[256];
´ÙÀ½À¸·Î Á¤Á¡ µ¥ÀÌÅ͸¦ ¸¸µé ¶§ ºñÁß°ú Çà·Ä À妽º¸¦ ¿¬°áÇÕ´Ï´Ù. Áö±ÝÀº
Á¤Á¡¿¡ ¼øÂ÷ÀûÀ¸·Î Çà·ÄÀ» Àû¿ëÇϰí ÀÖÁö¸¸ ÀÌ·± ¹æ¹ýÀº Ưº°ÇÑ °æ¿ìÀÔ´Ï´Ù.
for(¡¦)
¡¦
m_pVtx[2*i + 0].g[0] = 1.0F; // ºñÁß
m_pVtx[2*i + 0].m[0] = i; // Çà·Ä À妽º
m_pVtx[2*i + 1].g[0] = 1.0F; // ºñÁß
m_pVtx[2*i + 1].m[0] = i; // Çà·Ä Àε¥½º
¸Å ÇÁ·¹ÀÓ ¸¶´Ù Çà·ÄÀ» °»½ÅÇÕ´Ï´Ù.
FLOAT fAngle = GetTickCount() * 0.4f;
for(i=0; i<256; ++i)
{
float fTheta = fAngle + i
* (360.f/15);
m_mtWld[i]._41
= cosf( D3DXToRadian(fTheta) )
* 1.5f;
m_mtWld[i]._42
= sinf( D3DXToRadian(fTheta) )
* 4.0f;
}
·»´õ¸µ¸¸ ³²¾Ò½À´Ï´Ù. ¸ÕÀú ÇÁ·Î±×·¥ ½ÃÀÛÇÒ ¶§ Çϵå¿þ¾î¿¡¼ Áö¿øµÇ´Â
Çà·ÄÀÇ ÃÖ´ë ¼ýÀÚ¸¦ °¡Áö°í Áö±ÝÀÇ Çà·ÄÀÇ °³¼ö°¡ À̺¸´Ù Ŭ °æ¿ì¿¡´Â ´ÙÀ½°ú °°ÀÌ ¼ÒÇÁÆ®¿þ¾î ¹öÅØ½º ÇÁ·Î¼¼½ÌÀ» È£ÃâÇÕ´Ï´Ù.
if(m_nMaxMatrixSize<128)
m_pDev->SetSoftwareVertexProcessing(TRUE);
SetSoftwareVertexProcessing() ÇÔ¼ö´Â MIXED_VERTEX_PROCESSING¿¡¸¸ Àû¿ëÀÌ µË´Ï´Ù. µû¶ó¼ MIXED·Î µð¹ÙÀ̽º¸¦ »ý¼ºÇϰųª ¾Æ´Ï¸é
SOFTWARE_VERTEX_PROCESSINGÀ¸·Î µð¹ÙÀ̽º¸¦ ¸¸µé¾î¾ß ÇÕ´Ï´Ù. ´ÙÀ½¿¡
º¸¿©ÁÙ ¿¹Á¦´Â MIXED·Î µð¹ÙÀ̽º¸¦ ¸¸µé¾ú½À´Ï´Ù.
´ÙÀ½À¸·Î À妽º¿¡ ÀÇÇÑ ¹öÅØ½º ºí·»µùÀ» Ȱ¼ºÈÇÕ´Ï´Ù.
m_pDev->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE );
¶ÇÇÑ ¹öÅØ½º ºí·»µùÀÇ ºñÁß¿¡ ´ëÇÑ ÃÖ´ë À妽º¸¦ ÁöÁ¤ÇÕ´Ï´Ù. ±¸Á¶Ã¼¿¡¼ Çà·Ä¿¡ ´ëÇØ¼ 4°³ÀÇ À妽º¸¦ ÁöÁ¤Çϰí ÀÖÀ¸¹Ç·Î 0,1,2,3¿¡¼ 3ÀÇ °ªÀ» ¼±ÅÃÇØ ´ÙÀ½°ú °°ÀÌ µð¹ÙÀ̽º¿¡ Àû¿ëÇÕ´Ï´Ù.
m_pDev->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_3WEIGHTS );
Çà·Ä ¹è¿À» µð¹ÙÀ̽º¿¡ ¼³Á¤ÇÏ°í ¿ÀºêÁ§Æ®¸¦ ·»´õ¸µ ÇÕ´Ï´Ù.
for(i=0; i<256; ++i)
m_pDev->SetTransform( D3DTS_WORLDMATRIX(i),
&m_mtWld[i] );
¡¦
m_pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 40, m_pVtx, sizeof(VtxBlend));
µð¹ÙÀ̽º¸¦ ¿ø»óÅ·ΠµÇµ¹·Á ³õ½À´Ï´Ù.
m_pDev->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
m_pDev->SetRenderState( D3DRS_VERTEXBLEND, D3DVBF_DISABLE
);
m_pDev->SetSoftwareVertexProcessing(FALSE);
// µð¹ÙÀ̽ºÀÇ Çà·Ä ÃʱâÈ
static D3DXMATRIX mtIdentity( 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1);
for(i=0; i<256; ++i)
m_pDev->SetTransform( D3DTS_WORLDMATRIX(i),
&mtIdentity);
Àüü ÄÚµå´Â daux08_skinning01.zipÀ»
Âü°íÇϽʽÿÀ. À̸¦ ½ÇÇàÇÏ¸é ´ÙÀ½°ú °°Àº ȸéÀ» ¾òÀ» ¼ö ÀÖ½À´Ï´Ù.

<Skinning űر⠿¹Á¦:
daux08_skinning01.zip>
3.8.2 Modified SkinnedMesh
DXSDK SampleÀÇ
SkinnedMesh´Â X-fileÀÇ Á¤º¸¸¦ ¹Þ¾Æ¼
SkinningÀ¸·Î ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸ÇöÇÑ ¿¹Á¦ÀÔ´Ï´Ù.
¿¹Á¦´Â ÆÄÀÏ¿¡¼ ¾Ö´Ï¸ÞÀÌ¼Ç Á¤º¸¸¦ ¸¸µå´Â CAllocateHierarchy Ŭ·¡½º, Àå¸éÀÇ ·»´õ¸µ¿¡ ÇÊ¿äÇÑ ¸Þ½¬, ÅØ½ºÃ³, ÀçÁú, Çà·Ä µîÀ» °¡Áø D3DXMESHCONTAINER
Ŭ·¡½º, ¸Þ½¬ ÄÁÅ×À̳ʵéÀ» ¸ð¾Æ¼ ÇϳªÀÇ ³ª¹« ±¸Á¶(Tree
Structure)¸¦ ¸¸µå´Â D3DXFRAME ¼¼ ºÎºÐÀ¸·Î ±¸¼ºµÇ¾î ÀÖ°í, Skinning¿¡ ´ëÇÑ ¾Ö´Ï¸ÞÀ̼ÇÀ» Non-Index, Indexed, Á¤Á¡
½¦ÀÌ´õ(Vertex Shader), °í ¼öÁØ ½¦ÀÌ´õ(HLSL) ÃÑ 4°³ÀÇ ¹æ½Ä Áß¿¡¼ Çϳª¸¦ ¼±ÅÃÇØ¼ Àû¿ëÇØ º¼ ¼ö ÀÖ½À´Ï´Ù.

<SkinnedMesh ¿¹Á¦ÀÇ ¼öÁ¤µÈ ÀÚ·á ±¸Á¶>
Non-Index´Â ±âº»ÀûÀ¸·Î Indexed
¹æ½ÄÀ¸·Î ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸ÇöÇÏÁö¸¸ Á¤Á¡¿¡ ¼³Á¤µÈ Çà·ÄÀÇ À妽º°¡ Çϵå¿þ¾î¿¡¼ Áö¿øµÇ´Â ÃÖ´ë Å©±â¸¦ ³Ñ¾î¼´Â °æ¿ì¿¡ ¼ÒÇÁÆ®¿þ¾î(CPU)·Î Á¤Á¡ÀÇ Ã³¸®Çϵµ·Ï Äڵ尡 ±¸¼ºµÇ¾î ÀÖ½À´Ï´Ù. ¾Õ¼ űرâ
¿¹Á¦¿¡¼ ÀÌ·± ¹æ¹ýÀ» À§Çؼ µð¹ÙÀ̽ºÀÇ SetSoftware-VertexProcessing() ÇÔ¼ö¸¦
È£ÃâÇÑ ÀûÀÌ ÀÖ½À´Ï´Ù. À̰ÍÀÌ Áö¿øµÇ·Á¸é MIXED·Î µð¹ÙÀ̽º¸¦
»ý¼ºÇØ¾ß ÇÑ´Ù°í Çß°í, ÀÌ ¶§¹®¿¡ SkinnedMesh ¿¹Á¦µµ MIXED·Î µð¹ÙÀ̽º¸¦ ¸¸µé¾úÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.
ÀÌ ¿¹Á¦¸¦ ±×´ë·Î »ç¿ëÇϱâ´Â ¹«Ã´ ¾î·Æ½À´Ï´Ù. ±×·¡¼ Äڵ带 °ÔÀÓ¿¡
Àû¿ëÇÒ ¼ö ÀÖµµ·Ï Àç¹èÄ¡ ÇØ¾ß ÇÕ´Ï´Ù. daux08_skinning02.zip´Â
ÀÌ ¿¹Á¦¸¦ °ÔÀÓ ÇÁ·Î±×·¥¿¡ Àû¿ëÇÒ ¼ö ÀÖµµ·Ï ¼öÁ¤ÇÑ ¿¹ÀÔ´Ï´Ù.
Äڵ带 Àç¹èÄ¡ ÇÏ¸é¼ Shader ºÎºÐÀº °ú°¨È÷ »ý·«Çϰí, Indexed ¹æ½Äµµ Non-Index¿¡ Æ÷ÇԵǾî ÀÖÀ¸¹Ç·Î ÀÌ ºÎºÐµµ
Á¦°ÅÇß½À´Ï´Ù. ÀÌÀüÀÇ X-fileÀ» Ŭ·¡½º·Î ¸¸µé ¶§Ã³·³
±¸Á¶´Â °ÅÀÇ ±×´ë·Î µÎ°í(º¯¼ö À̸§°ú ÇÔ¼ö À̸§Àº ÀϺΠ¹Ù²Ù¾ú½À´Ï´Ù.)
¸î °³ÀÇ ÀÎÅÍÆäÀ̽º¿Í Ŭ·¡½º¸¦ Ãß°¡ÇÏ¿© ¾ÕÀÇ ±×¸²°ú °°Àº ±¸Á¶·Î º¯°æÇؼ ¸¸µç ¿¹°¡ daux08_skinning02.zipÀÔ´Ï´Ù.
ILcMdlÀº X-fileÀÇ Skinning¿¡ ´ëÇÑ ÃÖ»óÀ§ Ŭ·¡½º·Î ÀÎÅÍÆäÀ̽º ¿ªÇÒÀ» ÇÕ´Ï´Ù. À̸¦
»ó¼Ó¹ÞÀº CLcXSkin Ŭ·¡½º´Â ¾Ö´Ï¸ÞÀ̼ǿ¡ ÇÊ¿äÇÑ ½Ã°£°ú °´Ã¼¿¡ ´ëÇÑ ¿ùµå Çà·ÄÀÇ ¸â¹ö º¯¼ö¸¦ °¡Áö°í
ÀÖ°í À̵éÀ» ¼³Á¤Çϰųª ÂüÁ¶ÇÒ ¼ö ÀÖ´Â ¸â¹ö ÇÔ¼ö¸¦ ´ÙÀ½°ú °°ÀÌ °¡Áö°í ÀÖ½À´Ï´Ù.
class CLcXSkin : public ILcMdl
¡¦
D3DXMATRIX m_mtWorld ; // °´Ã¼ÀÇ ¿ùµå Çà·Ä
DOUBLE m_dTimeCur ; // °´Ã¼ÀÇ ½Ã°£
¡¦
virtual INT SetAttrib(char* sCmd, void* pVal);
virtual INT GetAttrib(char* sCmd, void* pVal);
virtual INT SetPosition(FLOAT* float3);
virtual INT GetPosition(FLOAT* float3);
¼Ó¼ºÀÌ ¸¹¾Æ Áö¸é ÀÌ¿¡ ´ëÇÑ ÇÔ¼öµµ Áõ°¡ÇÒ ¼ö ÀÖ¾î Äڵ尡 ¾û¸ÁÀÌ µÇ±â ½±½À´Ï´Ù. °£´ÜÇÑ µ¥ÀÌÅÍ¿¡ ´ëÇÑ ¼³Á¤°ú ÂüÁ¶´Â ÇϳªÀÇ ÇÔ¼ö¿¡¼ ´ÙÀ½°ú °°ÀÌ Ã³¸®ÇÏ´Â °ÍÀÌ Àüü ±¸Á¶¸¦ Àß °¡Áö°í °¥ ¼ö
ÀÖ´Â ºñ°áÀÔ´Ï´Ù.
INT CLcXSkin::SetAttrib(char* sCmd, void* pVal)
{
if(0 ==_stricmp(sCmd, "World Matrix"))
{
m_mtWorld
=*((D3DXMATRIX*)pVal);
return 0;
}
else if(0 ==_stricmp(sCmd, "Elapsed Time"))
{
FLOAT fTime =*((FLOAT*)pVal);
m_dTimeCur
+= fTime;
return 0;
}
¡¦
}
INT CLcXSkin::GetAttrib(char* sCmd, void* pVal)
{
if(0 ==_stricmp(sCmd, "World Matrix"))
{
*((D3DXMATRIX*)pVal) =
m_mtWorld;
return 0;
}
else if(0 ==_stricmp(sCmd, "Current Time"))
{
*((DOUBLE*)pVal) =
m_dTimeCur;
return 0;
}
¡¦
}
³»ºÎ¿¡¼ if ~ elseÀÇ Áõ°¡´Â ¾î¿ ¼ö ¾øÁö¸¸ ¹Û¿¡¼ º¸´Â Ŭ·¡½ºÀÇ
¿ÜÇüÀû ±¸Á¶´Â °£°áÇÕ´Ï´Ù.
¸Þ½¬, ¾Ö´Ï¸ÞÀÌ¼Ç Á¤º¸, ³ª¹«
±¸Á¶(Tree Structure)¸¦ ±¸¼ºÇÏ´Â CLcXSkinSrc Ŭ·¡½º´Â
´ÙÀ½°ú °°ÀÌ ¾Ö´Ï¸ÞÀÌ¼Ç Á¦¾î¿¡ ´ëÇÑ °´Ã¼¿Í Çà·ÄÀÇ ¹è¿À» °¡Áö°í ÀÖ½À´Ï´Ù.
class CLcXSkinSrc : public CLcXSkin
¡¦
SFrame* m_pFrameRoot ; // Root
LPD3DXANIMATIONCONTROLLER m_pAC ; // Animation Controller
UINT m_NumBoneMatricesMax; // Çà·Ä À妽ºÀÇ ¼ö
D3DXMATRIX* m_pBoneMatrices ; // Çà·ÄÀÇ ¹è¿
¡¦
virtual INT Create();
void UpdateFrameMatrices();
void DrawFrame();
void RenderNonIndexed();
CLcXSkinSrc::Create() ÇÔ¼ö´Â D3DXLoadMeshHierarchyFromX() ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼ ¸Þ½¬¿Í °èÃþ ±¸Á¶(hierarchy)¸¦ °¡Á®¿É´Ï´Ù. ÀÌ ÇÔ¼ö´Â »ç¿ëÀÚ°¡ ID3DXAllocateHierarchy »ó¼Ó ¹Þ´Â Ŭ·¡½º¸¦ Á¤ÀÇÇÑ ÀڷḦ Àμö·Î ¹Þ½À´Ï´Ù. »ç¿ëÀÚ´Â ´ÙÀ½ÀÇ ¼¼ ÇÔ¼ö¿¡ ´ëÇØ¼ ¹Ýµå½Ã ±¸ÇöÇØ¾ß ÇÕ´Ï´Ù.
class CLcXSkinAlloc: public ID3DXAllocateHierarchy
¡¦
public:
virtual HRESULT CreateFrame();
virtual HRESULT CreateMeshContainer();
virtual HRESULT DestroyFrame();
virtual HRESULT DestroyMeshContainer();
À̵é ÇÔ¼ö´Â D3DXLoadMeshHierarchyFromX() ÇÔ¼ö¿¡¼
È£ÃâµÇ¸ç ´ÙÀ½°ú °°Àº ¿ªÇÒÀ» ÇÕ´Ï´Ù.
CreateFrame(): FrameÀ» ¸Þ¸ð¸®¿¡ »ý¼ºÇÒ ¶§ È£ÃâÇÕ´Ï´Ù.
CreateMeshContainer(): ¸Þ½¬ ÄÁÅ×À̳ʸ¦ ¸Þ¸ð¸®¿¡
»ý¼ºÇÒ ¶§ È£ÃâÇÕ´Ï´Ù.
DestroyFrame(): »ý¼ºÇÑ
FrameÀ» ÇØÁ¦ÇÒ ¶§ È£ÃâÇÕ´Ï´Ù.
DestoryMeshContainer(): »ý¼ºÇÑ ¸Þ½¬ ÄÁÅ×À̳ʸ¦
ÇØÁ¦ÇÒ ¶§ È£ÃâÇÕ´Ï´Ù.
Äڵ带 ¿Å±â¸é¼ Mesh Container ±¸Á¶¸¦ »ó¼Ó¿¡¼ µ¶¸³µÈ
Ŭ·¡½º·Î ¹Ù²Ù¾ú½À´Ï´Ù. ÀÌ Mesh Container´Â Àå¸éÀ» ¸¸µå´Â °´Ã¼·Î ¸Þ½¬, º¯È¯¿¡ ÇÊ¿äÇÑ Çà·ÄÀÇ Æ÷ÀÎÅÍ, ÀçÁú(Material), Texture µîÀ» Æ÷ÇÔÇϰí ÀÖ½À´Ï´Ù.
struct SMeshContainer //: D3DXMESHCONTAINER
¡¦
D3DXMESHDATA
MeshData;
LPD3DXMATERIAL
pMaterials;
DWORD
NumMaterials;
LPDIRECT3DTEXTURE9* ppTextures;
// array of textures
// Skin Mesh
info
DWORD
NumAttributeGroups;
DWORD
NumInfl; // ÄÁÅ×À̳ʿ¡ ¿µÇâÀ» ÁÖ´Â
Çà·ÄÀÇ ¼ö
LPD3DXBUFFER
pBoneCombinationBuf;
D3DXMATRIX**
m_pBoneMatrix;
Frame °´Ã¼´Â °èÃþÀûÀÎ ³ª¹«(Tree)
±¸Á¶¸¦ Çü¼ºÇÏ´Â °´Ã¼·Î ³ëµå(Node)ÀÇ Æ÷ÀÎÅ͵é°ú ÇÔ²² Àå¸é°ú ¾Ö´Ï¸ÞÀ̼ÇÀ» ±¸¼ºÇϱâ À§ÇÑ
º¯È¯ Çà·Ä, ¸Þ½¬ Æ÷ÀÎÅÍ µîÀ» Æ÷ÇÔ ÇÑ °´Ã¼ÀÔ´Ï´Ù. Root ³ëµåºÎÅÍ
³Êºñ ¿ì¼± Ž»ö(breadth-first search: BFS)À¸·Î Çà·ÄÀ» °»½ÅÇϰí, Mesh Container Æ÷ÀÎÅ͸¦ ÀÌ¿ëÇØ¼ ·»´õ¸µÀ» ¼öÇà ÇÕ´Ï´Ù.
struct SFrame //: public D3DXFRAME
¡¦
D3DXMATRIX tmMatrix; // Áö¿ª ÁÂÇ¥°èÀÇ Çà·Ä
SMeshContainer* pmcMesh; // ·»´õ¸µ¿¡ ´ëÇÑ ¸Þ½¬ ÄÁÅ×À̳Ê
SFrame* pFrameSibling; // ÀÌ¿ô ÇüÁ¦ ³ëµå
SFrame* pFrameFirstChild;// ù ¹øÂ° ÀÚ½Ä ³ëµå
D3DXMATRIX tmWorld; // ¿ùµå Çà·Ä = tmMatrix * ºÎ¸ð Çà·Ä
SFrame *FindFrame(char *szFrame);
CLcXSkinSrc::UpdateFrameMatrices() ÇÔ¼ö¸¦
º¸¸é Frame °´Ã¼ÀÇ ¿ùµå Çà·ÄÀ» ÀÚ½ÅÀÇ Áö¿ª Çà·Ä°ú ºÎ¸ðÀÇ ¿ùµå Çà·Ä °öÀ¸·Î ¸¸µé°í ÀÖ°í ÇüÁ¦ ³ëµå¿Í
ÀÚ½Ä ³ëµå¿¡ ´ëÇØ¼ BFS·Î ³ëµå¸¦ ã¾Æ°¡ µ¥ÀÌÅ͸¦ °»½ÅÇϰí ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.
if (pParentMatrix != NULL)
D3DXMatrixMultiply(&pFrame->tmWorld,
&pFrame->tmMatrix, pParentMatrix);
else
pFrame->tmWorld
= pFrame->tmMatrix;
if
(pFrame->pFrameSibling != NULL)
UpdateFrameMatrices(pFrame->pFrameSibling,
pParentMatrix);
if
(pFrame->pFrameFirstChild != NULL)
UpdateFrameMatrices(pFrame->pFrameFirstChild,
&pFrame->tmWorld);
·»´õ¸µµµ CLcXSkinSrc::DrawFrame()ÇÔ¼ö¸¦ º¸¸é BFS·Î ÁøÇàÇϰí ÀÖ½À´Ï´Ù.
pMeshContainer = pFrame->pmcMesh;
while (pMeshContainer != NULL)
{
DrawMeshContainer(pMeshContainer,
pFrame);
pMeshContainer
= pMeshContainer->pNextMeshContainer;
}
if
(pFrame->pFrameSibling != NULL)
DrawFrame(pFrame->pFrameSibling);
if
(pFrame->pFrameFirstChild != NULL)
DrawFrame(pFrame->pFrameFirstChild);
ÇÁ·Î±×·¥¿¡¼ ·»´õ¸µ°ú ¾Ö´Ï¸ÞÀÌ¼Ç Á¤º¸¸¦ °¡Áö°í ÀÖ´Â CDXSkinSrc Ŭ·¡½ºÀÇ
ÀνºÅϽº¸¦ ÂüÁ¶Çؼ Àå¸éÀ» ±¸¼ºÇÏ´Â CDXSkinInst Ŭ·¡½º´Â ´ÙÀ½°ú °°Àº °£´ÜÇÑ ±¸Á¶·Î ±¸¼ºÀÌ
µË´Ï´Ù.
class CLcXSkinIns : public CLcXSkin
¡¦
CLcXSkinSrc* m_pOrg; // Original Pointer
LPD3DXANIMATIONCONTROLLER m_pAC; // Animation Controller
SFrame* m_pFrameRoot; // Root Frame
¡¦
virtual INT Create(void* =0, void* =0, void* =0, void* =0);
virtual void Destroy();
virtual INT FrameMove();
virtual void Render();
Root FrameÀº ¸Å¹ø
Original¿¡¼ °¡Á®¿À´Â ¹ø°Å·Î¿òÀ» ¾ø¾Ö±â À§ÇØ ¸¸µç º¯¼ö ÀÔ´Ï´Ù. INT
CLcXSkinIns::Create() ÇÔ¼ö¸¦ º¸¸é Animation Controller¸¦
º¹Á¦ÇÏ°í »ç¿ëÀÇ Æí¸®¸¦ À§ÇØ Original·ÎºÎÅÍ ÇÊ¿äÇÑ Á¤º¸¸¦ ¾ò½À´Ï´Ù.
INT CLcXSkinIns::Create(¡¦)
¡¦
m_pOrg
= (CLcXSkinSrc*)p3;
m_pFrameRoot
= (SFrame*)m_pOrg->GetRootFrame();
LPD3DXANIMATIONCONTROLLER pAC
=
(LPD3DXANIMATIONCONTROLLER)m_pOrg->GetAnimationController();
UINT
MaxNumAnimationOutputs = pAC->GetMaxNumAnimationOutputs();
UINT MaxNumAnimationSets =
pAC->GetMaxNumAnimationSets();
UINT MaxNumTracks =
pAC->GetMaxNumTracks();
UINT MaxNumEvents =
pAC->GetMaxNumEvents();
pAC->CloneAnimationController( MaxNumAnimationOutputs
,
MaxNumAnimationSets
,
MaxNumTracks
,
MaxNumEvents
,
&m_pAC);
·»´õ¸µÀº Animation ColtrollerÀÇ AdvanceTime () ÇÔ¼ö¿¡ Àüü Àå¸éÀ» 1 ÇÁ·¹ÀÓ ·»´õ¸µ Çϴµ¥
¼Ò¸ðµÈ ½Ã°£À» Àμö·Î Àü´ÞÇÏ¸é¼ ½ÃÀÛÇÕ´Ï´Ù. ¸¸¾à ÇÑ Àå¸é¿¡ µé¾ú´ø ½Ã°£ ´ë½Å ÃÑ ½Ã°£À» »ç¿ëÇÑ´Ù¸é
´ÙÀ½°ú °°ÀÌ TrackÀÇ À§Ä¡¸¦ 0À¸·Î ¼³Á¤ÇØ¾ß ÇÕ´Ï´Ù. ´ÙÀ½À¸·Î OriginalÀÇ
UpdateFrame-Matrices() ÇÔ¼ö¿Í DrawFrame() ÇÔ¼ö¸¦ ¼øÂ÷ÀûÀ¸·Î
È£ÃâÇØ¼ Àå¸éÀ» ±×¸³´Ï´Ù.
void CLcXSkinIns::Render()
¡¦
m_pAC->SetTrackPosition(0,
0);
m_pAC->AdvanceTime(m_dTimeCur, NULL);
m_pOrg->UpdateFrameMatrices(m_pFrameRoot, &m_mtWorld);
m_pOrg->DrawFrame(m_pFrameRoot);
CMain Ŭ·¡½º¿¡´Â ILcMdl¿¡
´ëÇÑ Original °´Ã¼ 1°³¿Í À̸¦ ÂüÁ¶Çؼ ¸¸µé 3°³ÀÇ ILcMdl °´Ã¼¸¦ ¼±¾ðÇϰí CMain::Init() ÇÔ¼ö¿¡¼ ÀÖ½À´Ï´Ù. LcMdl_Create()ÇÔ¼ö¿¡
ÆÄÀÏ À̸§À¸·Î OriginalÀ» ¸¸µé°í OriginalÀ»
Àμö·Î Àü´ÞÇØ¼ ³ª¸ÓÁö 3°³ÀÇ °´Ã¼¸¦ ¸¸µé°í ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù.
LcMdl_Create(NULL, &m_pDXMeshOrg, m_pd3dDevice, m_strMeshFilename);
LcMdl_Create(NULL,
&m_pDxMeshIns1, m_pd3dDevice, NULL, m_pDXMeshOrg);
LcMdl_Create(NULL,
&m_pDxMeshIns2, m_pd3dDevice, NULL, m_pDXMeshOrg);
LcMdl_Create(NULL,
&m_pDxMeshIns3, m_pd3dDevice, NULL, m_pDXMeshOrg);
LcMdl_Create() ÇÔ¼ö´Â ¾Ö´Ï¸ÞÀ̼ÇÀÌ ¾ø´Â X-file¿Í ºñ½ÁÇÏ°Ô ÆÄÀÏÀ̸§ÀÌ ÀÖÀ¸¸é ¿øº» °´Ã¼¸¦ ¸¸µé°í ¿øº» °´Ã¼ÀÇ ÁÖ¼Ò°¡ ¿À¸é À̸¦ ÂüÁ¶ÇÏ´Â °´Ã¼¸¦ ¸¸µì´Ï´Ù.
INT LcMdl_Create(char* sCmd , ILcMdl** pData // Output Data
,
void* p1 // Device
,
void* p2 // File Name
,
void* p3 // Source Model
,
void* p4 )
{
ILcMdl* pObj = NULL;
*pData
= NULL;
if( NULL != p2) pObj
= new CLcXSkinSrc;
else if(NULL != p3) pObj
= new CLcXSkinIns;
else return -1;
if(FAILED(pObj->Create(p1, p2, p3,
p4)))
{
delete pObj; return -1;
}
*pData
= pObj;
return 0;
}
ÀÌ daux08_skinning02.zip¸¦ ½ÇÇàÇÏ¸é ´ÙÀ½°ú °°ÀÌ ¼·Î ´Ù¸¥
½Ã°£¿¡ ¾Ö´Ï¸ÞÀ̼ÇÀ» ÇÏ´Â 3°³ÀÇ °´Ã¼¸¦ º¼ ¼ö ÀÖ½À´Ï´Ù.

<Modified
SkinnedMesh: daux08_skinning02.zip>
Äڵ带 ÀüȯÇÏ¸é¼ °¡Àå ¾î·Á¿ü´ø °ÍÀº µ¥ÀÌÅÍÀÇ °»½Å°ú ·»´õ¸µÀÌ ºÐ¸®°¡ ¾ÈµÇ¾î ÀÖ´Â Á¡°ú ¾Ö´Ï¸ÞÀÌ¼Ç ¼³Á¤ÀÌ ½±Áö°¡
¾Ê´Ù´Â °ÍÀÔ´Ï´Ù. Animation SetÀÌ ¿©·¯ °³ ÀÖÀ» °æ¿ì 0¹ø SetÀ¸·Î µÎ¸é ´Ù¸¥ °´Ã¼¿¡ ¿µÇâÀ» ÁÖ¾î ÇÒ ¼ö ¾øÀÌ ¸¶Áö¸· SetÀ¸·Î
¾Ö´Ï¸ÞÀ̼ÇÀ» °áÁ¤ÇØ¾ß Çß½À´Ï´Ù.
if(m_nAniMax)
m_pAC->SetTrackAnimationSet(0, m_vAS[m_nAniMax - 1]);
¿Ïº®ÇÏÁö´Â ¾ÊÁö¸¸ Á¦´ë·Î µÈ ¶óÀ̺귯¸®¸¦ ¾ò±â Àü±îÁö ¾µ¸¸ÇÏ´Ù°í
»ý°¢µÇ¸ç, ƯÈ÷ ¾Ö´Ï¸ÞÀ̼ÇÀ» óÀ½ Á¢ÇÏ´Â ºÐµé¿¡°Ô µµ¿òÀÌ µÇ¸®¶ó »ý°¢µË´Ï´Ù.
3.9 2D Sprite
3.9.1 RHW Sprite
3D ±âÃÊ¿Í °ÔÀÓ ÇÁ·Î±×·¥¿¡ ÇÊ¿äÇÑ ¾Ö´Ï¸ÞÀ̼DZîÁöÀÇ Áö½Ä¸¸À¸·Îµµ 3D °ÔÀÓÀ» ¾ó¸¶µçÁö ¸¸µé ¼ö ÀÖ½À´Ï´Ù. ±×·±µ¥ ´ëºÎºÐ 3D¸¦ ¹è¿ö³õ°íµµ ¹«¾ùÀ» ÇØ¾ß ÇÒÁö ¸·¸·ÇÒ ¶§°¡ ¸¹ÀÌ ÀÖ½À´Ï´Ù. ÀÌ·²
¶§ ±ÇÇÏ°í ½ÍÀº °ÍÀÌ ID3DXSprite¸¦ 3D·Î ¸¸µé¾î
º¸´Â °ÍÀÔ´Ï´Ù. 3D °ÔÀÓ¿¡¼ ȸéÀÇ UI(User
Interface)¸¦ ±¸¼ºÇÒ ¶§ 2D Sprite¸¦ »ç¿ëÇϰí ID3DXSprite¸¦ ´ëºÎºÐ »ç¿ëÇÕ´Ï´Ù. ±×·±µ¥ ID3DXSprite¶ó´Â °ÍÀÌ D3D ¶Ç´Â D3DX ¹öÀü ¸¶´Ù ¾à°£ÀÇ Â÷À̰¡ ÀÖ½À´Ï´Ù. ¸¸¾à 3D·Î 2D Sprite¸¦ ±¸ÇöÇØ ³õÀ¸¸é D3D ¹öÀü¿¡µµ ¿µÇâÀ» ¹ÞÁö ¾Ê°í ¿Ïº®ÇÏ°Ô 3D·Î 2D¸¦ ±¸Çö Çϴµ¥ Àǹ̰¡ ÀÖ½À´Ï´Ù.
3D´Â Á¤Á¡ÀÌ ÀÖ¾î¾ß Àå¸éÀ» ¿¬ÃâÇÒ ¼ö ÀÖÀ¸¸ç µû¶ó¼ 2Dµµ Á¤Á¡ÀÌ ÀÖ¾î¾ß ÇÕ´Ï´Ù. ÆÄÀÌÇÁ¶óÀÎÀÇ º¯È¯ °úÁ¤À» °ÅÄ¡Áö ¾Ê´Â
°¡Àå ÀûÇÕÇÑ ÇüÅ´ RHW(Reciprocal of Homogeneous W) ÇüÅ·ΠÁ¤Á¡À» ±¸¼ºÇÏ´Â
°ÍÀÔ´Ï´Ù. ÇÁ·Î±×·¥ÀÇ ÀÎÅÍÆäÀ̽º´Â D3D¿Í À¯»çÇÏ°Ô ±¸¼ºÇÏ´Â
°ÍÀÌ Áö±Ý±îÁö ¸¸µç ÇÁ·Î±×·¥°ú ȣȯ¼ºÀ» À¯Áö¿¡ µµ¿òÀÌ µË´Ï´Ù. ÀÌ·± ¾ÆÀ̵ð¾î¸¦ Á¾ÇÕÇØ¼ ÇÁ·Î±×·¥À» ÀÛ¼ºÇØ
º¾½Ã´Ù.
¸ÕÀú 2D SpriteÀÇ ÀÎÅÍÆäÀ̽º¿Í Sprite °´Ã¼¸¦ »ý¼ºÇÏ´Â ÇÔ¼ö ÀÔ´Ï´Ù.
interface ILcSprite // 2D Sprite Interface
{
virtual ~ILcSprite(){};
virtual INT Draw(void* pTx0, const RECT* pRcDrw=NULL
, const FLOAT* pvcPos=NULL, DWORD Color=0xFFFFFFFF)=0;
};
INT LcxCreateSprite(ILcSprite** pOut, void* pd3dDevice);
Sprite °´Ã¼¸¦ »ý¼ºÇÏ´Â LcxCreateSprite()
ÇÔ¼ö¿¡¼ °´Ã¼¿¡ ´ëÇÑ ¹ÝȯÀ» ÀμöÀÇ ¾ÕÂÊ¿¡ ³Ö¾ú½À´Ï´Ù.
CLcSprite Ŭ·¡½º´Â
ILcSprite¸¦ »ó¼Ó¹Þ¾Æ¼ ½ÇÁ¦·Î Draw() ÇÔ¼ö¸¦ ó¸®Çϴ Ŭ·¡½ºÀÔ´Ï´Ù.
class CLcSprite : public ILcSprite
¡¦
LPDIRECT3DDEVICE9 m_pDev;
LPDIRECT3DSTATEBLOCK9 m_pStCur; // Current State Block
LPDIRECT3DSTATEBLOCK9 m_pStSpt; // Sprite State Block
¡¦
INT Create(LPDIRECT3DDEVICE9 pDev);
virtual INT Draw(¡¦);
Sprite °´Ã¼¿¡ ÀÇÇØ µð¹ÙÀ̽ºÀÇ »óÅ °ªÀÌ º¯ÇÏÁö ¾Êµµ·Ï »óŸ¦
ÀúÀåÇϱâ À§Çؼ D3DÀÇ State Block °´Ã¼¸¦ °¡Áö°í
ÀÖ½À´Ï´Ù.
ÀÌ State Block °´Ã¼ »ý¼ºÀº D3D µð¹ÙÀ̽ºÀÇ BeginStateBlock()ÇÔ¼ö È£ÃâÀ» Çϸé¼
ÀúÀåÇÒ »óŸ¦ ¼³Á¤ÇÏ°í ¸¶Áö¸·¿¡ EndStateBlock() ÇÔ¼ö¿¡¼ °´Ã¼¸¦ »ý¼ºÇÕ´Ï´Ù.
m_pDev->BeginStateBlock();
m_pDev->SetRenderState( D3DRS_FOGENABLE, FALSE );
m_pDev->SetRenderState( D3DRS_LIGHTING, FALSE );
¡¦
m_pDev->EndStateBlock(&m_pStSpt);
»óÅ ¼³Á¤ÀÌ ±æ¾îÁú ¶§ À¯¿ëÇÕ´Ï´Ù. ÀÌ State Blockµµ ÇØÁ¦ÇÒ ¶§´Â Release() ÇÔ¼ö¸¦ ÀÌ¿ëÇÕ´Ï´Ù.
Draw() ÇÔ¼ö´Â ¿øº» À̹ÌÁöÀÇ Å©±â¿Í ȸ鿡 ±×¸®°Ô µÉ À̹ÌÁö
¿µ¿ª, ȸé ÁÂÇ¥, »ö»óÀ» ÀÌ¿ëÇØ¼ 4°³ÀÇ Á¤Á¡À» ¿Ï¼ºÇϰí Ãâ·ÂÇÏ´Â °ÍÀÔ´Ï´Ù. ÅØ½ºÃ³ ¼Çǽº¿¡¼ ³Êºñ¿Í
³ôÀ̸¦ °¡Á®¿Ã ¼ö ÀÖ°í ÀÌ¿Í ÇÔ²² ȸ鿡 Ãâ·ÂÇÒ À̹ÌÁöÀÇ ¿µ¿ªÀ» ÀÌ¿ëÇØ¼ ÅØ½ºÃ³ÀÇ UVÁÂÇ¥¸¦ °è»êÇÕ´Ï´Ù.
INT CLcSprite::Draw(¡¦, const RECT* pRcImg, const RECT* pRcDrw, const FLOAT* pvcPos, ¡¦)
¡¦
// ¼ÇǽºÀÇ Width, Height¸¦ °¡Á®¿Â´Ù.
D3DSURFACE_DESC dsc;
pTex0->GetLevelDesc(0, &dsc);
FLOAT fImgW = FLOAT(dsc.Width); // Width of Surface
FLOAT fImgH = FLOAT(dsc.Height); // Height of Surface
// Draw Region Width, Height
if(pRcDrw)
{
fDrwL
= FLOAT(pRcDrw->left);
fDrwT
= FLOAT(pRcDrw->top);
fDrwW
= FLOAT(pRcDrw->right
- pRcDrw->left);
fDrwH
= FLOAT(pRcDrw->bottom-
pRcDrw->top );
}
// Setup UV
uv0.x
= (fDrwL + 0)/fImgW;
uv1.x
= (fDrwL + fDrwW)/fImgW;
uv0.y
= (fDrwT + 0)/fImgH;
uv1.y
= (fDrwT + fDrwH)/fImgH;
// Setup Vertices
struct TVtxRHWUV1
{
FLOAT p[4];
DWORD d;
FLOAT u, v;
}
pVtx[4] =
{
{pos.x
+ 0, pos.y + 0, 0, 1, dColor, uv0.x,
uv0.y},
{pos.x
+ fDrwW, pos.y + 0, 0, 1, dColor,
uv1.x, uv0.y},
{pos.x
+ fDrwW, pos.y + fDrwH, 0, 1, dColor, uv1.x, uv1.y},
{pos.x
+ 0, pos.y + fDrwH, 0, 1, dColor, uv0.x, uv1.y},
};
// Rendering 2D
m_pStCur->Capture();
m_pStSpt->Apply();
m_pDev->SetTexture(0, pTex0);
m_pDev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
m_pDev->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, pVtx, sizeof(TVtxRHWUV1) );
m_pDev->SetTexture(0, NULL);
m_pStCur->Apply();
½ºÇÁ¶óÀÌÆ® °´Ã¼´Â ¸Å¹ø Á¤Á¡À» ¼³Á¤ÇØ¾ß ÇϹǷΠUser Memory
Pointer¸¦ »ç¿ëÇÏ´Â °ÍÀÌ Æí¸®ÇÕ´Ï´Ù.
Àüü ÄÚµå´Â daux09_2d_sprite01.zip
Âü°í Çϰí À̸¦ ½ÇÇàÇÏ¸é ´ÙÀ½°ú °°ÀÌ ID3DXSprite °´Ã¼¿Í ºñ±³ÇÑ È¸éÀÌ Ãâ·ÂµË´Ï´Ù.

<RHW Sprite: daux09_2d_sprite01.zip>
±×¸²ÀÇ ÀÛÀº ÀÔÀÚÀÇ ºÓÀº »ö µ¿±×¶ó¹Ì¸¦ º¸¸é UV°¡ ¾È ¸Â´Â °ÍÀÌ
º¸ÀÔ´Ï´Ù. À̰ÍÀº ÅØ½ºÃ³¸¦ ¸¸µé ¶§ ÇÊÅ͸µÀÌ ¼³Á¤µÇ¾ú±â ¶§¹®ÀÔ´Ï´Ù. ¶ÇÇÑ
ºÒÅõ¸í ÅØ½ºÃ³¿¡ ´ëÇÑ Ä®¶ó Ű(Color Key)°¡ ¼³Á¤ÀÌ ¾È µÇ¾î ÀÖ¾î¼ °ËÁ¤»ö ¹è°æ »ö»óÀÌ ±×´ë·Î
Ãâ·ÂµÇ°í ÀÖÀ½À» º¼ ¼ö ÀÖ½À´Ï´Ù. ÀÌ·± ¹®Á¦µéÀ» »ý°¢ÇßÀ» ¶§ Áö±Ý±îÁö Àß »ç¿ëÇϰí ÀÖ¾ú´ø IDirect3DTexture9 °´Ã¼
ÁÖ¼Ò¿Í D3DXIMAGE_INFO ±¸Á¶Ã¼
º¯¼ö¸¦ Wrapping ÇØ¼ »ç¿ëÇÒ ¼ö ÀÖ´Â ÀÎÅÍÆäÀ̽º°¡ ÇÊ¿äÇÏ°Ô µË´Ï´Ù.
´ÙÀ½°ú °°ÀÌ °£´ÜÇÑ ±¸Á¶Ã¼·Î ¸¸µé¾î¼ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.
struct LcTexture
{
D3DXIMAGE_INFO pInf;
LPDIRECT3DTEXTURE9 pTex;
};
ÇÑ ¹ø ÇØ ³õÀ¸¸é °è¼Ó ¾µ ¼ö ÀÖÀ¸´Ï ÀÌ¿ÕÀÌ¸é ´ÙÀ½°ú °°ÀÌ ÀÛ¼ºÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù. ¸ÕÀú ÀÎÅÍÆäÀ̽º¿Í »ý¼º ÇÔ¼ö¸¦ ÀÌÀüÀÇ Sprite¿Í ºñ½ÁÇÏ°Ô ¸¸µì´Ï´Ù. ILcTexture »ý¼º ÇÔ¼ö¿¡´Â ÇÊÅ͸µ, Ä®¶ó ۸¦ Àü´ÞÇÒ ¼ö
ÀÖ´Â Àμö¸¦ Ãß°¡ÇÕ´Ï´Ù.
interface ILcTexture
{
virtual ~ILcTexture(){};
virtual void* GetTexture()=0; // LPDIRECT3DTEXTURE9
virtual INT GetImgW()=0; // Image Width
virtual INT GetImgH()=0; // Image Height
virtual INT GetImgD()=0; // Image Depth
};
INT LcxCreateTextureFromFile(ILcTexture** pOut, void* pd3dDevice
, char* sFile, DWORD dFilter=-1, DWORD dColor=0x00FFFFFF);
ÀÎÅÍÆäÀ̽º ILcTexture¸¦ ±¸ÇöÇÒ Å¬·¡½º CLcTexture¸¦ ´ÙÀ½°ú °°ÀÌ ÀÛ¼ºÇÕ´Ï´Ù.
class CLcTexture : public ILcTexture
¡¦
LPDIRECT3DTEXTURE9 m_pTex;
D3DXIMAGE_INFO m_pInf;
¡¦
INT Create(LPDIRECT3DDEVICE9 pDev, char* sFile
, DWORD dFilter=-1, DWORD dColorKey=0x00FFFFFF);
CLcTexture::Create() ÇÔ¼ö´Â D3DXCreateTextureFromFileEx() ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼ ÅØ½ºÃ³¿Í ¿øº» À̹ÌÁö Á¤º¸¸¦ ÀúÀåÇÕ´Ï´Ù. ÇÊÅͰ¡ -1À̸é MipLevels¸¦
ÃÖ´ë·Î ¼³Á¤ÇÏ°í ±×·¸Áö ¾ÊÀº °æ¿ì¿¡´Â 1·Î ¼³Á¤Çؼ 2Dȯ°æ¿¡¼
»ç¿ëµÇÁö ¾Ê´Â Sub Texture¸¦ ¾È ¸¸µì´Ï´Ù.
INT CLcTexture::Create(¡¦)
¡¦
UINT MipLevels = (dFilter==-1? -1 : 1);
D3DXCreateTextureFromFileEx(pDev, sFile
,
D3DX_DEFAULT, D3DX_DEFAULT
, MipLevels, 0
,
D3DFMT_UNKNOWN, D3DPOOL_MANAGED
, dFilter, dFilter
, dColorKey, &m_pInf, NULL, &m_pTex);
daux09_2d_sprite02.zip¸¦
½ÇÇà ÇÏ¸é ´ÙÀ½°ú °°ÀÌ Lc, DX ¸ðµÎ ¿øÇÏ´Â ´ë·Î Ãâ·ÂÇϰí ÀÖ½À´Ï´Ù.

<RHW Sprite: daux09_2d_sprite02.zip>
3.9.2 ȸÀü º¯È¯
2D ȸÀüÀ» °áÁ¤ÇÏ´Â °ÍÀÌ ½¬¿ì¸é¼µµ ¾î·Æ½À´Ï´Ù. ±×°ÍÀº SpriteÀÇ È°¿ë¿¡ µû¶ó ´Þ¶óÁý´Ï´Ù. ¸¸¾à ºôº¸µå È¿°ú(Billboard Effect)°ú °°Àº 3D¿¡¼ 2Â÷¿ø Æò¸éÀ» À§ÇÑ °ÍÀ̶ó¸é SpriteÀÇ È¸ÀüÀº 3D º¯È¯ °úÁ¤°ú µ¿ÀÏÇØ¾ß ÇÕ´Ï´Ù. ±×·¸Áö ¾Ê°í ȸ鿡¸¸ ¸ÂÃá´Ù¸é 2Â÷¿ø ȸÀü¸¸ °í·ÁÇÏ¸é µË´Ï´Ù. ¿©±â¼´Â ȸéÀ» ±âÁØÀ¸·Î ȸÀüÀ» Àû¿ëÇϰڽÀ´Ï´Ù.
ȸÀü °¢µµ(Radian)¸¦ ¥è·Î Çϸé ȸÀü Àü ÁÂÇ¥¸¦ (x, y)¶ó Çϰí ȸÀü ÈÄ ÁÂÇ¥¸¦ (x', y') À§Ä¡ º¯È¯Àº ´ÙÀ½°ú
°°ÀÌ µË´Ï´Ù.
|
x' = x * cos¥è
- y * sin¥è
y' = x * sin¥è
+ y * cos¥è
<¿À¸¥¼Õ ÁÂÇ¥°è>
|
x' = x * cos¥è + y * sin¥è
y' = -x * sin¥è
+ y * cos¥è
<¿Þ¼Õ ÁÂÇ¥°è>
|
¸¸¾à ȸÀü Á᫐ ÃàÀÌ ÀÖ´Ù¸é À§Ä¡¸¦ ÀÌ Áß½ÉÃุŠÀ̵¿ÇÏ°í ³ª¼ ȸÀüÀ» Àû¿ëÇÑ ´ÙÀ½ ´Ù½Ã ¿ø·¡ÀÇ À§Ä¡·Î ¿Í¾ß
ÇÕ´Ï´Ù.
¥Äx = x- rot x, ¥Äy
= x- rot y
¥Äx' = ¥Äx * cos¥è - ¥Äy * sin¥è
¥Äy' = ¥Äx * sin¥è + ¥Äy * cos¥è
|
x' = ¥Äx' + rot
x
y' = ¥Äy' + rot
y
|
¶Ç´Â (x' y') = rot(x, y) + (¥Äx', ¥Äy')
|
daux09_2d_sprite03.zip
ÀÇ CLcSprite::Draw()´Â ÀÌ·¯ÇÑ È¸ÀüÀ» Àû¿ëÇÑ ÇÔ¼ö·Î ÄÚµåÀÇ Áß°£¿¡ ȸÀü Áß½É
ÃàÀÌ ÁÖ¾îÁö¸é À̸¦ ±¸ÇöÇϰí ÀÖ½À´Ï´Ù. ȸÀüÀº ¹Ý ½Ã°è¹æÇâÀ¸·Î ȸÀüÇϵµ·Ï Çϱâ À§Çؼ ¿Þ¼Õ ÁÂÇ¥°è °ø½ÄÀ»
Àû¿ëÇß½À´Ï´Ù.
if(pvcRot)
{
D3DXVECTOR2 vcR = D3DXVECTOR2(pvcRot[0], pvcRot[1]);
D3DXVECTOR2 d(0,0);
FLOAT fCos = cosf(fTheta);
FLOAT fSin = sinf(fTheta);
for(INT i=0; i<4; ++i)
{
D3DXVECTOR2 vcT = pos[i]
- vcR;
d.x
= vcT.x * fCos + vcT.y * fSin;
d.y
=-vcT.x * fSin + vcT.y * fCos;
pos[i]
= vcR + d;
}
}
°¢µµ´Â D3D´Â Radian [0,
2¥ð]À» »ç¿ëÇϳª Degree [0, 360] °¡
¸¹ÀÌ »ç¿ëµÇ¹Ç·Î ÀÔ·Â °ªÀº Degree·Î ÇÏ°í ³»ºÎ¿¡¼ RadianÀ¸·Î
ó¸®Çϵµ·Ï ÇÕ´Ï´Ù.
´ÙÀ½ ±×¸²Àº daux09_2d_sprite03.zip
½ÇÇà °á°úÀÔ´Ï´Ù.

<ȸÀüÀÌ Àû¿ëµÈ
2D Sprite: daux09_2d_sprite03.zip>
3.9.3 Å©±â º¯È¯
Å©±â º¯È¯µµ ȸÀüó·³ È¸é ±âÁØÀ¸·Î ÀÛ¼ºÇÕ´Ï´Ù. ¸¸¾à Å©±â¿¡ À½¼ö°¡
¿À¸é Á¿ì, ¶Ç´Â »óÇϸ¦ ¹Ý´ë·Î µÚ ¤¾î ÁÝ´Ï´Ù. ¹ÝÀüÀÌ
ÀÖÀ¸¸é »ï°¢ÇüÀ» ±×¸®´Â Á¤Á¡ÀÇ ¼ø¼°¡ CW¿¡¼ CCW·Î ¹Ù²ò´Ï´Ù. µû¶ó¼ Culling Mode¸¦
NoneÀ¸·Î ÇÏ´Â °ÍÀÌ ÁÁ½À´Ï´Ù.
m_pDev->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE);
ID3DXSprite´Â Å©±â º¯È¯ °ªÀ» À½¼ö·Î ¼³Á¤Çϸé À§Ä¡¸¦ º¸Á¤Çؾß
ÇÕ´Ï´Ù. À̰ÍÀº ºÒÆíÇϹǷΠ¹ÝÀüÀÌ À־ ½ÃÀÛ À§Ä¡¸¦ º¯µ¿½ÃŰÁö ¾Êµµ·Ï Äڵ忡¼ Á¤Á¡ÀÇ À§Ä¡¿¡ ´ëÇÑ
°è»êÀ» ´ÙÀ½°ú °°ÀÌ ÀÛ¼ºÇÕ´Ï´Ù.
FLOAT fSclX = pvcScl[0]; FLOAT fSclY =
pvcScl[1];
if(fSclX<0)
¡¦
pos[1].x = pos[0].x;
pos[2].x = pos[1].x;
pos[0].x = pos[1].x - fDrwW * fSclX;
pos[3].x = pos[0].x;
¡¦
if(fSclY<0)
¡¦
pos[3].y = pos[0].y;
pos[2].y = pos[3].y;
pos[0].y = pos[3].y - fDrwH * fSclY;
pos[1].y = pos[0].y;
Àüü ÄÚµå´Â daux09_2d_sprite04.zipÀ»
Âü°í Çϱâ¹Ù¶ø´Ï´Ù.

<Å©±â º¯È¯: daux09_2d_sprite04.zip>
3.9.4 ¾ËÆÄ ¸Ê(Alpha Map)
Sprite¿¡ ±â´ÉÀ» ³Ö±â ½ÃÀÛÇϸé Çѵµ ³¡µµ ¾øÀ» Á¤µµ·Î ¹«±Ã¹«Áø
ÇÕ´Ï´Ù. ±×·¡µµ ÇѰ¡Áö ³Ö°í ½ÍÀº °ÍÀÌ ÀÖ´Ù¸é ¾ËÆÄ ¸ÊÀ» ³Ö´Â °ÍÀÔ´Ï´Ù. ÀÌ ±â´ÉÀº ´ÙÀ½°ú °°ÀÌ ¿øº» À̹ÌÁö¿¡¼ ƯÁ¤ÇÑ ºÎºÐÀ» À߶󳻰ųª ¾Æ´Ï¸é ¹ÝÅõ¸íÀ» ó¸®ÇÏ´Â °ÍÀÔ´Ï´Ù.

<2D Sprite ¾ËÆÄ ¸Ê¿¡ ÀÇÇÑ Æ¯Á¤ ¿µ¿ªÀÇ Ãâ·Â>
À̰ÍÀº 3DÀÇ ´ÙÁß ÅØ½ºÃ³(Multi-Texturing)À»
Àû¿ëÇÏ¸é ¾ÆÁÖ ½±°Ô ÇØ°áÀÌ µË´Ï´Ù. ´ÙÀ½°ú °°ÀÌ ´ÙÁß ÅØ½ºÃ³ ó¸® ´Ü°è 1¿¡¼´Â ´Ü°è 0ÀÇ °á°ú °ªÀ»
Current·Î ÀúÀåÇÏ°í »ö»óÀº ±×´ë·Î Ãâ·ÂÇÕ´Ï´Ù.
m_pDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
m_pDev->SetTextureStageState( 1, D3DTSS_COLOROP,
D3DTOP_SELECTARG1);
¾ËÆÄ¸¸ Current°ª°ú
°ö¼ÀÀ» Çϰí Ãâ·ÂÇÕ´Ï´Ù.
m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );
m_pDev->SetTextureStageState( 1, D3DTSS_ALPHAOP,
D3DTOP_SELECTARG2);
ÅØ½ºÃ³ ÁÂÇ¥´Â ´Ü°è 0¿¡¼
»ç¿ëÇÑ ÁÂÇ¥¸¦ ±×´ë·Î »ç¿ëÇÕ´Ï´Ù. ÀÌ ºÎºÐÀº ÀÌ ÈÄ SpriteÀÇ
±â´É º¸°¿¡¼ ÇÊ¿äÇÏ´Ù¸é ¼öÁ¤ÇÏ¸é µË´Ï´Ù.
m_pDev->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
¹°·Ð Draw() ÇÔ¼öµµ ¼öÁ¤ÇØ¾ß ÇÕ´Ï´Ù. ÀÌÀüÀÇ Draw() ÇÔ¼ö¿Í ±¸ºÐÇϱâ À§Çؼ »õ·Î¿î DrawEx() ÇÔ¼ö¸¦ ¸¸µå´Â °ÍÀÌ ÁÁ½À´Ï´Ù. ±×¸®°í ÀÌÀü Draw()ÇÔ¼ö´Â DrawEx()¸¦ È£ÃâÇØ¼ »ç¿ëÇϵµ·Ï ÇÕ´Ï´Ù.
INT CLcSprite::Draw(¡¦)
{
return DrawEx(pTx0, NULL, ¡¦);
}
daux09_2d_sprite05.zip´Â
¾ËÆÄ ¸ÊÀ» Àû¿ëÇÑ Sprite ¿¹Á¦ÀÔ´Ï´Ù. ½ÇÇàÇÏ¸é ´ÙÀ½°ú
°°Àº ȸéÀ» º¼ ¼ö ÀÖ½À´Ï´Ù.

<¾ËÆÄ ¸ÊÀÌ ÀÖ´Â 2D
Sprite: daux09_2d_sprite05.zip>